git_proc/
rev_list.rs

1use std::path::Path;
2
3use crate::CommandError;
4
5/// Create a new `git rev-list` command builder.
6#[must_use]
7pub fn new() -> RevList<'static> {
8    RevList::new()
9}
10
11/// Builder for `git rev-list` command.
12///
13/// See `git rev-list --help` for full documentation.
14#[derive(Debug)]
15pub struct RevList<'a> {
16    repo_path: Option<&'a Path>,
17    topo_order: bool,
18    reverse: bool,
19    max_count: Option<usize>,
20    commits: Vec<&'a str>,
21}
22
23impl<'a> RevList<'a> {
24    #[must_use]
25    fn new() -> Self {
26        Self {
27            repo_path: None,
28            topo_order: false,
29            reverse: false,
30            max_count: None,
31            commits: Vec::new(),
32        }
33    }
34
35    /// Set the repository path (`-C <path>`).
36    #[must_use]
37    pub fn repo_path(mut self, path: &'a Path) -> Self {
38        self.repo_path = Some(path);
39        self
40    }
41
42    crate::flag_methods! {
43        /// Show commits in topological order.
44        ///
45        /// Corresponds to `--topo-order`.
46        pub fn topo_order / topo_order_if, topo_order, "Conditionally show commits in topological order."
47    }
48
49    crate::flag_methods! {
50        /// Output commits in reverse order.
51        ///
52        /// Corresponds to `--reverse`.
53        pub fn reverse / reverse_if, reverse, "Conditionally output commits in reverse order."
54    }
55
56    /// Limit the number of commits to output.
57    ///
58    /// Corresponds to `--max-count` or `-n`.
59    #[must_use]
60    pub fn max_count(mut self, count: usize) -> Self {
61        self.max_count = Some(count);
62        self
63    }
64
65    /// Add a commit or range to list.
66    #[must_use]
67    pub fn commit(mut self, commit: &'a str) -> Self {
68        self.commits.push(commit);
69        self
70    }
71
72    /// Capture stdout from this command.
73    #[must_use]
74    pub fn stdout(self) -> cmd_proc::Capture {
75        self.build().stdout()
76    }
77
78    /// Execute and return full output regardless of exit status.
79    ///
80    /// Use this when you need to inspect stderr on failure.
81    pub fn output(self) -> Result<cmd_proc::Output, CommandError> {
82        self.build().output()
83    }
84
85    fn build(self) -> cmd_proc::Command {
86        crate::base_command(self.repo_path)
87            .argument("rev-list")
88            .optional_argument(self.topo_order.then_some("--topo-order"))
89            .optional_argument(self.reverse.then_some("--reverse"))
90            .optional_option("--max-count", self.max_count.map(|c| c.to_string()))
91            .arguments(self.commits)
92    }
93}
94
95impl Default for RevList<'_> {
96    fn default() -> Self {
97        Self::new()
98    }
99}
100
101#[cfg(feature = "test-utils")]
102impl RevList<'_> {
103    /// Compare the built command with another command using debug representation.
104    pub fn test_eq(&self, other: &cmd_proc::Command) {
105        let command = Self {
106            repo_path: self.repo_path,
107            topo_order: self.topo_order,
108            reverse: self.reverse,
109            max_count: self.max_count,
110            commits: self.commits.clone(),
111        }
112        .build();
113        command.test_eq(other);
114    }
115}