Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ clap = { version = "~4.6", default-features = false, features = [
ctrlc = "3.4"
encoding_rs = "0.8"
flate2 = "1"
gix = { version = "0.85", default-features = false, features = [
gix = { version = "0.86", default-features = false, features = [
"command",
"revision",
"sha1",
Expand Down
10 changes: 2 additions & 8 deletions src/alias.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/branch/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ pub(super) fn dispatch(repo: &gix::Repository, matches: &clap::ArgMatches) -> Re
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)?;
Expand Down
10 changes: 3 additions & 7 deletions src/cmd/branch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
}
Expand All @@ -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))
}

Expand All @@ -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());
}
}
Expand Down
3 changes: 1 addition & 2 deletions src/cmd/branch/rename.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,7 @@ pub(super) fn dispatch(repo: &gix::Repository, matches: &clap::ArgMatches) -> Re
.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",
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/pick.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
33 changes: 7 additions & 26 deletions src/cmd/pull.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()),
Expand All @@ -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")
Expand Down Expand Up @@ -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());
Expand All @@ -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());
Expand All @@ -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 {
Expand All @@ -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());
Expand Down
30 changes: 9 additions & 21 deletions src/cmd/rebase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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)
};
Expand All @@ -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());
Expand Down
18 changes: 8 additions & 10 deletions src/ext/repository.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -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<()>;
Expand Down Expand Up @@ -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.
Expand All @@ -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,
Expand Down Expand Up @@ -171,7 +169,7 @@ impl RepositoryExtended for gix::Repository {
}
}

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(
Expand Down Expand Up @@ -233,11 +231,11 @@ impl RepositoryExtended for gix::Repository {
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)
}
Expand Down
30 changes: 14 additions & 16 deletions src/hook.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
//! Support for using git repository hooks.

use std::{
borrow::Cow,
io::Write,
path::{Path, PathBuf},
};
Expand All @@ -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) {
Expand Down
10 changes: 4 additions & 6 deletions src/patch/edit/interactive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,15 +135,13 @@ fn get_editor(config: &gix::config::Snapshot) -> Result<OsString> {
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") {
Expand Down
9 changes: 2 additions & 7 deletions src/stack/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand Down Expand Up @@ -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());
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/stack/upgrade.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ fn rm_stackformatversion(repo: &gix::Repository, branch_name: &str) -> Result<()
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());
}
}
Expand Down