--- Begin Message ---
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",
OpenPGP_signature.asc
Description: OpenPGP digital signature
--- End Message ---