Skip to content
Merged
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: 2 additions & 0 deletions src/cmd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub(crate) mod id;
pub(crate) mod import;
pub(crate) mod init;
pub(crate) mod log;
pub(crate) mod name;
pub(crate) mod new;
pub(crate) mod next;
pub(crate) mod patches;
Expand Down Expand Up @@ -101,6 +102,7 @@ pub(crate) const STGIT_COMMANDS: &[StGitCommand] = &[
import::STGIT_COMMAND,
init::STGIT_COMMAND,
log::STGIT_COMMAND,
name::STGIT_COMMAND,
new::STGIT_COMMAND,
next::STGIT_COMMAND,
patches::STGIT_COMMAND,
Expand Down
100 changes: 100 additions & 0 deletions src/cmd/name.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// SPDX-License-Identifier: GPL-2.0-only

//! `stg name` implementation.

use std::io::Write;

use anyhow::{anyhow, Result};
use clap::{Arg, ArgMatches};
use termcolor::WriteColor;

use crate::{
argset,
branchloc::BranchLocator,
ext::RepositoryExtended,
patch::SingleRevisionSpec,
stack::{InitializationPolicy, Stack, StackAccess, StackStateAccess},
};

pub(super) const STGIT_COMMAND: super::StGitCommand = super::StGitCommand {
name: "name",
category: super::CommandCategory::PatchInspection,
make,
run,
};

fn make() -> clap::Command {
clap::Command::new(STGIT_COMMAND.name)
.about("Print patch name of a StGit revision")
.long_about(
"Print the patch name of a StGit revision.\n\
\n\
Try to get the name of the patch in the current \
branch as specified by a StGit revision. Revisions \
can be specified in the all the forms accepted by \
\"stg id\" command.",
)
.arg(argset::branch_arg())
.arg(
Arg::new("show-branch")
.long("showbranch")
.help("Display the branch name with the patch")
.action(clap::ArgAction::SetTrue),
)
.arg(
Arg::new("no-show-branch")
.long("no-showbranch")
.help("Do not display branch name")
.hide(true)
.action(clap::ArgAction::SetTrue)
.overrides_with("show-branch"),
)
.arg(
Arg::new("stgit-revision")
.value_name("revision")
.allow_hyphen_values(true)
.value_parser(clap::value_parser!(SingleRevisionSpec))
.help("StGit revision"),
)
}

fn run(matches: &ArgMatches) -> Result<()> {
let repo = gix::Repository::open()?;

let stack = Stack::from_branch_locator(
&repo,
matches.get_one::<BranchLocator>("branch"),
InitializationPolicy::RequireInitialized,
)?;

let oid = matches
.get_one::<SingleRevisionSpec>("stgit-revision")
.map(|spec| spec.resolve_object(&repo, &stack).map(|object| object.id))
.transpose()?
.unwrap_or_else(|| stack.get_branch_head().id);

let Some(patch_name) = (oid == stack.base().id).then_some("{base}").or_else(|| {
stack
.all_patches()
.find(|name| oid == stack.get_patch_commit_id(name))
.map(|name| name.as_ref())
}) else {
return Err(anyhow!("patch name not found for revision `{oid}`"));
};

let mut stdout = crate::color::get_color_stdout(matches);
let mut color_spec = termcolor::ColorSpec::new();
color_spec.set_bold(true);
stdout.set_color(&color_spec)?;

if matches.get_flag("show-branch") {
write!(stdout, "{}:", stack.get_branch_name())?;
}

write!(stdout, "{patch_name}")?;
color_spec.clear();
stdout.set_color(&color_spec)?;
writeln!(stdout)?;

Ok(())
}
44 changes: 44 additions & 0 deletions t/t3700-name.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/bin/sh

test_description="Test 'stg name'"

. ./test-lib.sh

test_expect_success 'Test on uninitialized repo' '
command_error stg name 2>err &&
grep "stack not initialized" err
'

test_expect_success 'Init repo' '
echo "foo" >foo.txt &&
git add foo.txt &&
git commit -m "initial" &&
git commit --allow-empty -m "base" &&
git branch nostack &&
for i in 1 2; do
echo "line $i" >>foo.txt &&
stg new -m "patch-$i" &&
stg refresh || return 1
done &&
stg branch -C cloned &&
stg branch -c forked &&
stg branch master
'

test_expect_success 'Get patch names' '
test "$(stg name)" = "patch-2" &&
test "$(stg name -1)" = "patch-1" &&
test "$(stg name 0~1)" = "{base}" &&
test "$(stg name --showbranch)" = "master:patch-2" &&
test "$(stg name -b cloned --showbranch)" = "cloned:patch-2" &&
test "$(stg name -b forked --showbranch)" = "forked:{base}"
'

test_expect_success 'Fail to get patch names' '
command_error stg name -b nostack --showbranch 2>err &&
grep "stack not initialized" err &&
command_error stg name 0~2 2>err &&
grep "patch name not found" err
'

test_done
Loading