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;
81#[cfg(feature = "blocking-client")]
82pub mod remote;
83pub mod repository;
84
85mod output;
86
87mod discover;
88pub use discover::discover;
89
90pub fn trust(paths: &[std::path::PathBuf], mut out: impl std::io::Write) -> anyhow::Result<()> {
91 let trust_width = "Reduced".len();
92 for path in paths {
93 let trust = gix::sec::Trust::from_path_ownership(path)?;
94 let trust = format!("{trust:?}");
95 writeln!(out, "{trust:<trust_width$} {}", path.display())?;
96 }
97 Ok(())
98}
99
100pub fn env(mut out: impl std::io::Write, format: OutputFormat) -> anyhow::Result<()> {
101 if format != OutputFormat::Human {
102 bail!("JSON output isn't supported");
103 }
104
105 let width = 15;
106 writeln!(
107 out,
108 "{field:>width$}: {}",
109 std::path::Path::new(gix::path::env::shell()).display(),
110 field = "shell",
111 )?;
112 writeln!(
113 out,
114 "{field:>width$}: {:?}",
115 gix::path::env::installation_config_prefix(),
116 field = "config prefix",
117 )?;
118 writeln!(
119 out,
120 "{field:>width$}: {:?}",
121 gix::path::env::installation_config(),
122 field = "config",
123 )?;
124 writeln!(
125 out,
126 "{field:>width$}: {}",
127 gix::path::env::exe_invocation().display(),
128 field = "git exe",
129 )?;
130 writeln!(
131 out,
132 "{field:>width$}: {:?}",
133 gix::path::env::system_prefix(),
134 field = "system prefix",
135 )?;
136 writeln!(
137 out,
138 "{field:>width$}: {:?}",
139 gix::path::env::core_dir(),
140 field = "core dir",
141 )?;
142 Ok(())
143}
144
145#[cfg(all(feature = "async-client", feature = "blocking-client"))]
146compile_error!("Cannot set both 'blocking-client' and 'async-client' features as they are mutually exclusive");
147
148fn is_dir_to_mode(is_dir: bool) -> gix::index::entry::Mode {
149 if is_dir {
150 gix::index::entry::Mode::DIR
151 } else {
152 gix::index::entry::Mode::FILE
153 }
154}