Skip to main content

git_proc/
commit_ish.rs

1//! Commit-ish target type and reusable typestate markers shared by command
2//! builders that take a "thing that names a tree state" — `git checkout`,
3//! `git reset`, etc.
4
5use std::ffi::OsStr;
6
7use crate::branch::Branch;
8use crate::commit_id::CommitId;
9use crate::tag::Tag;
10
11/// Anything that names a git commit-ish: a branch tip, a tag, or a specific
12/// commit object ID.
13///
14/// This is a typed subset of git's full commit-ish concept — only validated
15/// newtypes from this crate are accepted, no free-form revspecs.
16#[derive(Clone, Copy, Debug)]
17pub enum CommitIsh<'a> {
18    Branch(&'a Branch),
19    Tag(&'a Tag),
20    Commit(&'a CommitId),
21}
22
23impl AsRef<OsStr> for CommitIsh<'_> {
24    fn as_ref(&self) -> &OsStr {
25        match self {
26            Self::Branch(branch) => branch.as_ref(),
27            Self::Tag(tag) => tag.as_ref(),
28            Self::Commit(commit) => commit.as_ref(),
29        }
30    }
31}
32
33impl<'a> From<&'a Branch> for CommitIsh<'a> {
34    fn from(value: &'a Branch) -> Self {
35        Self::Branch(value)
36    }
37}
38
39impl<'a> From<&'a Tag> for CommitIsh<'a> {
40    fn from(value: &'a Tag) -> Self {
41        Self::Tag(value)
42    }
43}
44
45impl<'a> From<&'a CommitId> for CommitIsh<'a> {
46    fn from(value: &'a CommitId) -> Self {
47        Self::Commit(value)
48    }
49}
50
51/// Initial typestate: no commit-ish target chosen yet.
52#[derive(Debug)]
53pub struct NoTarget;
54
55/// Typestate after a target has been selected.
56#[derive(Debug)]
57pub struct WithTarget<'a> {
58    pub(crate) target: CommitIsh<'a>,
59}