1#![cfg_attr(
25 all(doc, feature = "document-features"),
26 doc = ::document_features::document_features!()
27)]
28#![cfg_attr(all(doc, feature = "document-features"), feature(doc_cfg))]
29#![cfg_attr(feature = "async-client", allow(unused))]
30#![forbid(unsafe_code)]
31
32use std::str::FromStr;
33
34use anyhow::bail;
35
36#[derive(Debug, Eq, PartialEq, Hash, Clone, Copy)]
37pub enum OutputFormat {
38 Human,
39 #[cfg(feature = "serde")]
40 Json,
41}
42
43impl OutputFormat {
44 pub fn variants() -> &'static [&'static str] {
45 &[
46 "human",
47 #[cfg(feature = "serde")]
48 "json",
49 ]
50 }
51}
52
53impl FromStr for OutputFormat {
54 type Err = String;
55
56 fn from_str(s: &str) -> Result<Self, Self::Err> {
57 let s_lc = s.to_ascii_lowercase();
58 Ok(match s_lc.as_str() {
59 "human" => OutputFormat::Human,
60 #[cfg(feature = "serde")]
61 "json" => OutputFormat::Json,
62 _ => return Err(format!("Invalid output format: '{s}'")),
63 })
64 }
65}
66
67pub mod commitgraph;
68#[cfg(feature = "corpus")]
69pub mod corpus;
70pub mod net;
71
72#[cfg(feature = "estimate-hours")]
73pub mod hours;
74pub mod index;
75pub mod mailmap;
76#[cfg(feature = "organize")]
77pub mod organize;
78pub mod pack;
79#[cfg(feature = "query")]
80pub mod query;
81pub mod repository;
82
83mod discover;
84pub use discover::discover;
85
86pub fn trust(paths: &[std::path::PathBuf], mut out: impl std::io::Write) -> anyhow::Result<()> {
87 let trust_width = "Reduced".len();
88 for path in paths {
89 let trust = gix::sec::Trust::from_path_ownership(path)?;
90 let trust = format!("{trust:?}");
91 writeln!(out, "{trust:<trust_width$} {}", path.display())?;
92 }
93 Ok(())
94}
95
96pub fn env(mut out: impl std::io::Write, format: OutputFormat) -> anyhow::Result<()> {
97 if format != OutputFormat::Human {
98 bail!("JSON output isn't supported");
99 }
100
101 let width = 15;
102 writeln!(
103 out,
104 "{field:>width$}: {}",
105 std::path::Path::new(gix::path::env::shell()).display(),
106 field = "shell",
107 )?;
108 writeln!(
109 out,
110 "{field:>width$}: {:?}",
111 gix::path::env::installation_config_prefix(),
112 field = "config prefix",
113 )?;
114 writeln!(
115 out,
116 "{field:>width$}: {:?}",
117 gix::path::env::installation_config(),
118 field = "config",
119 )?;
120 writeln!(
121 out,
122 "{field:>width$}: {}",
123 gix::path::env::exe_invocation().display(),
124 field = "git exe",
125 )?;
126 writeln!(
127 out,
128 "{field:>width$}: {:?}",
129 gix::path::env::system_prefix(),
130 field = "system prefix",
131 )?;
132 writeln!(
133 out,
134 "{field:>width$}: {:?}",
135 gix::path::env::core_dir(),
136 field = "core dir",
137 )?;
138 Ok(())
139}
140
141#[cfg(all(feature = "async-client", feature = "blocking-client"))]
142compile_error!("Cannot set both 'blocking-client' and 'async-client' features as they are mutually exclusive");
143
144fn is_dir_to_mode(is_dir: bool) -> gix::index::entry::Mode {
145 if is_dir {
146 gix::index::entry::Mode::DIR
147 } else {
148 gix::index::entry::Mode::FILE
149 }
150}