Showing the changes to gitoxide-core/src/repository/commitgraph (1 of 4 files). Show all
Unified · Split
| @@ -1,55 +1,92 @@ | ||
| 1 | 1 | pub(crate) mod function { |
| 2 | − use std::{borrow::Cow, ffi::OsString}; | |
| 3 | − | |
| 2 | + use crate::OutputFormat; | |
| 4 | 3 | use anyhow::{bail, Context}; |
| 4 | + use gix::odb::store::RefreshMode; | |
| 5 | + use gix::revision::plumbing::Spec; | |
| 5 | 6 | use gix::{prelude::ObjectIdExt, revision::walk::Sorting}; |
| 6 | − | |
| 7 | − use crate::OutputFormat; | |
| 7 | + use std::fmt::Formatter; | |
| 8 | + use std::{borrow::Cow, ffi::OsString}; | |
| 8 | 9 | |
| 9 | 10 | pub fn list( |
| 10 | 11 | mut repo: gix::Repository, |
| 11 | 12 | spec: OsString, |
| 12 | 13 | mut out: impl std::io::Write, |
| 14 | + long_hashes: bool, | |
| 13 | 15 | format: OutputFormat, |
| 14 | 16 | ) -> anyhow::Result<()> { |
| 15 | 17 | if format != OutputFormat::Human { |
| 16 | 18 | bail!("Only human output is currently supported"); |
| 17 | 19 | } |
| 18 | 20 | let graph = repo |
| 19 | − .commit_graph() | |
| 21 | + .commit_graph_if_enabled() | |
| 20 | 22 | .context("a commitgraph is required, but none was found")?; |
| 21 | 23 | repo.object_cache_size_if_unset(4 * 1024 * 1024); |
| 24 | + repo.objects.refresh = RefreshMode::Never; | |
| 22 | 25 | |
| 23 | 26 | let spec = gix::path::os_str_into_bstr(&spec)?; |
| 24 | − let id = repo | |
| 25 | − .rev_parse_single(spec) | |
| 26 | − .context("Only single revisions are currently supported")?; | |
| 27 | − let commits = id | |
| 28 | − .object()? | |
| 29 | − .peel_to_kind(gix::object::Kind::Commit) | |
| 30 | − .context("Need committish as starting point")? | |
| 31 | − .id() | |
| 32 | − .ancestors() | |
| 33 | − .sorting(Sorting::ByCommitTime(Default::default())) | |
| 34 | − .all()?; | |
| 27 | + let spec = repo.rev_parse(spec)?.detach(); | |
| 28 | + let commits = match spec { | |
| 29 | + Spec::Include(id) => connected_commit_id(&repo, id)? | |
| 30 | + .ancestors() | |
| 31 | + .sorting(Sorting::ByCommitTime(Default::default())) | |
| 32 | + .all()?, | |
| 33 | + Spec::Range { from, to } => connected_commit_id(&repo, to)? | |
| 34 | + .ancestors() | |
| 35 | + .sorting(Sorting::ByCommitTime(Default::default())) | |
| 36 | + .with_hidden(Some(connected_commit_id(&repo, from)?)) | |
| 37 | + .all()?, | |
| 38 | + Spec::Exclude(_) | Spec::Merge { .. } | Spec::IncludeOnlyParents(_) | Spec::ExcludeParents(_) => { | |
| 39 | + bail!("The spec isn't currently supported: {spec:?}") | |
| 40 | + } | |
| 41 | + }; | |
| 35 | 42 | for commit in commits { |
| 36 | 43 | let commit = commit?; |
| 37 | 44 | writeln!( |
| 38 | 45 | out, |
| 39 | 46 | "{} {} {} {}", |
| 40 | − commit.id().shorten_or_id(), | |
| 47 | + HexId::new(commit.id(), long_hashes), | |
| 41 | 48 | commit.commit_time.expect("traversal with date"), |
| 42 | 49 | commit.parent_ids.len(), |
| 43 | − graph.commit_by_id(commit.id).map_or_else( | |
| 44 | − || Cow::Borrowed("<NOT IN GRAPH-CACHE>"), | |
| 45 | − |c| Cow::Owned(format!( | |
| 46 | − "{} {}", | |
| 47 | − c.root_tree_id().to_owned().attach(&repo).shorten_or_id(), | |
| 48 | − c.generation() | |
| 50 | + graph | |
| 51 | + .as_ref() | |
| 52 | + .map_or(Cow::Borrowed(""), |graph| graph.commit_by_id(commit.id).map_or_else( | |
| 53 | + || Cow::Borrowed("<NOT IN GRAPH-CACHE>"), | |
| 54 | + |c| Cow::Owned(format!( | |
| 55 | + "{} {}", | |
| 56 | + HexId::new(c.root_tree_id().to_owned().attach(&repo), long_hashes), | |
| 57 | + c.generation() | |
| 58 | + )) | |
| 49 | 59 | )) |
| 50 | − ) | |
| 51 | 60 | )?; |
| 52 | 61 | } |
| 53 | 62 | Ok(()) |
| 54 | 63 | } |
| 64 | + | |
| 65 | + fn connected_commit_id(repo: &gix::Repository, id: gix::ObjectId) -> anyhow::Result<gix::Id<'_>> { | |
| 66 | + Ok(id | |
| 67 | + .attach(repo) | |
| 68 | + .object()? | |
| 69 | + .peel_to_kind(gix::object::Kind::Commit) | |
| 70 | + .context("Need committish as starting point")? | |
| 71 | + .id()) | |
| 72 | + } | |
| 73 | + | |
| 74 | + struct HexId<'a>(gix::Id<'a>, bool); | |
| 75 | + | |
| 76 | + impl<'a> HexId<'a> { | |
| 77 | + pub fn new(id: gix::Id<'a>, long_hex: bool) -> Self { | |
| 78 | + HexId(id, long_hex) | |
| 79 | + } | |
| 80 | + } | |
| 81 | + | |
| 82 | + impl std::fmt::Display for HexId<'_> { | |
| 83 | + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | |
| 84 | + let HexId(id, long_hex) = self; | |
| 85 | + if *long_hex { | |
| 86 | + id.fmt(f) | |
| 87 | + } else { | |
| 88 | + id.shorten_or_id().fmt(f) | |
| 89 | + } | |
| 90 | + } | |
| 91 | + } | |
| 55 | 92 | } |