oceanpkg/drop/source/
git.rs

1//! Git repository information.
2
3use std::fmt;
4use serde::{Serialize, Serializer};
5
6/// Ocean's git repository.
7pub const OCEAN_REPO: &str = env!("CARGO_PKG_REPOSITORY");
8
9flexible! {
10    /// Information about a git repository where a drop or dependency can be found.
11    #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)]
12    pub struct Git {
13        /// Where the git repository is located.
14        #[serde(alias = "repository")]
15        pub repo: String,
16        /// The specific branch to use.
17        #[serde(flatten)]
18        #[serde(skip_serializing_if = "Option::is_none")]
19        pub reference: Option<Ref>,
20    }
21}
22
23impl From<String> for Git {
24    #[inline]
25    fn from(repo: String) -> Self {
26        Self { repo, reference: None }
27    }
28}
29
30impl Git {
31    /// Creates a new instance with the given fields.
32    pub fn new<A, B>(repo: A, reference: B) -> Self
33    where
34        A: Into<String>,
35        B: Into<Option<Ref>>,
36    {
37        Self {
38            repo: repo.into(),
39            reference: reference.into(),
40        }
41    }
42
43    /// Writes the TOML form of `self` to `f`.
44    #[inline]
45    pub fn write_toml(&self, f: &mut fmt::Formatter) -> fmt::Result {
46        write!(f, r#"git = {{ repo = "{}""#, self.repo)?;
47        if let Some(reference) = &self.reference {
48            write!(f, r#", {} = "{}""#, reference.kind(), reference)?;
49        }
50        write!(f, " }}")
51    }
52
53    /// Returns a type that can be used to as `{}` to display TOML.
54    #[inline]
55    pub fn display_toml<'a>(&'a self) -> impl fmt::Display + Copy + 'a {
56        #[derive(Clone, Copy)]
57        struct Displayer<'a>(&'a Git);
58
59        impl fmt::Display for Displayer<'_> {
60            #[inline]
61            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
62                self.0.write_toml(f)
63            }
64        }
65
66        Displayer(self)
67    }
68}
69
70/// A reference to a git branch/tag/revision.
71#[derive(Clone, Debug, PartialEq, Eq, Hash, Deserialize)]
72#[serde(rename_all = "lowercase")]
73pub enum Ref {
74    // When adding a case, make sure to add it to `Ref::all`.
75
76    /// The specific git branch.
77    Branch(String),
78    /// A specific git tag.
79    Tag(String),
80    /// A specific git revision.
81    Rev(String),
82}
83
84impl Default for Ref {
85    #[inline]
86    fn default() -> Self {
87        Self::master()
88    }
89}
90
91impl fmt::Display for Ref {
92    #[inline]
93    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
94        self.as_str().fmt(f)
95    }
96}
97
98impl AsRef<str> for Ref {
99    #[inline]
100    fn as_ref(&self) -> &str {
101        self.as_str()
102    }
103}
104
105impl Serialize for Ref {
106    fn serialize<S>(&self, ser: S) -> Result<S::Ok, S::Error>
107        where S: Serializer
108    {
109        use serde::ser::SerializeMap;
110
111        let mut map = ser.serialize_map(Some(1))?;
112        map.serialize_entry(self.kind(), self.as_str())?;
113        map.end()
114    }
115}
116
117impl Ref {
118    /// Returns an array of all `Ref` variants, each pointing to `reference`.
119    pub fn all(reference: String) -> [Self; 3] {
120        [
121            Ref::Branch(reference.clone()),
122            Ref::Tag(reference.clone()),
123            Ref::Rev(reference),
124        ]
125    }
126
127    /// Creates a new `Branch` instance pointing to `reference`.
128    pub fn branch<R: Into<String>>(reference: R) -> Self {
129        Ref::Branch(reference.into())
130    }
131
132    /// Creates a new `Tag` instance pointing to `reference`.
133    pub fn tag<R: Into<String>>(reference: R) -> Self {
134        Ref::Tag(reference.into())
135    }
136
137    /// Creates a new `Rev` instance pointing to `reference`.
138    pub fn rev<R: Into<String>>(reference: R) -> Self {
139        Ref::Rev(reference.into())
140    }
141
142    /// A reference to the master branch.
143    #[inline]
144    pub fn master() -> Self {
145        Ref::branch("master")
146    }
147
148    /// Returns the reference string.
149    #[inline]
150    pub fn as_str(&self) -> &str {
151        match self {
152            Self::Branch(r) | Self::Tag(r) | Self::Rev(r) => r
153        }
154    }
155
156    /// Returns the name of the reference kind: `branch`, `tag`, or `rev`.
157    #[inline]
158    pub fn kind(&self) -> &'static str {
159        match self {
160            Self::Branch(_) => "branch",
161            Self::Tag(_) => "tag",
162            Self::Rev(_) => "rev",
163        }
164    }
165}