Skip to content

Commit

Permalink
feat: Add gix repo commit describe (#298)
Browse files Browse the repository at this point in the history
It supports typical but basic flags mostly similar to the ones in git.
  • Loading branch information
Byron committed Apr 4, 2022
1 parent 0a7776b commit 7e99e6a
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 8 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ Please see _'Development Status'_ for a listing of all crates and their capabili
* [x] **verify** - check entries of a mailmap file for parse errors and display them
* **repository**
* **verify** - validate a whole repository, for now only the object database.
* **commit**
* [x] **describe** - identify a commit by its closest tag in its past
* **tree**
* [x] **entries** - list tree entries for a single tree or recursively
* [x] **info** - display tree statistics
Expand Down
53 changes: 53 additions & 0 deletions gitoxide-core/src/repository/commit.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
use anyhow::{Context, Result};
use git_repository as git;
use std::path::PathBuf;

pub fn describe(
repo: impl Into<PathBuf>,
rev_spec: Option<&str>,
mut out: impl std::io::Write,
describe::Options {
all_tags,
all_refs,
first_parent,
always,
long_format,
}: describe::Options,
) -> Result<()> {
let repo = git::open(repo)?.apply_environment();
let commit = match rev_spec {
Some(spec) => repo.rev_parse(spec)?.object()?.try_into_commit()?,
None => repo.head_commit()?,
};
use git::commit::describe::SelectRef::*;
let select_ref = if all_refs {
AllRefs
} else if all_tags {
AllTags
} else {
Default::default()
};
let mut describe_id = commit
.describe()
.names(select_ref)
.traverse_first_parent(first_parent)
.id_as_fallback(always)
.try_format()?
.with_context(|| format!("Did not find a single candidate ref for naming id '{}'", commit.id))?;

describe_id.long(long_format);

writeln!(out, "{}", describe_id)?;
Ok(())
}

pub mod describe {
#[derive(Debug, Clone)]
pub struct Options {
pub all_tags: bool,
pub all_refs: bool,
pub first_parent: bool,
pub always: bool,
pub long_format: bool,
}
}
2 changes: 2 additions & 0 deletions gitoxide-core/src/repository/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ pub fn init(directory: Option<PathBuf>) -> Result<git_repository::Path> {

pub mod tree;

pub mod commit;

pub mod verify;

pub mod odb;
Expand Down
18 changes: 16 additions & 2 deletions src/plumbing/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,20 +156,34 @@ pub fn main() -> Result<()> {
),
},
Subcommands::Repository(repo::Platform { repository, cmd }) => match cmd {
repo::Subcommands::Describe { cmd } => match cmd {
repo::Subcommands::Commit { cmd } => match cmd {
repo::commit::Subcommands::Describe {
all_tags,
all_refs,
first_parent,
always,
long,
rev_spec,
} => prepare_and_run(
"repository-commit-describe",
verbose,
progress,
progress_keep_open,
None,
move |_progress, out, err| todo!(),
move |_progress, out, _err| {
core::repository::commit::describe(
repository,
rev_spec.as_deref(),
out,
core::repository::commit::describe::Options {
all_tags,
all_refs,
long_format: long,
first_parent,
always,
},
)
},
),
},
repo::Subcommands::Mailmap { cmd } => match cmd {
Expand Down
16 changes: 10 additions & 6 deletions src/plumbing/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,8 +350,8 @@ pub mod repo {
#[clap(flatten)]
args: super::pack::VerifyOptions,
},
/// Describe the current commit or the given one using the name of the closest annotated tag in its ancestry.
Describe {
/// Interact with commit objects.
Commit {
#[clap(subcommand)]
cmd: commit::Subcommands,
},
Expand Down Expand Up @@ -396,18 +396,22 @@ pub mod repo {
/// Describe the current commit or the given one using the name of the closest annotated tag in its ancestry.
Describe {
/// Use all tag references for naming, not only annotated tags.
#[clap(short = 't', conflicts_with("all-refs"))]
#[clap(long, short = 't', conflicts_with("all-refs"))]
all_tags: bool,

/// Use all references under the `ref/` namespaces, which includes tag references, local and remote branches.
#[clap(short = 'a', conflicts_with("all-tags"))]
#[clap(long, short = 'a', conflicts_with("all-tags"))]
all_refs: bool,

/// Only follow the first parent when traversing the commit graph.
#[clap(short = 'f')]
#[clap(long, short = 'f')]
first_parent: bool,

#[clap(short = 'a')]
/// Always display the long format, even if that would not be necessary as the id is located directly on a reference.
#[clap(long, short = 'l')]
long: bool,

#[clap(long)]
/// If there was no way to describe the commit, fallback to using the abbreviated input revision.
always: bool,

Expand Down

0 comments on commit 7e99e6a

Please sign in to comment.