gitoxide_core/repository/revision/
resolve.rs1use crate::OutputFormat;
2
3pub struct Options {
4 pub format: OutputFormat,
5 pub explain: bool,
6 pub cat_file: bool,
7 pub tree_mode: TreeMode,
8 pub blob_format: BlobFormat,
9 pub show_reference: bool,
10}
11
12pub enum TreeMode {
13 Raw,
14 Pretty,
15}
16
17#[derive(Copy, Clone)]
18pub enum BlobFormat {
19 Git,
20 Worktree,
21 Diff,
22 DiffOrGit,
23}
24
25pub(crate) mod function {
26 use std::ffi::OsString;
27
28 use gix::revision::Spec;
29
30 use super::Options;
31 use crate::repository::cat::display_object;
32 use crate::repository::revision::resolve::BlobFormat;
33 use crate::{repository::revision, OutputFormat};
34
35 pub fn resolve(
36 mut repo: gix::Repository,
37 specs: Vec<OsString>,
38 mut out: impl std::io::Write,
39 Options {
40 format,
41 explain,
42 cat_file,
43 tree_mode,
44 blob_format,
45 show_reference,
46 }: Options,
47 ) -> anyhow::Result<()> {
48 repo.object_cache_size_if_unset(1024 * 1024);
49 let mut cache = (!matches!(blob_format, BlobFormat::Git))
50 .then(|| {
51 repo.diff_resource_cache(
52 match blob_format {
53 BlobFormat::Git => {
54 unreachable!("checked before")
55 }
56 BlobFormat::Worktree | BlobFormat::Diff => {
57 gix::diff::blob::pipeline::Mode::ToWorktreeAndBinaryToText
58 }
59 BlobFormat::DiffOrGit => gix::diff::blob::pipeline::Mode::ToGitUnlessBinaryToTextIsPresent,
60 },
61 Default::default(),
62 )
63 })
64 .transpose()?;
65
66 match format {
67 OutputFormat::Human => {
68 for spec in specs {
69 if explain {
70 return revision::explain(spec, out);
71 }
72 let spec = gix::path::os_str_into_bstr(&spec)?;
73 let spec = repo.rev_parse(spec)?;
74 if cat_file {
75 return display_object(&repo, spec, tree_mode, cache.as_mut().map(|c| (blob_format, c)), out);
76 }
77 if let Some(r) = spec.first_reference().filter(|_| show_reference) {
78 writeln!(out, "{}", r.name)?;
79 }
80 if let Some(r) = spec.second_reference().filter(|_| show_reference) {
81 writeln!(out, "{}", r.name)?;
82 }
83 writeln!(out, "{spec}", spec = spec.detach())?;
84 }
85 }
86 #[cfg(feature = "serde")]
87 OutputFormat::Json => {
88 if explain {
89 anyhow::bail!("Explanations are only for human consumption")
90 }
91 serde_json::to_writer_pretty(
92 &mut out,
93 &specs
94 .into_iter()
95 .map(|spec| {
96 gix::path::os_str_into_bstr(&spec)
97 .map_err(anyhow::Error::from)
98 .and_then(|spec| repo.rev_parse(spec).map_err(Into::into))
99 .map(Spec::detach)
100 })
101 .collect::<Result<Vec<_>, _>>()?,
102 )?;
103 }
104 }
105 Ok(())
106 }
107}