Source: stgit
Version: 2.6.1-1
Severity: important
Tags: patch
User: [email protected]
Usertags: gix-0.86
X-Debbugs-Cc: [email protected]

Dear maintainer,

I am preparing a rust-gix transition to 0.86, which will likely be uploaded in 
the coming days.

stgit currently depends on gix 0.83, so it needs a dependency bump and port.

I have attached a debdiff fixing this.

Best regards,
Simon Quigley
[email protected]
diff -Nru stgit-2.6.1/debian/changelog stgit-2.6.1/debian/changelog
--- stgit-2.6.1/debian/changelog        2026-07-20 12:53:23.000000000 -0500
+++ stgit-2.6.1/debian/changelog        2026-08-20 11:57:19.000000000 -0500
@@ -1,3 +1,10 @@
+stgit (2.6.1-1.1) UNRELEASED; urgency=medium
+
+  * Non-maintainer upload.
+  * Port to gix 0.86 via gix-0.86.patch, remove gix 0.83 patch.
+
+ -- Simon Quigley <[email protected]>  Thu, 20 Aug 2026 11:57:19 -0500
+
 stgit (2.6.1-1) unstable; urgency=medium
 
   * New upstream release.
diff -Nru stgit-2.6.1/debian/control stgit-2.6.1/debian/control
--- stgit-2.6.1/debian/control  2026-07-20 12:53:23.000000000 -0500
+++ stgit-2.6.1/debian/control  2026-08-20 11:57:19.000000000 -0500
@@ -24,7 +24,7 @@
  librust-curl-dev,
  librust-encoding-rs-dev,
  librust-flate2-dev,
- librust-gix-dev (>= 0.83),
+ librust-gix-dev (>= 0.86),
  librust-indexmap-dev,
  librust-is-terminal-dev,
  librust-jiff-dev (>= 0.2.1),
diff -Nru stgit-2.6.1/debian/patches/gix-0.86.patch 
stgit-2.6.1/debian/patches/gix-0.86.patch
--- stgit-2.6.1/debian/patches/gix-0.86.patch   1969-12-31 18:00:00.000000000 
-0600
+++ stgit-2.6.1/debian/patches/gix-0.86.patch   2026-08-20 11:57:19.000000000 
-0500
@@ -0,0 +1,429 @@
+Description: Port to gix 0.86
+ Bump the gix crate from 0.84 to 0.86 and update call sites for the
+ gix-config 0.59 API that gix 0.86 re-exports. A version-only bump does
+ not compile.
+ .
+ gix::config::File no longer takes a lifetime, so File<'static> and
+ CommitOptions<'_> lose that parameter. Snapshot::string() now returns
+ Option<BString> rather than Option<Cow<BStr>>, so CommitOptions stores
+ BString and for_label() takes s.as_ref().
+ .
+ Snapshot::string_by and boolean_by are gone. Look up dotted keys with
+ string() / boolean() / try_boolean(), which stgit already uses for
+ keys such as branch.{name}.remote. try_boolean() is Result<Option<bool>>
+ rather than Option<Result<bool>>, so drop the extra transpose() on the
+ autostash lookups.
+ .
+ SectionRef::num_values() moved to BodyRef (section.body().num_values()).
+ value_names() yields String rather than BStr, so skip to_str() and pass
+ the name through to value(). File::rename_section's new subsection is
+ IntoBStringOpt (Option<BString>), not Option<Cow<BStr>>.
+ .
+ Snapshot::trusted_path returns Result<Option<PathBuf>, _> instead of an
+ Option that needs transpose(). Hook path construction can use PathBuf
+ directly; editor lookup maps PathBuf with into_os_string().
+Author: Simon Quigley <[email protected]>
+Origin: vendor
+Forwarded: no
+Last-Update: 2026-08-20
+---
+This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
+--- a/Cargo.toml
++++ b/Cargo.toml
+@@ -43,7 +43,7 @@ clap = { version = "~4.6", default-featu
+ ctrlc = "3.4"
+ encoding_rs = "0.8"
+ flate2 = "1"
+-gix = { version = "0.84", default-features = false, features = [
++gix = { version = "0.86", default-features = false, features = [
+   "command",
+   "revision",
+   "sha1",
+--- a/src/alias.rs
++++ b/src/alias.rs
+@@ -100,15 +100,9 @@ where
+                 .filter(|section| section.header().subsection_name() == 
Some("alias".into()))
+             {
+                 for value_name in section.value_names() {
+-                    let name = value_name.to_str().map_err(|_| {
+-                        anyhow!(
+-                            "alias name `{}` in {} is not valid UTF-8",
+-                            value_name.to_str_lossy(),
+-                            config_source_str(section.meta().source),
+-                        )
+-                    })?;
++                    let name = value_name.as_str();
+                     if let Some(value) = section
+-                        .value(value_name)
++                        .value(name)
+                         .and_then(|v| (!v.is_empty()).then_some(v))
+                     {
+                         if !exclude(name) {
+--- a/src/cmd/branch/list.rs
++++ b/src/cmd/branch/list.rs
+@@ -101,7 +101,7 @@ pub(super) fn dispatch(repo: &gix::Repos
+         stdout.set_color(&color_spec)?;
+ 
+         let description = config
+-            .string_by("branch", Some(branchname.into()), "description")
++            .string(format!("branch.{branchname}.description").as_str())
+             .unwrap_or_default();
+         if description.is_empty() {
+             writeln!(stdout)?;
+--- a/src/cmd/branch/mod.rs
++++ b/src/cmd/branch/mod.rs
+@@ -151,7 +151,7 @@ fn set_description(
+             value.delete();
+         }
+         if let Ok(section) = local_config_file.section("branch", 
Some(branchname.into())) {
+-            if section.num_values() == 0 {
++            if section.body().num_values() == 0 {
+                 local_config_file.remove_section_by_id(section.id());
+             }
+         }
+@@ -171,11 +171,7 @@ fn set_description(
+ 
+ fn get_stgit_parent(config: &gix::config::Snapshot, branchname: 
&PartialRefName) -> Option<String> {
+     config
+-        .string_by(
+-            "branch",
+-            Some(format!("{branchname}.stgit").as_str().into()),
+-            "parentbranch",
+-        )
++        .string(format!("branch.{branchname}.stgit.parentbranch").as_str())
+         .and_then(|bs| bs.to_str().ok().map(str::to_string))
+ }
+ 
+@@ -202,7 +198,7 @@ fn set_stgit_parent(
+             value.delete();
+         }
+         if let Ok(section) = local_config_file.section("branch", 
Some(subsection.as_str().into())) {
+-            if section.num_values() == 0 {
++            if section.body().num_values() == 0 {
+                 local_config_file.remove_section_by_id(section.id());
+             }
+         }
+--- a/src/cmd/branch/rename.rs
++++ b/src/cmd/branch/rename.rs
+@@ -84,8 +84,7 @@ pub(super) fn dispatch(repo: &gix::Repos
+             .section("branch", Some(old_section_name))
+             .is_ok()
+         {
+-            let new_section_name =
+-                
std::borrow::Cow::Owned(BString::from(format!("{new_branchname}.stgit")));
++            let new_section_name = 
BString::from(format!("{new_branchname}.stgit"));
+             local_config_file
+                 .rename_section(
+                     "branch",
+--- a/src/cmd/pick.rs
++++ b/src/cmd/pick.rs
+@@ -297,7 +297,7 @@ fn pick_picks(
+                  {body}"
+             )
+         } else if matches.get_flag("expose") {
+-            let expose_format = config.string_by("stgit", 
Some("pick".into()), "expose-format");
++            let expose_format = config.string("stgit.pick.expose-format");
+             let expose_format = expose_format
+                 .as_ref()
+                 .map(|bs| bs.to_str().ok())
+--- a/src/cmd/pull.rs
++++ b/src/cmd/pull.rs
+@@ -101,11 +101,7 @@ fn run(matches: &ArgMatches) -> Result<(
+     let config = repo.config_snapshot();
+     let policy = PullPolicy::from_str(
+         &config
+-            .string_by(
+-                "branch",
+-                Some(format!("{branch_name}.stgit").as_str().into()),
+-                "pull-policy",
+-            )
++            
.string(format!("branch.{branch_name}.stgit.pull-policy").as_str())
+             .or_else(|| config.string("stgit.pull-policy"))
+             .map(|bs| bs.to_str_lossy().to_string())
+             .unwrap_or_else(|| "pull".to_string()),
+@@ -125,7 +121,7 @@ fn run(matches: &ArgMatches) -> Result<(
+         }
+         PullPolicy::Pull | PullPolicy::FetchRebase => {
+             parent_remote = config
+-                .string_by("branch", Some(branch_name.as_str().into()), 
"remote")
++                .string(format!("branch.{branch_name}.remote").as_str())
+                 .and_then(|bs| bs.to_str().map(str::to_string).ok());
+             let remote_name = matches
+                 .get_one::<String>("repository")
+@@ -163,11 +159,7 @@ fn run(matches: &ArgMatches) -> Result<(
+     let rebase_target = match policy {
+         PullPolicy::Pull => {
+             let pull_cmd = config
+-                .string_by(
+-                    "branch",
+-                    Some(format!("{branch_name}.stgit").as_str().into()),
+-                    "pullcmd",
+-                )
++                
.string(format!("branch.{branch_name}.stgit.pullcmd").as_str())
+                 .or_else(|| config.string("stgit.pullcmd"))
+                 .and_then(|bs| bs.to_str().map(str::to_string).ok())
+                 .unwrap_or_else(|| "git pull".to_string());
+@@ -183,11 +175,7 @@ fn run(matches: &ArgMatches) -> Result<(
+         }
+         PullPolicy::FetchRebase => {
+             let fetch_cmd = config
+-                .string_by(
+-                    "branch",
+-                    Some(format!("{branch_name}.stgit").as_str().into()),
+-                    "fetchcmd",
+-                )
++                
.string(format!("branch.{branch_name}.stgit.fetchcmd").as_str())
+                 .or_else(|| config.string("stgit.fetchcmd"))
+                 .and_then(|bs| bs.to_str().map(str::to_string).ok())
+                 .unwrap_or_else(|| "git fetch".to_string());
+@@ -203,11 +191,8 @@ fn run(matches: &ArgMatches) -> Result<(
+             Some(target_id)
+         }
+         PullPolicy::Rebase => {
+-            let parent_branch_name = config.string_by(
+-                "branch",
+-                Some(format!("{branch_name}.stgit").as_str().into()),
+-                "parentbranch",
+-            );
++            let parent_branch_name =
++                
config.string(format!("branch.{branch_name}.stgit.parentbranch").as_str());
+             let parent_branch_name = 
parent_branch_name.as_ref().and_then(|bs| bs.to_str().ok());
+ 
+             let parent_object = if let Some(name) = parent_branch_name {
+@@ -227,11 +212,7 @@ fn run(matches: &ArgMatches) -> Result<(
+ 
+     if let Some(rebase_target) = rebase_target {
+         let rebase_cmd = config
+-            .string_by(
+-                "branch",
+-                Some(format!("{branch_name}.stgit").as_str().into()),
+-                "rebasecmd",
+-            )
++            .string(format!("branch.{branch_name}.stgit.rebasecmd").as_str())
+             .or_else(|| config.string("stgit.rebasecmd"))
+             .and_then(|bs| bs.to_str().map(str::to_string).ok())
+             .unwrap_or_else(|| "git reset --hard".to_string());
+--- a/src/cmd/rebase.rs
++++ b/src/cmd/rebase.rs
+@@ -175,12 +175,7 @@ fn run(matches: &ArgMatches) -> Result<(
+         true
+     } else {
+         config
+-            .boolean_by(
+-                "branch",
+-                Some(format!("{branch_name}.stgit").as_str().into()),
+-                "autostash",
+-            )
+-            .transpose()
++            
.try_boolean(format!("branch.{branch_name}.stgit.autostash").as_str())
+             .unwrap_or_else(|e| {
+                 crate::print_warning_message(
+                     matches,
+@@ -189,16 +184,13 @@ fn run(matches: &ArgMatches) -> Result<(
+                 Some(false)
+             })
+             .or_else(|| {
+-                config
+-                    .try_boolean("stgit.autostash")
+-                    .transpose()
+-                    .unwrap_or_else(|e| {
+-                        crate::print_warning_message(
+-                            matches,
+-                            &format!("Invalid config value `stgit.autostash`: 
{e}"),
+-                        );
+-                        Some(false)
+-                    })
++                config.try_boolean("stgit.autostash").unwrap_or_else(|e| {
++                    crate::print_warning_message(
++                        matches,
++                        &format!("Invalid config value `stgit.autostash`: 
{e}"),
++                    );
++                    Some(false)
++                })
+             })
+             .unwrap_or(false)
+     };
+@@ -225,11 +217,7 @@ fn run(matches: &ArgMatches) -> Result<(
+         .execute("rebase (pop)")?;
+ 
+     let rebase_cmd = config
+-        .string_by(
+-            "branch",
+-            Some(format!("{branch_name}.stgit").as_str().into()),
+-            "rebasecmd",
+-        )
++        .string(format!("branch.{branch_name}.stgit.rebasecmd").as_str())
+         .or_else(|| config.string("stgit.rebasecmd"))
+         .and_then(|bs| bs.to_str().map(str::to_string).ok())
+         .unwrap_or_else(|| "git reset --hard".to_string());
+--- a/src/ext/repository.rs
++++ b/src/ext/repository.rs
+@@ -1,9 +1,7 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+ 
+-use std::borrow::Cow;
+-
+ use anyhow::{anyhow, Result};
+-use bstr::{BStr, ByteSlice};
++use bstr::{BString, ByteSlice};
+ 
+ use crate::{
+     stupid::Stupid,
+@@ -42,7 +40,7 @@ pub(crate) trait RepositoryExtended {
+ 
+     /// Get repository-local config file which can be used to change local
+     /// configuration.
+-    fn local_config_file(&self) -> Result<gix::config::File<'static>>;
++    fn local_config_file(&self) -> Result<gix::config::File>;
+ 
+     /// Write repository-local config file.
+     fn write_local_config(&self, file: gix::config::File) -> Result<()>;
+@@ -73,7 +71,7 @@ pub(crate) trait RepositoryExtended {
+         message: &Message,
+         tree_id: gix::ObjectId,
+         parent_ids: impl IntoIterator<Item = gix::ObjectId>,
+-        options: &CommitOptions<'_>,
++        options: &CommitOptions,
+     ) -> Result<gix::ObjectId>;
+ 
+     /// [`gix::Repository::rev_parse_single()`] with StGit-specific error 
mapping.
+@@ -88,9 +86,9 @@ pub(crate) trait RepositoryExtended {
+ }
+ 
+ /// Options for creating a git commit object.
+-pub(crate) struct CommitOptions<'a> {
++pub(crate) struct CommitOptions {
+     /// The target encoding for the commit message.
+-    pub(crate) commit_encoding: Option<Cow<'a, BStr>>,
++    pub(crate) commit_encoding: Option<BString>,
+ 
+     /// Determine whether the commit object should be signed with GPG.
+     pub(crate) gpgsign: bool,
+@@ -171,7 +169,7 @@ impl RepositoryExtended for gix::Reposit
+         }
+     }
+ 
+-    fn local_config_file(&self) -> Result<gix::config::File<'static>> {
++    fn local_config_file(&self) -> Result<gix::config::File> {
+         let source = gix::config::Source::Local;
+ 
+         let local_config_path = self.common_dir().join(
+@@ -233,11 +231,11 @@ impl RepositoryExtended for gix::Reposit
+         message: &Message,
+         tree_id: gix::ObjectId,
+         parent_ids: impl IntoIterator<Item = gix::ObjectId>,
+-        options: &CommitOptions<'_>,
++        options: &CommitOptions,
+     ) -> Result<gix::ObjectId> {
+         let commit_encoding = match &options.commit_encoding {
+             Some(s) => {
+-                let encoding = encoding_rs::Encoding::for_label(s)
++                let encoding = encoding_rs::Encoding::for_label(s.as_ref())
+                     .ok_or_else(|| anyhow!("unhandled i18n.commitEncoding 
`{s}`"))?;
+                 Some(encoding)
+             }
+--- a/src/hook.rs
++++ b/src/hook.rs
+@@ -3,7 +3,6 @@
+ //! Support for using git repository hooks.
+ 
+ use std::{
+-    borrow::Cow,
+     io::Write,
+     path::{Path, PathBuf},
+ };
+@@ -18,22 +17,21 @@ use crate::wrap::Message;
+ /// Returns None if the hook script is not found or is not executable.
+ fn get_hook_path(repo: &gix::Repository, hook_name: &str) -> 
Result<Option<PathBuf>> {
+     let config = repo.config_snapshot();
+-    let hooks_path =
+-        if let Some(core_hooks_path) = 
config.trusted_path("core.hookspath").transpose()? {
+-            if core_hooks_path.is_absolute() {
+-                core_hooks_path
+-            } else if repo.is_bare() {
+-                // The hooks path is relative to GIT_DIR in the case of a 
bare repo
+-                Cow::Owned(repo.common_dir().join(core_hooks_path))
+-            } else {
+-                // The hooks path is relative to the root of the working tree 
otherwise
+-                let work_dir = repo.workdir().expect("non-bare repo must have 
work dir");
+-                Cow::Owned(work_dir.join(core_hooks_path))
+-            }
++    let hooks_path = if let Some(core_hooks_path) = 
config.trusted_path("core.hookspath")? {
++        if core_hooks_path.is_absolute() {
++            core_hooks_path
++        } else if repo.is_bare() {
++            // The hooks path is relative to GIT_DIR in the case of a bare 
repo
++            repo.common_dir().join(core_hooks_path)
+         } else {
+-            // No core.hookspath, use default .git/hooks location
+-            Cow::Owned(repo.common_dir().join("hooks"))
+-        };
++            // The hooks path is relative to the root of the working tree 
otherwise
++            let work_dir = repo.workdir().expect("non-bare repo must have 
work dir");
++            work_dir.join(core_hooks_path)
++        }
++    } else {
++        // No core.hookspath, use default .git/hooks location
++        repo.common_dir().join("hooks")
++    };
+     let hook_path = hooks_path.join(hook_name);
+ 
+     let hook_meta = match std::fs::metadata(&hook_path) {
+--- a/src/patch/edit/interactive.rs
++++ b/src/patch/edit/interactive.rs
+@@ -135,15 +135,13 @@ fn get_editor(config: &gix::config::Snap
+     let editor = if let Some(editor) = std::env::var_os("GIT_EDITOR") {
+         editor
+     } else if let Some(editor) = config
+-        .trusted_path("stgit.editor")
+-        .transpose()?
+-        .map(|p| p.as_os_str().to_os_string())
++        .trusted_path("stgit.editor")?
++        .map(|p| p.into_os_string())
+     {
+         editor
+     } else if let Some(editor) = config
+-        .trusted_path("core.editor")
+-        .transpose()?
+-        .map(|p| p.as_os_str().to_os_string())
++        .trusted_path("core.editor")?
++        .map(|p| p.into_os_string())
+     {
+         editor
+     } else if let Some(editor) = std::env::var_os("VISUAL") {
+--- a/src/stack/stack.rs
++++ b/src/stack/stack.rs
+@@ -238,12 +238,7 @@ impl<'repo> Stack<'repo> {
+     /// Check whether the stack is marked as protected in the config.
+     pub(crate) fn is_protected(&self, config: &gix::config::Snapshot) -> bool 
{
+         config
+-            .boolean_by(
+-                "branch",
+-                Some(format!("{}.stgit", self.branch_name).as_str().into()),
+-                "protect",
+-            )
+-            .unwrap_or(Ok(false))
++            .boolean(format!("branch.{}.stgit.protect", 
self.branch_name).as_str())
+             .unwrap_or(false)
+     }
+ 
+@@ -271,7 +266,7 @@ impl<'repo> Stack<'repo> {
+             if let Ok(section) = local_config_file
+                 
.section_by_key(format!("{section}.{subsection}").as_bytes().as_bstr())
+             {
+-                if section.num_values() == 0 {
++                if section.body().num_values() == 0 {
+                     local_config_file.remove_section_by_id(section.id());
+                 }
+             }
+--- a/src/stack/upgrade.rs
++++ b/src/stack/upgrade.rs
+@@ -325,7 +325,7 @@ fn rm_stackformatversion(repo: &gix::Rep
+     if let Ok(section) =
+         
local_config_file.section_by_key(format!("{section}.{subsection}").as_bytes().as_bstr())
+     {
+-        if section.num_values() == 0 {
++        if section.body().num_values() == 0 {
+             local_config_file.remove_section_by_id(section.id());
+         }
+     }
diff -Nru stgit-2.6.1/debian/patches/series stgit-2.6.1/debian/patches/series
--- stgit-2.6.1/debian/patches/series   2026-07-20 12:53:23.000000000 -0500
+++ stgit-2.6.1/debian/patches/series   2026-08-20 11:57:19.000000000 -0500
@@ -2,4 +2,4 @@
 disable_interactive_test
 use_bzip2_crate
 use_winnow_0_7
-use_gix_0_83
+gix-0.86.patch
diff -Nru stgit-2.6.1/debian/patches/use_gix_0_83 
stgit-2.6.1/debian/patches/use_gix_0_83
--- stgit-2.6.1/debian/patches/use_gix_0_83     2026-07-20 12:53:23.000000000 
-0500
+++ stgit-2.6.1/debian/patches/use_gix_0_83     1969-12-31 18:00:00.000000000 
-0600
@@ -1,11 +0,0 @@
---- a/Cargo.toml
-+++ b/Cargo.toml
-@@ -43,7 +43,7 @@
- ctrlc = "3.4"
- encoding_rs = "0.8"
- flate2 = "1"
--gix = { version = "0.84", default-features = false, features = [
-+gix = { version = "0.83", default-features = false, features = [
-   "command",
-   "revision",
-   "sha1",

Attachment: OpenPGP_signature.asc
Description: OpenPGP digital signature

Reply via email to