summaryrefslogtreecommitdiffstats
path: root/vendor/git2/src/describe.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/git2/src/describe.rs')
-rw-r--r--vendor/git2/src/describe.rs201
1 files changed, 201 insertions, 0 deletions
diff --git a/vendor/git2/src/describe.rs b/vendor/git2/src/describe.rs
new file mode 100644
index 000000000..cbaa1893b
--- /dev/null
+++ b/vendor/git2/src/describe.rs
@@ -0,0 +1,201 @@
+use std::ffi::CString;
+use std::marker;
+use std::mem;
+use std::ptr;
+
+use libc::{c_int, c_uint};
+
+use crate::util::Binding;
+use crate::{raw, Buf, Error, Repository};
+
+/// The result of a `describe` operation on either an `Describe` or a
+/// `Repository`.
+pub struct Describe<'repo> {
+ raw: *mut raw::git_describe_result,
+ _marker: marker::PhantomData<&'repo Repository>,
+}
+
+/// Options which indicate how a `Describe` is created.
+pub struct DescribeOptions {
+ raw: raw::git_describe_options,
+ pattern: CString,
+}
+
+/// Options which can be used to customize how a description is formatted.
+pub struct DescribeFormatOptions {
+ raw: raw::git_describe_format_options,
+ dirty_suffix: CString,
+}
+
+impl<'repo> Describe<'repo> {
+ /// Prints this describe result, returning the result as a string.
+ pub fn format(&self, opts: Option<&DescribeFormatOptions>) -> Result<String, Error> {
+ let buf = Buf::new();
+ let opts = opts.map(|o| &o.raw as *const _).unwrap_or(ptr::null());
+ unsafe {
+ try_call!(raw::git_describe_format(buf.raw(), self.raw, opts));
+ }
+ Ok(String::from_utf8(buf.to_vec()).unwrap())
+ }
+}
+
+impl<'repo> Binding for Describe<'repo> {
+ type Raw = *mut raw::git_describe_result;
+
+ unsafe fn from_raw(raw: *mut raw::git_describe_result) -> Describe<'repo> {
+ Describe {
+ raw,
+ _marker: marker::PhantomData,
+ }
+ }
+ fn raw(&self) -> *mut raw::git_describe_result {
+ self.raw
+ }
+}
+
+impl<'repo> Drop for Describe<'repo> {
+ fn drop(&mut self) {
+ unsafe { raw::git_describe_result_free(self.raw) }
+ }
+}
+
+impl Default for DescribeFormatOptions {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl DescribeFormatOptions {
+ /// Creates a new blank set of formatting options for a description.
+ pub fn new() -> DescribeFormatOptions {
+ let mut opts = DescribeFormatOptions {
+ raw: unsafe { mem::zeroed() },
+ dirty_suffix: CString::new(Vec::new()).unwrap(),
+ };
+ opts.raw.version = 1;
+ opts.raw.abbreviated_size = 7;
+ opts
+ }
+
+ /// Sets the size of the abbreviated commit id to use.
+ ///
+ /// The value is the lower bound for the length of the abbreviated string,
+ /// and the default is 7.
+ pub fn abbreviated_size(&mut self, size: u32) -> &mut Self {
+ self.raw.abbreviated_size = size as c_uint;
+ self
+ }
+
+ /// Sets whether or not the long format is used even when a shorter name
+ /// could be used.
+ pub fn always_use_long_format(&mut self, long: bool) -> &mut Self {
+ self.raw.always_use_long_format = long as c_int;
+ self
+ }
+
+ /// If the workdir is dirty and this is set, this string will be appended to
+ /// the description string.
+ pub fn dirty_suffix(&mut self, suffix: &str) -> &mut Self {
+ self.dirty_suffix = CString::new(suffix).unwrap();
+ self.raw.dirty_suffix = self.dirty_suffix.as_ptr();
+ self
+ }
+}
+
+impl Default for DescribeOptions {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl DescribeOptions {
+ /// Creates a new blank set of formatting options for a description.
+ pub fn new() -> DescribeOptions {
+ let mut opts = DescribeOptions {
+ raw: unsafe { mem::zeroed() },
+ pattern: CString::new(Vec::new()).unwrap(),
+ };
+ opts.raw.version = 1;
+ opts.raw.max_candidates_tags = 10;
+ opts
+ }
+
+ #[allow(missing_docs)]
+ pub fn max_candidates_tags(&mut self, max: u32) -> &mut Self {
+ self.raw.max_candidates_tags = max as c_uint;
+ self
+ }
+
+ /// Sets the reference lookup strategy
+ ///
+ /// This behaves like the `--tags` option to git-describe.
+ pub fn describe_tags(&mut self) -> &mut Self {
+ self.raw.describe_strategy = raw::GIT_DESCRIBE_TAGS as c_uint;
+ self
+ }
+
+ /// Sets the reference lookup strategy
+ ///
+ /// This behaves like the `--all` option to git-describe.
+ pub fn describe_all(&mut self) -> &mut Self {
+ self.raw.describe_strategy = raw::GIT_DESCRIBE_ALL as c_uint;
+ self
+ }
+
+ /// Indicates when calculating the distance from the matching tag or
+ /// reference whether to only walk down the first-parent ancestry.
+ pub fn only_follow_first_parent(&mut self, follow: bool) -> &mut Self {
+ self.raw.only_follow_first_parent = follow as c_int;
+ self
+ }
+
+ /// If no matching tag or reference is found whether a describe option would
+ /// normally fail. This option indicates, however, that it will instead fall
+ /// back to showing the full id of the commit.
+ pub fn show_commit_oid_as_fallback(&mut self, show: bool) -> &mut Self {
+ self.raw.show_commit_oid_as_fallback = show as c_int;
+ self
+ }
+
+ #[allow(missing_docs)]
+ pub fn pattern(&mut self, pattern: &str) -> &mut Self {
+ self.pattern = CString::new(pattern).unwrap();
+ self.raw.pattern = self.pattern.as_ptr();
+ self
+ }
+}
+
+impl Binding for DescribeOptions {
+ type Raw = *mut raw::git_describe_options;
+
+ unsafe fn from_raw(_raw: *mut raw::git_describe_options) -> DescribeOptions {
+ panic!("unimplemened")
+ }
+ fn raw(&self) -> *mut raw::git_describe_options {
+ &self.raw as *const _ as *mut _
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::DescribeOptions;
+
+ #[test]
+ fn smoke() {
+ let (_td, repo) = crate::test::repo_init();
+ let head = t!(repo.head()).target().unwrap();
+
+ let d = t!(repo.describe(DescribeOptions::new().show_commit_oid_as_fallback(true)));
+ let id = head.to_string();
+ assert_eq!(t!(d.format(None)), &id[..7]);
+
+ let obj = t!(repo.find_object(head, None));
+ let sig = t!(repo.signature());
+ t!(repo.tag("foo", &obj, &sig, "message", true));
+ let d = t!(repo.describe(&DescribeOptions::new()));
+ assert_eq!(t!(d.format(None)), "foo");
+
+ let d = t!(obj.describe(&DescribeOptions::new()));
+ assert_eq!(t!(d.format(None)), "foo");
+ }
+}