1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
//! # git-spawn
//!
//! A Rust wrapper around the `git` CLI. Each git subcommand is a struct with a
//! builder-style API; calling [`.execute().await`](GitCommand::execute) spawns
//! `git` as a subprocess and returns typed output.
//!
//! Unlike libraries that link against libgit2, this crate shells out to the
//! `git` binary installed on the host. That choice has trade-offs:
//!
//! | Pro | Con |
//! |----------------------------------------------|----------------------------------------|
//! | Behavior matches the user's local git | Requires `git` on `PATH` at runtime |
//! | Supports every flag — escape hatches for all | Higher per-call overhead than libgit2 |
//! | Honors `core.*` config, hooks, credentials | Output parsing is up to you (or us!) |
//!
//! If you want a scripting-like experience with the same flags you'd type in a
//! shell, this crate is for you. For in-process object database manipulation,
//! reach for [`git2`](https://docs.rs/git2) instead.
//!
//! ## Quick start
//!
//! ```no_run
//! use git_spawn::{GitCommand, Repository};
//!
//! # async fn example() -> git_spawn::Result<()> {
//! let repo = Repository::open("/path/to/repo")?;
//!
//! // Stage everything and commit.
//! repo.add().all().execute().await?;
//! repo.commit().message("snapshot").execute().await?;
//!
//! // Push to origin/main.
//! repo.push().remote("origin").refspec("main").execute().await?;
//! # Ok(())
//! # }
//! ```
//!
//! ## Core concepts
//!
//! ### The `GitCommand` trait
//!
//! Every command struct implements [`GitCommand`]. That trait provides:
//!
//! - [`execute()`](GitCommand::execute) — run the command and decode output
//! - [`arg()`](GitCommand::arg) / [`args()`](GitCommand::args) — append raw CLI
//! arguments (the universal escape hatch)
//! - [`current_dir()`](GitCommand::current_dir) — choose the working directory
//! - [`env()`](GitCommand::env) — set environment variables
//! - [`with_timeout()`](GitCommand::with_timeout) — cap execution time
//!
//! ### `Repository`
//!
//! [`Repository`] is a cheap, cloneable handle to a working tree. Its accessor
//! methods return commands pre-scoped to that path, so you rarely need to set
//! `.current_dir()` explicitly:
//!
//! ```no_run
//! # async fn ex() -> git_spawn::Result<()> {
//! # use git_spawn::{GitCommand, Repository};
//! let repo = Repository::open("/path/to/repo")?;
//! let status = repo.status().format(
//! git_spawn::command::status::StatusFormat::PorcelainV2
//! ).execute().await?;
//! println!("{}", status.stdout);
//! # Ok(())
//! # }
//! ```
//!
//! ### Typed parsers (the `parse` module)
//!
//! By default commands return [`CommandOutput`] — raw stdout/stderr plus the
//! exit status. For common outputs the [`parse`] module provides structured
//! types behind the `parse` feature (on by default):
//!
//! ```no_run
//! # async fn ex() -> git_spawn::Result<()> {
//! # use git_spawn::{GitCommand, Repository};
//! use git_spawn::command::status::StatusFormat;
//! use git_spawn::parse::{parse_status, StatusKind};
//!
//! let repo = Repository::open("/path/to/repo")?;
//! let out = repo.status()
//! .format(StatusFormat::PorcelainV1)
//! .null_terminate()
//! .execute()
//! .await?;
//! for entry in parse_status(&out.stdout)? {
//! if entry.index == StatusKind::Modified {
//! println!("modified in index: {}", entry.path);
//! }
//! }
//! # Ok(())
//! # }
//! ```
//!
//! ## Feature flags
//!
//! | Flag | Default | Purpose |
//! |------------|:-------:|----------------------------------------------------|
//! | `parse` | on | Typed parsers for status/log/diff output |
//! | `serde` | off | `Serialize`/`Deserialize` on parsed types |
//! | `workflow` | off | Higher-level helpers ([`info`], [`branches`], [`tags`], [`history`], [`workflow`]) |
//!
//! ## Error handling
//!
//! All methods return [`Result<T>`](Result). The [`Error`] enum distinguishes
//! common failure modes — `git` missing from `PATH`, a non-zero exit, a
//! timeout, an invalid builder configuration, a path that isn't a git repo,
//! and so on. The [`Error::CommandFailed`] variant carries the captured
//! `stdout`, `stderr`, and exit code so you can present a good error message
//! or retry.
//!
//! ## Design principles
//!
//! - **One struct per subcommand** under [`command`]
//! - **Async-first** on [`tokio`]
//! - **Raw output by default**; typed parsing is opt-in via the `parse` module
//! - **Escape hatches everywhere** so the crate is useful for flags we haven't
//! wrapped yet
//! - **No unsafe code**, no global state, no hidden config
pub use ;
pub use ;
pub use Repository;