Skip to content

Commit 49d8c92

Browse files
authored
Merge pull request #882 from sanjayts/git2rs_714
Add bindings for git_reference_name_is_valid, git_remote_name_is_vali…
2 parents 59bb979 + 7506425 commit 49d8c92

File tree

4 files changed

+82
-9
lines changed

4 files changed

+82
-9
lines changed

libgit2-sys/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -2251,6 +2251,7 @@ extern "C" {
22512251
) -> c_int;
22522252
pub fn git_remote_get_refspec(remote: *const git_remote, n: size_t) -> *const git_refspec;
22532253
pub fn git_remote_is_valid_name(remote_name: *const c_char) -> c_int;
2254+
pub fn git_remote_name_is_valid(valid: *mut c_int, remote_name: *const c_char) -> c_int;
22542255
pub fn git_remote_list(out: *mut git_strarray, repo: *mut git_repository) -> c_int;
22552256
pub fn git_remote_rename(
22562257
problems: *mut git_strarray,
@@ -2402,6 +2403,7 @@ extern "C" {
24022403
pub fn git_reference_is_remote(r: *const git_reference) -> c_int;
24032404
pub fn git_reference_is_tag(r: *const git_reference) -> c_int;
24042405
pub fn git_reference_is_valid_name(name: *const c_char) -> c_int;
2406+
pub fn git_reference_name_is_valid(valid: *mut c_int, refname: *const c_char) -> c_int;
24052407
pub fn git_reference_lookup(
24062408
out: *mut *mut git_reference,
24072409
repo: *mut git_repository,
@@ -3224,6 +3226,7 @@ extern "C" {
32243226
pub fn git_tag_target(target_out: *mut *mut git_object, tag: *const git_tag) -> c_int;
32253227
pub fn git_tag_target_id(tag: *const git_tag) -> *const git_oid;
32263228
pub fn git_tag_target_type(tag: *const git_tag) -> git_object_t;
3229+
pub fn git_tag_name_is_valid(valid: *mut c_int, tag_name: *const c_char) -> c_int;
32273230

32283231
// checkout
32293232
pub fn git_checkout_head(repo: *mut git_repository, opts: *const git_checkout_options)

src/reference.rs

+23-5
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ use std::str;
88
use crate::object::CastOrPanic;
99
use crate::util::{c_cmp_to_ordering, Binding};
1010
use crate::{
11-
raw, Blob, Commit, Error, Object, ObjectType, Oid, ReferenceFormat, ReferenceType, Repository,
12-
Tag, Tree,
11+
call, raw, Blob, Commit, Error, Object, ObjectType, Oid, ReferenceFormat, ReferenceType,
12+
Repository, Tag, Tree,
1313
};
1414

1515
// Not in the public header files (yet?), but a hard limit used by libgit2
@@ -62,7 +62,15 @@ impl<'repo> Reference<'repo> {
6262
pub fn is_valid_name(refname: &str) -> bool {
6363
crate::init();
6464
let refname = CString::new(refname).unwrap();
65-
unsafe { raw::git_reference_is_valid_name(refname.as_ptr()) == 1 }
65+
let mut valid: libc::c_int = 0;
66+
unsafe {
67+
call::c_try(raw::git_reference_name_is_valid(
68+
&mut valid,
69+
refname.as_ptr(),
70+
))
71+
.unwrap();
72+
}
73+
valid == 1
6674
}
6775

6876
/// Normalize reference name and check validity.
@@ -492,13 +500,23 @@ mod tests {
492500
use crate::{ObjectType, Reference, ReferenceType};
493501

494502
#[test]
495-
fn smoke() {
503+
fn is_valid_name() {
496504
assert!(Reference::is_valid_name("refs/foo"));
497505
assert!(!Reference::is_valid_name("foo"));
506+
assert!(Reference::is_valid_name("FOO_BAR"));
507+
508+
assert!(!Reference::is_valid_name("foo"));
509+
assert!(!Reference::is_valid_name("_FOO_BAR"));
498510
}
499511

500512
#[test]
501-
fn smoke2() {
513+
#[should_panic]
514+
fn is_valid_name_for_invalid_ref() {
515+
Reference::is_valid_name("ab\012");
516+
}
517+
518+
#[test]
519+
fn smoke() {
502520
let (_td, repo) = crate::test::repo_init();
503521
let mut head = repo.head().unwrap();
504522
assert!(head.is_branch());

src/remote.rs

+17-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use std::{ffi::CString, os::raw::c_char};
1010

1111
use crate::string_array::StringArray;
1212
use crate::util::Binding;
13-
use crate::{raw, Buf, Direction, Error, FetchPrune, Oid, ProxyOptions, Refspec};
13+
use crate::{call, raw, Buf, Direction, Error, FetchPrune, Oid, ProxyOptions, Refspec};
1414
use crate::{AutotagOption, Progress, RemoteCallbacks, Repository};
1515

1616
/// A structure representing a [remote][1] of a git repository.
@@ -92,7 +92,15 @@ impl<'repo> Remote<'repo> {
9292
pub fn is_valid_name(remote_name: &str) -> bool {
9393
crate::init();
9494
let remote_name = CString::new(remote_name).unwrap();
95-
unsafe { raw::git_remote_is_valid_name(remote_name.as_ptr()) == 1 }
95+
let mut valid: libc::c_int = 0;
96+
unsafe {
97+
call::c_try(raw::git_remote_name_is_valid(
98+
&mut valid,
99+
remote_name.as_ptr(),
100+
))
101+
.unwrap();
102+
}
103+
valid == 1
96104
}
97105

98106
/// Create a detached remote
@@ -851,11 +859,17 @@ mod tests {
851859
}
852860

853861
#[test]
854-
fn is_valid() {
862+
fn is_valid_name() {
855863
assert!(Remote::is_valid_name("foobar"));
856864
assert!(!Remote::is_valid_name("\x01"));
857865
}
858866

867+
#[test]
868+
#[should_panic]
869+
fn is_valid_name_for_invalid_remote() {
870+
Remote::is_valid_name("ab\012");
871+
}
872+
859873
#[test]
860874
fn transfer_cb() {
861875
let (td, _repo) = crate::test::repo_init();

src/tag.rs

+39-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1+
use std::ffi::CString;
12
use std::marker;
23
use std::mem;
34
use std::ptr;
45
use std::str;
56

67
use crate::util::Binding;
7-
use crate::{raw, signature, Error, Object, ObjectType, Oid, Signature};
8+
use crate::{call, raw, signature, Error, Object, ObjectType, Oid, Signature};
89

910
/// A structure to represent a git [tag][1]
1011
///
@@ -15,6 +16,19 @@ pub struct Tag<'repo> {
1516
}
1617

1718
impl<'repo> Tag<'repo> {
19+
/// Determine whether a tag name is valid, meaning that (when prefixed with refs/tags/) that
20+
/// it is a valid reference name, and that any additional tag name restrictions are imposed
21+
/// (eg, it cannot start with a -).
22+
pub fn is_valid_name(tag_name: &str) -> bool {
23+
crate::init();
24+
let tag_name = CString::new(tag_name).unwrap();
25+
let mut valid: libc::c_int = 0;
26+
unsafe {
27+
call::c_try(raw::git_tag_name_is_valid(&mut valid, tag_name.as_ptr())).unwrap();
28+
}
29+
valid == 1
30+
}
31+
1832
/// Get the id (SHA1) of a repository tag
1933
pub fn id(&self) -> Oid {
2034
unsafe { Binding::from_raw(raw::git_tag_id(&*self.raw)) }
@@ -141,6 +155,30 @@ impl<'repo> Drop for Tag<'repo> {
141155

142156
#[cfg(test)]
143157
mod tests {
158+
use crate::Tag;
159+
160+
// Reference -- https://git-scm.com/docs/git-check-ref-format
161+
#[test]
162+
fn name_is_valid() {
163+
assert_eq!(Tag::is_valid_name("blah_blah"), true);
164+
assert_eq!(Tag::is_valid_name("v1.2.3"), true);
165+
assert_eq!(Tag::is_valid_name("my/tag"), true);
166+
assert_eq!(Tag::is_valid_name("@"), true);
167+
168+
assert_eq!(Tag::is_valid_name("-foo"), false);
169+
assert_eq!(Tag::is_valid_name("foo:bar"), false);
170+
assert_eq!(Tag::is_valid_name("foo^bar"), false);
171+
assert_eq!(Tag::is_valid_name("foo."), false);
172+
assert_eq!(Tag::is_valid_name("@{"), false);
173+
assert_eq!(Tag::is_valid_name("as\\cd"), false);
174+
}
175+
176+
#[test]
177+
#[should_panic]
178+
fn is_valid_name_for_invalid_tag() {
179+
Tag::is_valid_name("ab\012");
180+
}
181+
144182
#[test]
145183
fn smoke() {
146184
let (_td, repo) = crate::test::repo_init();

0 commit comments

Comments
 (0)