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