git_proc/lib.rs
1#![doc = include_str!("../README.md")]
2
3/// Generate a pair of flag methods: unconditional and conditional.
4///
5/// The unconditional method calls the conditional one with `true`.
6///
7/// # Example
8///
9/// ```ignore
10/// flag_methods! {
11/// /// Enable foo mode.
12/// ///
13/// /// Corresponds to `--foo`.
14/// pub fn foo / foo_if, foo_field, "Conditionally enable foo mode."
15/// }
16/// ```
17///
18/// Generates:
19/// - `pub fn foo(self) -> Self` - calls `foo_if(true)`
20/// - `pub fn foo_if(mut self, value: bool) -> Self` - sets `self.foo_field = value`
21#[doc(hidden)]
22#[macro_export]
23macro_rules! flag_methods {
24 (
25 $(#[$attr:meta])*
26 $vis:vis fn $name:ident / $name_if:ident, $field:ident, $doc_if:literal
27 ) => {
28 $(#[$attr])*
29 #[must_use]
30 $vis fn $name(self) -> Self {
31 self.$name_if(true)
32 }
33
34 #[doc = $doc_if]
35 #[must_use]
36 $vis fn $name_if(mut self, value: bool) -> Self {
37 self.$field = value;
38 self
39 }
40 };
41}
42
43/// Generate an inherent `repo_path` method and a `RepoPath` trait implementation.
44///
45/// The inherent method sets the `repo_path` field to `Some(path)`.
46/// The trait implementation delegates to the inherent method.
47///
48/// This ensures callers can use `.repo_path()` without importing the `RepoPath` trait,
49/// while the trait remains available for generic bounds.
50#[doc(hidden)]
51#[macro_export]
52macro_rules! impl_repo_path {
53 ($ty:ident) => {
54 impl<'a> $ty<'a> {
55 /// Set the repository path (`-C <path>`).
56 #[must_use]
57 pub fn repo_path(mut self, path: &'a std::path::Path) -> Self {
58 self.repo_path = Some(path);
59 self
60 }
61 }
62
63 impl<'a> $crate::RepoPath<'a> for $ty<'a> {
64 fn repo_path(self, path: &'a std::path::Path) -> Self {
65 self.repo_path(path)
66 }
67 }
68 };
69}
70
71pub mod add;
72pub mod branch;
73pub mod clone;
74pub mod commit;
75pub mod config;
76pub mod diff;
77pub mod fetch;
78pub mod init;
79pub mod ls_remote;
80pub mod push;
81pub mod remote;
82pub mod repository;
83pub mod rev_list;
84pub mod rev_parse;
85pub mod show;
86pub mod show_ref;
87pub mod status;
88pub mod worktree;
89
90use std::path::Path;
91
92pub use cmd_proc::CommandError;
93
94/// Trait for git command builders that support porcelain output.
95///
96/// Provides the `porcelain` and `porcelain_if` methods to set `--porcelain`.
97pub trait Porcelain: Sized {
98 /// Conditionally enable porcelain output (`--porcelain`).
99 fn porcelain_if(self, value: bool) -> Self;
100
101 /// Enable porcelain output (`--porcelain`).
102 fn porcelain(self) -> Self {
103 self.porcelain_if(true)
104 }
105}
106
107/// Generate inherent `porcelain` / `porcelain_if` methods and a `Porcelain` trait implementation.
108///
109/// The inherent methods set the `porcelain` field.
110/// The trait implementation delegates to the inherent methods.
111///
112/// This ensures callers can use `.porcelain()` without importing the `Porcelain` trait,
113/// while the trait remains available for generic bounds.
114#[doc(hidden)]
115#[macro_export]
116macro_rules! impl_porcelain {
117 ($ty:ident) => {
118 impl<'a> $ty<'a> {
119 /// Give output in machine-parseable format.
120 ///
121 /// Corresponds to `--porcelain`.
122 #[must_use]
123 pub fn porcelain(self) -> Self {
124 self.porcelain_if(true)
125 }
126
127 /// Conditionally enable porcelain output.
128 #[must_use]
129 pub fn porcelain_if(mut self, value: bool) -> Self {
130 self.porcelain = value;
131 self
132 }
133 }
134
135 impl<'a> $crate::Porcelain for $ty<'a> {
136 fn porcelain_if(self, value: bool) -> Self {
137 self.porcelain_if(value)
138 }
139 }
140 };
141}
142
143/// Trait for git command builders that support a repository path.
144///
145/// Provides the `repo_path` method to set `-C <path>`.
146#[must_use = "repo_path returns a modified builder; the return value must be used"]
147pub trait RepoPath<'a>: Sized {
148 /// Set the repository path (`-C <path>`).
149 fn repo_path(self, path: &'a Path) -> Self;
150}
151
152/// Trait for building a command without executing it.
153///
154/// All git command builders implement this trait, allowing you to
155/// access the underlying `cmd_proc::Command` for custom execution.
156///
157/// # Example
158///
159/// ```ignore
160/// use git_proc::Build;
161///
162/// git_proc::fetch::new()
163/// .all()
164/// .build()
165/// .stderr_null()
166/// .status()
167/// .await?;
168/// ```
169pub trait Build {
170 /// Build the command without executing it.
171 fn build(self) -> cmd_proc::Command;
172}
173
174/// Create a command builder with optional repository path.
175///
176/// If `repo_path` is `Some`, adds `-C <path>` to the command.
177/// If `repo_path` is `None`, uses current working directory.
178fn base_command(repo_path: Option<&Path>) -> cmd_proc::Command {
179 cmd_proc::Command::new("git").optional_option("-C", repo_path)
180}