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