Your message dated Fri, 18 Sep 2026 20:22:38 +0000
with message-id <[email protected]>
and subject line Bug#1148264: fixed in stgit 2.6.1-1.2
has caused the Debian Bug report #1148264,
regarding stgit: port to gix 0.87
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact [email protected]
immediately.)


-- 
1148264: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1148264
Debian Bug Tracking System
Contact [email protected] with problems
--- Begin Message ---
Source: stgit
Version: 2.6.1-1.1
Severity: important
Tags: patch
User: [email protected]
Usertags: gix-0.87
X-Debbugs-Cc: [email protected]

Dear maintainer,

I am preparing a rust-gix transition to 0.87, which will likely be uploaded 
soon.

stgit currently depends on gix 0.86. My patch was rejected upstream in favor of 
a 0.87 port, that needs to be cherry-picked with a small test fix.

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-08-24 09:43:17.000000000 -0500
+++ stgit-2.6.1/debian/changelog        2026-09-18 10:19:50.000000000 -0500
@@ -1,3 +1,12 @@
+stgit (2.6.1-1.2) unstable; urgency=medium
+
+  * Non-maintainer upload.
+  * Drop gix-0.86.patch in favor of a direct upstream cherry-pick in
+    gix-0.87.patch.
+  * Cherry-pick upstream fix to reject a lone "@" as a partial ref name.
+
+ -- Simon Quigley <[email protected]>  Fri, 18 Sep 2026 10:19:50 -0500
+
 stgit (2.6.1-1.1) unstable; urgency=medium
 
   * Non-maintainer upload (Closes: #1144970).
diff -Nru stgit-2.6.1/debian/control stgit-2.6.1/debian/control
--- stgit-2.6.1/debian/control  2026-08-24 09:43:17.000000000 -0500
+++ stgit-2.6.1/debian/control  2026-09-18 10:01:34.000000000 -0500
@@ -24,7 +24,7 @@
  librust-curl-dev,
  librust-encoding-rs-dev,
  librust-flate2-dev,
- librust-gix-dev (>= 0.86),
+ librust-gix-dev (>= 0.87),
  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   2026-08-24 09:43:17.000000000 
-0500
+++ stgit-2.6.1/debian/patches/gix-0.86.patch   1969-12-31 18:00:00.000000000 
-0600
@@ -1,430 +0,0 @@
-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
-Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1144970
-Forwarded: https://github.com/stacked-git/stgit/pull/648
-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/gix-0.87.patch 
stgit-2.6.1/debian/patches/gix-0.87.patch
--- stgit-2.6.1/debian/patches/gix-0.87.patch   1969-12-31 18:00:00.000000000 
-0600
+++ stgit-2.6.1/debian/patches/gix-0.87.patch   2026-09-18 10:01:21.000000000 
-0500
@@ -0,0 +1,474 @@
+Description: feat: update gix to 0.87.1 introducing git approxidates
+ Skip gix 0.86.0 and 0.87.0 because both use a version of gix-protocol
+ that depends on bisync, and every published bisync release has been
+ yanked. So neither gix 0.86.0 or 0.87.0 resolve at all. gix 0.87.1 drops
+ bisync.
+ . 
+ gix-date 0.16 reads relative dates the way git's approxidate does, so
+ StGit now accepts spellings it used to reject: "2 days 3 hours ago",
+ "one week ago", "last week", "3.days.ago", and a "@" before an epoch.
+ .
+ Relative dates are also anchored in the local zone rather than UTC. That
+ same leniency made the offset-appending retry in parse_time unsound: "a
+ long time ago" carries no offset, so the retry turned it into "a long
+ time ago-04:00", which parses as four seconds ago. Git accepts that
+ mangled string too, so the fault is appending an offset blind; only
+ inputs that look like a time of day are retried now.
+ .
+ The remaining changes are mechanical responses to gix interface changes.
+Author: Peter Grayson <[email protected]>
+Origin: upstream
+Bug: https://github.com/stacked-git/stgit/pull/648
+Applied-Upstream: 68ad69139ad69cb90bd1ea2f5c379dc342fa57a0
+Reviewed-by: Simon Quigley <[email protected]>
+Last-Update: 2026-09-18
+---
+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.87", 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/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());
+             }
+         }
+@@ -202,7 +202,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/rebase.rs
++++ b/src/cmd/rebase.rs
+@@ -180,7 +180,6 @@ fn run(matches: &ArgMatches) -> Result<(
+                 Some(format!("{branch_name}.stgit").as_str().into()),
+                 "autostash",
+             )
+-            .transpose()
+             .unwrap_or_else(|e| {
+                 crate::print_warning_message(
+                     matches,
+@@ -189,16 +188,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)
+     };
+--- 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)
+             }
+@@ -296,7 +294,7 @@ impl RepositoryExtended for gix::Reposit
+                 // is malformed" by looking for a typed NotFound frame 
anywhere in the
+                 // error tree underlying SingleError::Parse.
+                 if let SingleError::Parse(ref gix_err) = single_err {
+-                    let not_found = gix_err.sources().any(|src| {
++                    let not_found = gix_err.iter_errors().any(|src| {
+                         matches!(
+                             src.downcast_ref::<RefFindError>(),
+                             Some(RefFindError::NotFound { .. })
+--- a/src/ext/time.rs
++++ b/src/ext/time.rs
+@@ -19,29 +19,37 @@ pub(crate) trait TimeExtended {
+     /// | `gitoxide default`| `Thu Jan 6 2022 09:32:07 -0500`  |
+     fn parse_time(time_str: &str) -> Result<gix::date::Time> {
+         let time_str = time_str.trim();
+-        let now = std::time::SystemTime::now();
+-        let zoned_now = jiff::Zoned::try_from(now).unwrap_or_else(|_| 
jiff::Zoned::now());
++        let zoned_now = jiff::Zoned::try_from(std::time::SystemTime::now())
++            .unwrap_or_else(|_| jiff::Zoned::now());
+ 
+         if time_str == "now" {
+-            Ok(gix::date::Time::new(
++            return Ok(gix::date::Time::new(
+                 zoned_now.timestamp().as_second(),
+                 zoned_now.offset().seconds(),
+-            ))
+-        } else if let Ok(time) = gix::date::parse(time_str, Some(now)) {
+-            Ok(time)
+-        } else if let Ok(time) = gix::date::parse(
+-            &format!("{time_str} {}", zoned_now.strftime("%z")),
+-            Some(now),
+-        ) {
+-            Ok(time)
+-        } else if let Ok(time) = gix::date::parse(
+-            &format!("{time_str}{}", zoned_now.strftime("%:z")),
+-            Some(now),
+-        ) {
+-            Ok(time)
+-        } else {
+-            Err(anyhow!("invalid date `{time_str}`"))
++            ));
+         }
++
++        if let Ok(time) = gix::date::parse(time_str, Some(zoned_now.clone())) 
{
++            return Ok(time);
++        }
++
++        // A date-time that is only missing its UTC offset is retried with 
the local
++        // offset appended. Only do that for something that looks like a time 
of day:
++        // git's approxidate reads the appended offset as part of a relative 
date, so
++        // "a long time ago" would otherwise become "a long time ago-04:00", 
which
++        // parses as four seconds ago.
++        if time_str.contains(':') && time_str.ends_with(|c: char| 
c.is_ascii_digit()) {
++            for with_offset in [
++                format!("{time_str} {}", zoned_now.strftime("%z")),
++                format!("{time_str}{}", zoned_now.strftime("%:z")),
++            ] {
++                if let Ok(time) = gix::date::parse(&with_offset, 
Some(zoned_now.clone())) {
++                    return Ok(time);
++                }
++            }
++        }
++
++        Err(anyhow!("invalid date `{time_str}`"))
+     }
+ }
+ 
+@@ -95,6 +103,69 @@ mod tests {
+         Time::parse_time("now").unwrap();
+     }
+ 
++    /// Formats that carry no UTC offset are retried with the local offset 
appended.
++    /// Comparing wall clock time keeps this independent of the test 
machine's zone.
++    #[test]
++    fn parse_time_without_offset() {
++        // 2022-01-06T09:32:07 read as if it were UTC.
++        let wall_clock = 1641461527;
++        for s in [
++            "Thu Jan 6 09:32:07 2022",
++            "Thu, 6 Jan 2022 09:32:07",
++            "2022-01-06 09:32:07",
++            "2022-01-06T09:32:07",
++        ] {
++            let time = Time::parse_time(s).unwrap();
++            assert_eq!(
++                time.seconds + i64::from(time.offset),
++                wall_clock,
++                "`{s}` did not parse to the expected wall clock time"
++            );
++        }
++    }
++
++    /// Git allows a `@` before a commit-header date, with or without an 
offset.
++    #[test]
++    fn parse_time_at_prefixed_epoch() {
++        let time = Time::parse_time("@1641479527").unwrap();
++        assert_eq!(time.seconds, 1641479527);
++
++        let time = Time::parse_time("@1641479527 -0500").unwrap();
++        assert_eq!(time.seconds, 1641479527);
++        assert_eq!(time.offset, -5 * 60 * 60);
++    }
++
++    /// Relative dates are resolved against the current time, so equivalent 
spellings
++    /// are compared against each other rather than against a fixed value.
++    #[test]
++    fn parse_time_relative_spellings() {
++        fn assert_same_moment(a: &str, b: &str) {
++            let (ta, tb) = (Time::parse_time(a).unwrap(), 
Time::parse_time(b).unwrap());
++            let delta = (ta.seconds - tb.seconds).abs();
++            assert!(delta <= 2, "`{a}` and `{b}` differ by {delta} seconds");
++        }
++
++        assert_same_moment("one week ago", "7 days ago");
++        assert_same_moment("last week", "7 days ago");
++        assert_same_moment("ten days ago", "10 days ago");
++        assert_same_moment("3.days.ago", "3 days ago");
++        assert_same_moment("2 days 3 hours ago", "51 hours ago");
++        assert_same_moment("last month", "1 month ago");
++    }
++
++    /// Relative dates are anchored in the local zone, not UTC.
++    #[test]
++    fn parse_time_relative_uses_local_offset() {
++        let now = Time::parse_time("now").unwrap();
++        for s in ["3 days ago", "yesterday", "1 month ago"] {
++            assert_eq!(
++                Time::parse_time(s).unwrap().offset,
++                now.offset,
++                "`{s}` did not use the same UTC offset as `now`"
++            );
++        }
++    }
++
+     #[test]
+     fn test_parse_time_negative_offset() {
+         let time = Time::parse_time("123456 -0230").unwrap();
+@@ -110,6 +181,8 @@ mod tests {
+             "123456 -060",
+             "123456 +06000",
+             "123456 06000",
++            "a long time ago",
++            "bogus nonsense",
+         ] {
+             assert!(Time::parse_time(bad_str).is_err());
+         }
+--- 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
+@@ -243,7 +243,7 @@ impl<'repo> Stack<'repo> {
+                 Some(format!("{}.stgit", self.branch_name).as_str().into()),
+                 "protect",
+             )
+-            .unwrap_or(Ok(false))
++            .unwrap_or(Some(false))
+             .unwrap_or(false)
+     }
+ 
+@@ -271,7 +271,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());
+         }
+     }
+--- a/t/t3300-edit.sh
++++ b/t/t3300-edit.sh
+@@ -345,6 +345,36 @@ test_expect_success 'Set author date to
+     printf "$before\n$(adate HEAD)\n$after\n" | sort -c -
+ '
+ 
++test_expect_success 'Set author date to a relative date' '
++    stg edit p2 --authdate "one week ago" &&
++    week=$(adate HEAD) &&
++    stg edit p2 --authdate "3 days ago" &&
++    days=$(adate HEAD) &&
++    stg edit p2 --authdate "3.days.ago" &&
++    dotted=$(adate HEAD) &&
++    stg edit p2 --authdate "2 days 3 hours ago" &&
++    hours=$(adate HEAD) &&
++    test "$week" \< "$days" &&
++    test "$week" \< "$dotted" &&
++    test "$days" \< "$hours" &&
++    test "$dotted" \< "$hours"
++'
++
++test_expect_success 'Relative author date uses the local time zone' '
++    TZ=Asia/Kolkata stg edit p2 --authdate "1 day ago" &&
++    case "$(adate HEAD)" in
++    *" +0530") : ;;
++    *) echo "expected +0530, got $(adate HEAD)" && false ;;
++    esac
++'
++
++test_expect_success 'Set author date from epoch with @ prefix' '
++    stg edit p2 --authdate "@1641479527 -0500" &&
++    test "$(adate HEAD)" = "2022-01-06 09:32:07 -0500" &&
++    stg edit p2 --authdate "@1641479527" &&
++    test "$(adate HEAD)" = "2022-01-06 14:32:07 +0000"
++'
++
+ test_expect_success 'Set patch tree' '
+     p2tree=$(git log -1 --pretty=format:%T $(stg id p2)) &&
+     p4commit=$(stg id p4) &&
diff -Nru stgit-2.6.1/debian/patches/reject-lone-at-partial-ref.patch 
stgit-2.6.1/debian/patches/reject-lone-at-partial-ref.patch
--- stgit-2.6.1/debian/patches/reject-lone-at-partial-ref.patch 1969-12-31 
18:00:00.000000000 -0600
+++ stgit-2.6.1/debian/patches/reject-lone-at-partial-ref.patch 2026-09-18 
10:19:36.000000000 -0500
@@ -0,0 +1,53 @@
+Description: Reject a lone "@" as a partial ref name
+Author: Peter Grayson <[email protected]>
+Origin: upstream
+Applied-Upstream: 10d8dec999f783459ad45671539d37752fad1406
+Last-Update: 2026-09-18
+---
+--- a/src/wrap/partialrefname.rs
++++ b/src/wrap/partialrefname.rs
+@@ -101,7 +101,9 @@ pub(crate) fn partial_ref_name(input: &m
+ 
+     let name = input.next_slice(split_offset);
+ 
+-    if name.is_empty() || name == "-" {
++    if name.is_empty() || name == "-" || name == "@" {
++        // A lone "@" is shorthand for "HEAD" in revspecs, so git does not 
allow it as a
++        // reference name. It remains valid as a component, e.g. 
"refs/heads/@".
+         Err(ErrMode::Backtrack(ContextError::from_input(input)))
+     } else if name.ends_with(".lock") {
+         // Names ending with ".lock" are invalid and there is no recovery.
+@@ -141,5 +143,15 @@ mod tests {
+             partial_ref_name.parse_peek("abc.def/"),
+             Ok(("/", PartialRefName(String::from("abc.def"))))
+         );
++        assert!(partial_ref_name.parse_peek("@").is_err());
++        assert!(partial_ref_name.parse_peek("@~").is_err());
++        assert_eq!(
++            partial_ref_name.parse_peek("@abc"),
++            Ok(("", PartialRefName(String::from("@abc"))))
++        );
++        assert_eq!(
++            partial_ref_name.parse_peek("abc/@"),
++            Ok(("", PartialRefName(String::from("abc/@"))))
++        );
+     }
+ }
+--- a/t/t1000-branch-create.sh
++++ b/t/t1000-branch-create.sh
+@@ -168,4 +168,15 @@ test_expect_success 'Reuse name of parti
+     stg branch --create new
+ '
+ 
++test_expect_success 'Create branch with reserved name "@"' '
++    general_error stg branch --create @ &&
++    test_must_fail git rev-parse --verify refs/heads/@
++'
++
++test_expect_success 'Create branch with "@" as a name component' '
++    stg branch --create @-suffix &&
++    stg branch --create with/@ &&
++    stg branch master
++'
++
+ test_done
diff -Nru stgit-2.6.1/debian/patches/series stgit-2.6.1/debian/patches/series
--- stgit-2.6.1/debian/patches/series   2026-08-24 09:43:17.000000000 -0500
+++ stgit-2.6.1/debian/patches/series   2026-09-18 10:10:37.000000000 -0500
@@ -2,4 +2,5 @@
 disable_interactive_test
 use_bzip2_crate
 use_winnow_0_7
-gix-0.86.patch
+gix-0.87.patch
+reject-lone-at-partial-ref.patch

Attachment: OpenPGP_signature.asc
Description: OpenPGP digital signature


--- End Message ---
--- Begin Message ---
Source: stgit
Source-Version: 2.6.1-1.2
Done: Simon Quigley <[email protected]>

We believe that the bug you reported is fixed in the latest version of
stgit, which is due to be installed in the Debian FTP archive.

A summary of the changes between this version and the previous one is
attached.

Thank you for reporting the bug, which will now be closed.  If you
have further comments please address them to [email protected],
and the maintainer will reopen the bug report if appropriate.

Debian distribution maintenance software
pp.
Simon Quigley <[email protected]> (supplier of updated stgit package)

(This message was generated automatically at their request; if you
believe that there is a problem with it please contact the archive
administrators by mailing [email protected])


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

Format: 1.8
Date: Fri, 18 Sep 2026 14:52:28 -0500
Source: stgit
Architecture: source
Version: 2.6.1-1.2
Distribution: unstable
Urgency: medium
Maintainer: Maximiliano Curia <[email protected]>
Changed-By: Simon Quigley <[email protected]>
Closes: 1148264
Changes:
 stgit (2.6.1-1.2) unstable; urgency=medium
 .
   * Non-maintainer upload (Closes: #1148264).
   * Drop gix-0.86.patch in favor of a direct upstream cherry-pick in
     gix-0.87.patch.
   * Cherry-pick upstream fix to reject a lone "@" as a partial ref name.
Checksums-Sha1:
 6e56476007b6b80e3f2aff268faf2e0353f48a83 2487 stgit_2.6.1-1.2.dsc
 10d5edfe51feded59a30370cbe33a0ea2b96c58a 14676 stgit_2.6.1-1.2.debian.tar.xz
 a1632cee372b25c8d1e92a005b86ffc60929eaf0 8143 stgit_2.6.1-1.2_source.buildinfo
Checksums-Sha256:
 96c215ea1514e15b84248297b164e3818a0c7c927df76bf6472da4e06888aa64 2487 
stgit_2.6.1-1.2.dsc
 1a726f5fb1b434d5d592add295644408323e73f8323b5568c9f95cb0372d9b81 14676 
stgit_2.6.1-1.2.debian.tar.xz
 1b71f4b6a4de51fe483067933aa371ee50556430924487cc07e0e9a1c9ea57c4 8143 
stgit_2.6.1-1.2_source.buildinfo
Files:
 17f7c8fd25df9a531e5b6c4bd28965b0 2487 vcs optional stgit_2.6.1-1.2.dsc
 e786d1f09d3e6b984e2010ddb88f3b33 14676 vcs optional 
stgit_2.6.1-1.2.debian.tar.xz
 92bbfc50bbe6390e60dd8702f9903632 8143 vcs optional 
stgit_2.6.1-1.2_source.buildinfo

-----BEGIN PGP SIGNATURE-----

iQIzBAEBCgAdFiEEXHq+og+GMEWcyMi14n8s+EWML6QFAmqtlqEACgkQ4n8s+EWM
L6Q4PhAAtSzS3K+tncsovG4AMbbZ5hDnvFko0XqSr08+pO55yW1cXOXd0rTh33/x
sgw4jLMhfkYn7H6IkAjoRqWV1iRt4spW7dvJanf1Co2+1V6CEPdNWDdcmYCH7LNk
eyGPBOAn6GEGL/qEVZuAbch3AgUegHFCIvV5vNyFFfsxfEYiyvMaCPpbrb5erHv3
jLMn764qdqm3w5Nyl1YQkHWiuPI20vWPYdqtNRKHdJBipwExDLskFi0FS3tzThE+
25kVG5zHxEc0OmZrmPJdwB5Z+39IDiw5aqzZwtRFnPMEuth9meTfTaJcZogWImIU
CY5ymM0Bg6VeCI+QKucSXj+zc4l+mbjMXVO6g+3WSeqF4v3x9Fa8trJgqW8kKddd
C0bOzEc6rzylYpujDhN+ouQ6VVf6fSpqTTejE/kqAUOOYuRwo+iV8Kz+bF+pJrSN
mKkLsrNs5vEoHu2wZkypBAASl94dkw8QU915PrPUHdoMxDl6tVoWp17G+vz+KnPf
dZNP9fzQOFyj4y2IGpj02Ql6TFNBM7SbAEUCJ3xHHBjXUmG1K3zFSnz8+PmMF4Eg
LzTyiRXdnDeeBHhumACHQKgS/cVG8i8ZRfF4OAJImqZucG/xji4niuRCmsayRjhO
zJ1JrPiJ/mqNj+2yRk3UCGYpYFW1X2YmlRBclGztwT3eSCmys3Y=
=0HAm
-----END PGP SIGNATURE-----

Attachment: pgpG7tdMPfWDX.pgp
Description: PGP signature


--- End Message ---

Reply via email to