mirror of
https://git.proxmox.com/git/libgit2
synced 2025-08-08 12:52:00 +00:00
Merge pull request #938 from nulltoken/topic/is_valid_name
Topic/is valid name
This commit is contained in:
commit
3f7c5497c3
@ -392,7 +392,8 @@ enum {
|
|||||||
/**
|
/**
|
||||||
* Control whether one-level refnames are accepted
|
* Control whether one-level refnames are accepted
|
||||||
* (i.e., refnames that do not contain multiple /-separated
|
* (i.e., refnames that do not contain multiple /-separated
|
||||||
* components)
|
* components). Those are expected to be written only using
|
||||||
|
* uppercase letters and underscore (FETCH_HEAD, ...)
|
||||||
*/
|
*/
|
||||||
GIT_REF_FORMAT_ALLOW_ONELEVEL = (1 << 0),
|
GIT_REF_FORMAT_ALLOW_ONELEVEL = (1 << 0),
|
||||||
|
|
||||||
@ -414,8 +415,6 @@ enum {
|
|||||||
* Once normalized, if the reference name is valid, it will be
|
* Once normalized, if the reference name is valid, it will be
|
||||||
* returned in the user allocated buffer.
|
* returned in the user allocated buffer.
|
||||||
*
|
*
|
||||||
* TODO: Implement handling of GIT_REF_FORMAT_REFSPEC_PATTERN
|
|
||||||
*
|
|
||||||
* @param buffer_out The user allocated buffer where the
|
* @param buffer_out The user allocated buffer where the
|
||||||
* normalized name will be stored.
|
* normalized name will be stored.
|
||||||
*
|
*
|
||||||
@ -454,6 +453,16 @@ GIT_EXTERN(int) git_reference_peel(
|
|||||||
git_reference *ref,
|
git_reference *ref,
|
||||||
git_otype type);
|
git_otype type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure the reference name is well-formed.
|
||||||
|
*
|
||||||
|
* @param refname name to be checked.
|
||||||
|
*
|
||||||
|
* @return 1 if the reference name is acceptable; 0 if it isn't
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(int) git_reference_is_valid_name(
|
||||||
|
const char *refname);
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
GIT_END_DECL
|
GIT_END_DECL
|
||||||
#endif
|
#endif
|
||||||
|
272
src/refs.c
272
src/refs.c
@ -1098,7 +1098,7 @@ int git_reference_lookup_resolved(
|
|||||||
scan->name = git__calloc(GIT_REFNAME_MAX + 1, sizeof(char));
|
scan->name = git__calloc(GIT_REFNAME_MAX + 1, sizeof(char));
|
||||||
GITERR_CHECK_ALLOC(scan->name);
|
GITERR_CHECK_ALLOC(scan->name);
|
||||||
|
|
||||||
if ((result = git_reference__normalize_name(
|
if ((result = git_reference__normalize_name_lax(
|
||||||
scan->name,
|
scan->name,
|
||||||
GIT_REFNAME_MAX,
|
GIT_REFNAME_MAX,
|
||||||
name)) < 0) {
|
name)) < 0) {
|
||||||
@ -1200,7 +1200,7 @@ int git_reference_create_symbolic(
|
|||||||
char normalized[GIT_REFNAME_MAX];
|
char normalized[GIT_REFNAME_MAX];
|
||||||
git_reference *ref = NULL;
|
git_reference *ref = NULL;
|
||||||
|
|
||||||
if (git_reference__normalize_name(
|
if (git_reference__normalize_name_lax(
|
||||||
normalized,
|
normalized,
|
||||||
sizeof(normalized),
|
sizeof(normalized),
|
||||||
name) < 0)
|
name) < 0)
|
||||||
@ -1239,7 +1239,7 @@ int git_reference_create_oid(
|
|||||||
git_reference *ref = NULL;
|
git_reference *ref = NULL;
|
||||||
char normalized[GIT_REFNAME_MAX];
|
char normalized[GIT_REFNAME_MAX];
|
||||||
|
|
||||||
if (git_reference__normalize_name_oid(
|
if (git_reference__normalize_name_lax(
|
||||||
normalized,
|
normalized,
|
||||||
sizeof(normalized),
|
sizeof(normalized),
|
||||||
name) < 0)
|
name) < 0)
|
||||||
@ -1322,7 +1322,7 @@ int git_reference_set_target(git_reference *ref, const char *target)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (git_reference__normalize_name(
|
if (git_reference__normalize_name_lax(
|
||||||
normalized,
|
normalized,
|
||||||
sizeof(normalized),
|
sizeof(normalized),
|
||||||
target))
|
target))
|
||||||
@ -1584,106 +1584,175 @@ static int is_valid_ref_char(char ch)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ensure_segment_validity(const char *name)
|
||||||
|
{
|
||||||
|
const char *current = name;
|
||||||
|
char prev = '\0';
|
||||||
|
|
||||||
|
if (*current == '.')
|
||||||
|
return -1; /* Refname starts with "." */
|
||||||
|
|
||||||
|
for (current = name; ; current++) {
|
||||||
|
if (*current == '\0' || *current == '/')
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!is_valid_ref_char(*current))
|
||||||
|
return -1; /* Illegal character in refname */
|
||||||
|
|
||||||
|
if (prev == '.' && *current == '.')
|
||||||
|
return -1; /* Refname contains ".." */
|
||||||
|
|
||||||
|
if (prev == '@' && *current == '{')
|
||||||
|
return -1; /* Refname contains "@{" */
|
||||||
|
|
||||||
|
prev = *current;
|
||||||
|
}
|
||||||
|
|
||||||
|
return current - name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_all_caps_and_underscore(const char *name, int len)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
assert(name && len > 0);
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
c = name[i];
|
||||||
|
if ((c < 'A' || c > 'Z') && c != '_')
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*name == '_' || name[len - 1] == '_')
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int git_reference__normalize_name(
|
||||||
|
git_buf *buf,
|
||||||
|
const char *name,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
// Inspired from https://github.com/git/git/blob/f06d47e7e0d9db709ee204ed13a8a7486149f494/refs.c#L36-100
|
||||||
|
|
||||||
|
char *current;
|
||||||
|
int segment_len, segments_count = 0, error = -1;
|
||||||
|
unsigned int process_flags;
|
||||||
|
bool normalize = (buf != NULL);
|
||||||
|
assert(name);
|
||||||
|
|
||||||
|
process_flags = flags;
|
||||||
|
current = (char *)name;
|
||||||
|
|
||||||
|
if (normalize)
|
||||||
|
git_buf_clear(buf);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
segment_len = ensure_segment_validity(current);
|
||||||
|
if (segment_len < 0) {
|
||||||
|
if ((process_flags & GIT_REF_FORMAT_REFSPEC_PATTERN) &&
|
||||||
|
current[0] == '*' &&
|
||||||
|
(current[1] == '\0' || current[1] == '/')) {
|
||||||
|
/* Accept one wildcard as a full refname component. */
|
||||||
|
process_flags &= ~GIT_REF_FORMAT_REFSPEC_PATTERN;
|
||||||
|
segment_len = 1;
|
||||||
|
} else
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (segment_len > 0) {
|
||||||
|
if (normalize) {
|
||||||
|
int cur_len = git_buf_len(buf);
|
||||||
|
|
||||||
|
git_buf_joinpath(buf, git_buf_cstr(buf), current);
|
||||||
|
git_buf_truncate(buf,
|
||||||
|
cur_len + segment_len + (segments_count ? 1 : 0));
|
||||||
|
|
||||||
|
if (git_buf_oom(buf))
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
segments_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current[segment_len] == '\0')
|
||||||
|
break;
|
||||||
|
|
||||||
|
current += segment_len + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A refname can not be empty */
|
||||||
|
if (segment_len == 0 && segments_count == 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/* A refname can not end with "." */
|
||||||
|
if (current[segment_len - 1] == '.')
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/* A refname can not end with "/" */
|
||||||
|
if (current[segment_len - 1] == '/')
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/* A refname can not end with ".lock" */
|
||||||
|
if (!git__suffixcmp(name, GIT_FILELOCK_EXTENSION))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if ((segments_count == 1 ) && !(flags & GIT_REF_FORMAT_ALLOW_ONELEVEL))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if ((segments_count == 1 ) &&
|
||||||
|
!(is_all_caps_and_underscore(name, segment_len) ||
|
||||||
|
((flags & GIT_REF_FORMAT_REFSPEC_PATTERN) && !strcmp("*", name))))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if ((segments_count > 1)
|
||||||
|
&& (is_all_caps_and_underscore(name, strchr(name, '/') - name)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
error = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (error)
|
||||||
|
giterr_set(
|
||||||
|
GITERR_REFERENCE,
|
||||||
|
"The given reference name '%s' is not valid", name);
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
int git_reference_normalize_name(
|
int git_reference_normalize_name(
|
||||||
char *buffer_out,
|
char *buffer_out,
|
||||||
size_t buffer_size,
|
size_t buffer_size,
|
||||||
const char *name,
|
const char *name,
|
||||||
unsigned int flags)
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
const char *name_end, *buffer_out_start;
|
git_buf buf = GIT_BUF_INIT;
|
||||||
const char *current;
|
int error;
|
||||||
int contains_a_slash = 0;
|
|
||||||
|
|
||||||
assert(name && buffer_out);
|
if ((error = git_reference__normalize_name(&buf, name, flags)) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
if (flags & GIT_REF_FORMAT_REFSPEC_PATTERN) {
|
if (git_buf_len(&buf) > buffer_size - 1) {
|
||||||
giterr_set(GITERR_INVALID, "Unimplemented");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer_out_start = buffer_out;
|
|
||||||
current = name;
|
|
||||||
name_end = name + strlen(name);
|
|
||||||
|
|
||||||
/* Terminating null byte */
|
|
||||||
buffer_size--;
|
|
||||||
|
|
||||||
/* A refname can not be empty */
|
|
||||||
if (name_end == name)
|
|
||||||
goto invalid_name;
|
|
||||||
|
|
||||||
/* A refname can not end with a dot or a slash */
|
|
||||||
if (*(name_end - 1) == '.' || *(name_end - 1) == '/')
|
|
||||||
goto invalid_name;
|
|
||||||
|
|
||||||
while (current < name_end && buffer_size > 0) {
|
|
||||||
if (!is_valid_ref_char(*current))
|
|
||||||
goto invalid_name;
|
|
||||||
|
|
||||||
if (buffer_out > buffer_out_start) {
|
|
||||||
char prev = *(buffer_out - 1);
|
|
||||||
|
|
||||||
/* A refname can not start with a dot nor contain a double dot */
|
|
||||||
if (*current == '.' && ((prev == '.') || (prev == '/')))
|
|
||||||
goto invalid_name;
|
|
||||||
|
|
||||||
/* '@{' is forbidden within a refname */
|
|
||||||
if (*current == '{' && prev == '@')
|
|
||||||
goto invalid_name;
|
|
||||||
|
|
||||||
/* Prevent multiple slashes from being added to the output */
|
|
||||||
if (*current == '/' && prev == '/') {
|
|
||||||
current++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*current == '/') {
|
|
||||||
if (buffer_out > buffer_out_start)
|
|
||||||
contains_a_slash = 1;
|
|
||||||
else {
|
|
||||||
current++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*buffer_out++ = *current++;
|
|
||||||
buffer_size--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current < name_end) {
|
|
||||||
giterr_set(
|
giterr_set(
|
||||||
GITERR_REFERENCE,
|
GITERR_REFERENCE,
|
||||||
"The provided buffer is too short to hold the normalization of '%s'", name);
|
"The provided buffer is too short to hold the normalization of '%s'", name);
|
||||||
return GIT_EBUFS;
|
error = GIT_EBUFS;
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Object id refname have to contain at least one slash, except
|
git_buf_copy_cstr(buffer_out, buffer_size, &buf);
|
||||||
* for HEAD in a detached state or MERGE_HEAD if we're in the
|
|
||||||
* middle of a merge */
|
|
||||||
if (!(flags & GIT_REF_FORMAT_ALLOW_ONELEVEL) &&
|
|
||||||
!contains_a_slash &&
|
|
||||||
strcmp(name, GIT_HEAD_FILE) != 0 &&
|
|
||||||
strcmp(name, GIT_MERGE_HEAD_FILE) != 0 &&
|
|
||||||
strcmp(name, GIT_FETCH_HEAD_FILE) != 0)
|
|
||||||
goto invalid_name;
|
|
||||||
|
|
||||||
/* A refname can not end with ".lock" */
|
error = 0;
|
||||||
if (!git__suffixcmp(name, GIT_FILELOCK_EXTENSION))
|
|
||||||
goto invalid_name;
|
|
||||||
|
|
||||||
*buffer_out = '\0';
|
cleanup:
|
||||||
|
git_buf_free(&buf);
|
||||||
return 0;
|
return error;
|
||||||
|
|
||||||
invalid_name:
|
|
||||||
giterr_set(
|
|
||||||
GITERR_REFERENCE,
|
|
||||||
"The given reference name '%s' is not valid", name);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_reference__normalize_name(
|
int git_reference__normalize_name_lax(
|
||||||
char *buffer_out,
|
char *buffer_out,
|
||||||
size_t out_size,
|
size_t out_size,
|
||||||
const char *name)
|
const char *name)
|
||||||
@ -1694,19 +1763,6 @@ int git_reference__normalize_name(
|
|||||||
name,
|
name,
|
||||||
GIT_REF_FORMAT_ALLOW_ONELEVEL);
|
GIT_REF_FORMAT_ALLOW_ONELEVEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_reference__normalize_name_oid(
|
|
||||||
char *buffer_out,
|
|
||||||
size_t out_size,
|
|
||||||
const char *name)
|
|
||||||
{
|
|
||||||
return git_reference_normalize_name(
|
|
||||||
buffer_out,
|
|
||||||
out_size,
|
|
||||||
name,
|
|
||||||
GIT_REF_FORMAT_NORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define GIT_REF_TYPEMASK (GIT_REF_OID | GIT_REF_SYMBOLIC)
|
#define GIT_REF_TYPEMASK (GIT_REF_OID | GIT_REF_SYMBOLIC)
|
||||||
|
|
||||||
int git_reference_cmp(git_reference *ref1, git_reference *ref2)
|
int git_reference_cmp(git_reference *ref1, git_reference *ref2)
|
||||||
@ -1895,3 +1951,19 @@ cleanup:
|
|||||||
git_reference_free(resolved);
|
git_reference_free(resolved);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int git_reference__is_valid_name(
|
||||||
|
const char *refname,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
giterr_clear();
|
||||||
|
return git_reference__normalize_name(NULL, refname, flags) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int git_reference_is_valid_name(
|
||||||
|
const char *refname)
|
||||||
|
{
|
||||||
|
return git_reference__is_valid_name(
|
||||||
|
refname,
|
||||||
|
GIT_REF_FORMAT_ALLOW_ONELEVEL);
|
||||||
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "git2/oid.h"
|
#include "git2/oid.h"
|
||||||
#include "git2/refs.h"
|
#include "git2/refs.h"
|
||||||
#include "strmap.h"
|
#include "strmap.h"
|
||||||
|
#include "buffer.h"
|
||||||
|
|
||||||
#define GIT_REFS_DIR "refs/"
|
#define GIT_REFS_DIR "refs/"
|
||||||
#define GIT_REFS_HEADS_DIR GIT_REFS_DIR "heads/"
|
#define GIT_REFS_HEADS_DIR GIT_REFS_DIR "heads/"
|
||||||
@ -52,8 +53,9 @@ typedef struct {
|
|||||||
|
|
||||||
void git_repository__refcache_free(git_refcache *refs);
|
void git_repository__refcache_free(git_refcache *refs);
|
||||||
|
|
||||||
int git_reference__normalize_name(char *buffer_out, size_t out_size, const char *name);
|
int git_reference__normalize_name_lax(char *buffer_out, size_t out_size, const char *name);
|
||||||
int git_reference__normalize_name_oid(char *buffer_out, size_t out_size, const char *name);
|
int git_reference__normalize_name(git_buf *buf, const char *name, unsigned int flags);
|
||||||
|
int git_reference__is_valid_name(const char *refname, unsigned int flags);
|
||||||
int git_reference__update(git_repository *repo, const git_oid *oid, const char *ref_name);
|
int git_reference__update(git_repository *repo, const git_oid *oid, const char *ref_name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
113
src/refspec.c
113
src/refspec.c
@ -11,6 +11,119 @@
|
|||||||
#include "refspec.h"
|
#include "refspec.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "posix.h"
|
#include "posix.h"
|
||||||
|
#include "refs.h"
|
||||||
|
|
||||||
|
int git_refspec__parse(git_refspec *refspec, const char *input, bool is_fetch)
|
||||||
|
{
|
||||||
|
// Ported from https://github.com/git/git/blob/f06d47e7e0d9db709ee204ed13a8a7486149f494/remote.c#L518-636
|
||||||
|
|
||||||
|
size_t llen;
|
||||||
|
int is_glob = 0;
|
||||||
|
const char *lhs, *rhs;
|
||||||
|
int flags;
|
||||||
|
|
||||||
|
assert(refspec && input);
|
||||||
|
|
||||||
|
memset(refspec, 0x0, sizeof(git_refspec));
|
||||||
|
|
||||||
|
lhs = input;
|
||||||
|
if (*lhs == '+') {
|
||||||
|
refspec->force = 1;
|
||||||
|
lhs++;
|
||||||
|
}
|
||||||
|
|
||||||
|
rhs = strrchr(lhs, ':');
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Before going on, special case ":" (or "+:") as a refspec
|
||||||
|
* for matching refs.
|
||||||
|
*/
|
||||||
|
if (!is_fetch && rhs == lhs && rhs[1] == '\0') {
|
||||||
|
refspec->matching = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rhs) {
|
||||||
|
size_t rlen = strlen(++rhs);
|
||||||
|
is_glob = (1 <= rlen && strchr(rhs, '*'));
|
||||||
|
refspec->dst = git__strndup(rhs, rlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
llen = (rhs ? (size_t)(rhs - lhs - 1) : strlen(lhs));
|
||||||
|
if (1 <= llen && memchr(lhs, '*', llen)) {
|
||||||
|
if ((rhs && !is_glob) || (!rhs && is_fetch))
|
||||||
|
goto invalid;
|
||||||
|
is_glob = 1;
|
||||||
|
} else if (rhs && is_glob)
|
||||||
|
goto invalid;
|
||||||
|
|
||||||
|
refspec->pattern = is_glob;
|
||||||
|
refspec->src = git__strndup(lhs, llen);
|
||||||
|
flags = GIT_REF_FORMAT_ALLOW_ONELEVEL
|
||||||
|
| (is_glob ? GIT_REF_FORMAT_REFSPEC_PATTERN : 0);
|
||||||
|
|
||||||
|
if (is_fetch) {
|
||||||
|
/*
|
||||||
|
* LHS
|
||||||
|
* - empty is allowed; it means HEAD.
|
||||||
|
* - otherwise it must be a valid looking ref.
|
||||||
|
*/
|
||||||
|
if (!*refspec->src)
|
||||||
|
; /* empty is ok */
|
||||||
|
else if (!git_reference__is_valid_name(refspec->src, flags))
|
||||||
|
goto invalid;
|
||||||
|
/*
|
||||||
|
* RHS
|
||||||
|
* - missing is ok, and is same as empty.
|
||||||
|
* - empty is ok; it means not to store.
|
||||||
|
* - otherwise it must be a valid looking ref.
|
||||||
|
*/
|
||||||
|
if (!refspec->dst)
|
||||||
|
; /* ok */
|
||||||
|
else if (!*refspec->dst)
|
||||||
|
; /* ok */
|
||||||
|
else if (!git_reference__is_valid_name(refspec->dst, flags))
|
||||||
|
goto invalid;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* LHS
|
||||||
|
* - empty is allowed; it means delete.
|
||||||
|
* - when wildcarded, it must be a valid looking ref.
|
||||||
|
* - otherwise, it must be an extended SHA-1, but
|
||||||
|
* there is no existing way to validate this.
|
||||||
|
*/
|
||||||
|
if (!*refspec->src)
|
||||||
|
; /* empty is ok */
|
||||||
|
else if (is_glob) {
|
||||||
|
if (!git_reference__is_valid_name(refspec->src, flags))
|
||||||
|
goto invalid;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
; /* anything goes, for now */
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* RHS
|
||||||
|
* - missing is allowed, but LHS then must be a
|
||||||
|
* valid looking ref.
|
||||||
|
* - empty is not allowed.
|
||||||
|
* - otherwise it must be a valid looking ref.
|
||||||
|
*/
|
||||||
|
if (!refspec->dst) {
|
||||||
|
if (!git_reference__is_valid_name(refspec->src, flags))
|
||||||
|
goto invalid;
|
||||||
|
} else if (!*refspec->dst) {
|
||||||
|
goto invalid;
|
||||||
|
} else {
|
||||||
|
if (!git_reference__is_valid_name(refspec->dst, flags))
|
||||||
|
goto invalid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
invalid:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
int git_refspec_parse(git_refspec *refspec, const char *str)
|
int git_refspec_parse(git_refspec *refspec, const char *str)
|
||||||
{
|
{
|
||||||
|
@ -20,6 +20,10 @@ struct git_refspec {
|
|||||||
};
|
};
|
||||||
|
|
||||||
int git_refspec_parse(struct git_refspec *refspec, const char *str);
|
int git_refspec_parse(struct git_refspec *refspec, const char *str);
|
||||||
|
int git_refspec__parse(
|
||||||
|
struct git_refspec *refspec,
|
||||||
|
const char *str,
|
||||||
|
bool is_fetch);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transform a reference to its target following the refspec's rules,
|
* Transform a reference to its target following the refspec's rules,
|
||||||
|
@ -50,6 +50,11 @@ static int disambiguate_refname(git_reference **out, git_repository *repo, const
|
|||||||
if ((error = git_buf_printf(&refnamebuf, formatters[i], git_buf_cstr(&name))) < 0)
|
if ((error = git_buf_printf(&refnamebuf, formatters[i], git_buf_cstr(&name))) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!git_reference_is_valid_name(git_buf_cstr(&refnamebuf))) {
|
||||||
|
error = GIT_ENOTFOUND;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
error = git_reference_lookup_resolved(&ref, repo, git_buf_cstr(&refnamebuf), -1);
|
error = git_reference_lookup_resolved(&ref, repo, git_buf_cstr(&refnamebuf), -1);
|
||||||
|
|
||||||
if (!error) {
|
if (!error) {
|
||||||
|
83
tests-clar/network/refspecs.c
Normal file
83
tests-clar/network/refspecs.c
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
#include "clar_libgit2.h"
|
||||||
|
#include "refspec.h"
|
||||||
|
#include "remote.h"
|
||||||
|
|
||||||
|
static void assert_refspec(unsigned int direction, const char *input, bool is_expected_to_be_valid)
|
||||||
|
{
|
||||||
|
git_refspec refspec;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
error = git_refspec__parse(&refspec, input, direction == GIT_DIR_FETCH);
|
||||||
|
|
||||||
|
if (is_expected_to_be_valid)
|
||||||
|
cl_assert_equal_i(0, error);
|
||||||
|
else
|
||||||
|
cl_assert_equal_i(GIT_ERROR, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_network_refspecs__parsing(void)
|
||||||
|
{
|
||||||
|
// Ported from https://github.com/git/git/blob/abd2bde78bd994166900290434a2048e660dabed/t/t5511-refspec.sh
|
||||||
|
|
||||||
|
assert_refspec(GIT_DIR_PUSH, "", false);
|
||||||
|
assert_refspec(GIT_DIR_PUSH, ":", true);
|
||||||
|
assert_refspec(GIT_DIR_PUSH, "::", false);
|
||||||
|
assert_refspec(GIT_DIR_PUSH, "+:", true);
|
||||||
|
|
||||||
|
assert_refspec(GIT_DIR_FETCH, "", true);
|
||||||
|
assert_refspec(GIT_DIR_PUSH, ":", true);
|
||||||
|
assert_refspec(GIT_DIR_FETCH, "::", false);
|
||||||
|
|
||||||
|
assert_refspec(GIT_DIR_PUSH, "refs/heads/*:refs/remotes/frotz/*", true);
|
||||||
|
assert_refspec(GIT_DIR_PUSH, "refs/heads/*:refs/remotes/frotz", false);
|
||||||
|
assert_refspec(GIT_DIR_PUSH, "refs/heads:refs/remotes/frotz/*", false);
|
||||||
|
assert_refspec(GIT_DIR_PUSH, "refs/heads/master:refs/remotes/frotz/xyzzy", true);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These have invalid LHS, but we do not have a formal "valid sha-1
|
||||||
|
* expression syntax checker" so they are not checked with the current
|
||||||
|
* code. They will be caught downstream anyway, but we may want to
|
||||||
|
* have tighter check later...
|
||||||
|
*/
|
||||||
|
//assert_refspec(GIT_DIR_PUSH, "refs/heads/master::refs/remotes/frotz/xyzzy", false);
|
||||||
|
//assert_refspec(GIT_DIR_PUSH, "refs/heads/maste :refs/remotes/frotz/xyzzy", false);
|
||||||
|
|
||||||
|
assert_refspec(GIT_DIR_FETCH, "refs/heads/*:refs/remotes/frotz/*", true);
|
||||||
|
assert_refspec(GIT_DIR_FETCH, "refs/heads/*:refs/remotes/frotz", false);
|
||||||
|
assert_refspec(GIT_DIR_FETCH, "refs/heads:refs/remotes/frotz/*", false);
|
||||||
|
assert_refspec(GIT_DIR_FETCH, "refs/heads/master:refs/remotes/frotz/xyzzy", true);
|
||||||
|
assert_refspec(GIT_DIR_FETCH, "refs/heads/master::refs/remotes/frotz/xyzzy", false);
|
||||||
|
assert_refspec(GIT_DIR_FETCH, "refs/heads/maste :refs/remotes/frotz/xyzzy", false);
|
||||||
|
|
||||||
|
assert_refspec(GIT_DIR_PUSH, "master~1:refs/remotes/frotz/backup", true);
|
||||||
|
assert_refspec(GIT_DIR_FETCH, "master~1:refs/remotes/frotz/backup", false);
|
||||||
|
assert_refspec(GIT_DIR_PUSH, "HEAD~4:refs/remotes/frotz/new", true);
|
||||||
|
assert_refspec(GIT_DIR_FETCH, "HEAD~4:refs/remotes/frotz/new", false);
|
||||||
|
|
||||||
|
assert_refspec(GIT_DIR_PUSH, "HEAD", true);
|
||||||
|
assert_refspec(GIT_DIR_FETCH, "HEAD", true);
|
||||||
|
assert_refspec(GIT_DIR_PUSH, "refs/heads/ nitfol", false);
|
||||||
|
assert_refspec(GIT_DIR_FETCH, "refs/heads/ nitfol", false);
|
||||||
|
|
||||||
|
assert_refspec(GIT_DIR_PUSH, "HEAD:", false);
|
||||||
|
assert_refspec(GIT_DIR_FETCH, "HEAD:", true);
|
||||||
|
assert_refspec(GIT_DIR_PUSH, "refs/heads/ nitfol:", false);
|
||||||
|
assert_refspec(GIT_DIR_FETCH, "refs/heads/ nitfol:", false);
|
||||||
|
|
||||||
|
assert_refspec(GIT_DIR_PUSH, ":refs/remotes/frotz/deleteme", true);
|
||||||
|
assert_refspec(GIT_DIR_FETCH, ":refs/remotes/frotz/HEAD-to-me", true);
|
||||||
|
assert_refspec(GIT_DIR_PUSH, ":refs/remotes/frotz/delete me", false);
|
||||||
|
assert_refspec(GIT_DIR_FETCH, ":refs/remotes/frotz/HEAD to me", false);
|
||||||
|
|
||||||
|
assert_refspec(GIT_DIR_FETCH, "refs/heads/*/for-linus:refs/remotes/mine/*-blah", false);
|
||||||
|
assert_refspec(GIT_DIR_PUSH, "refs/heads/*/for-linus:refs/remotes/mine/*-blah", false);
|
||||||
|
|
||||||
|
assert_refspec(GIT_DIR_FETCH, "refs/heads*/for-linus:refs/remotes/mine/*", false);
|
||||||
|
assert_refspec(GIT_DIR_PUSH, "refs/heads*/for-linus:refs/remotes/mine/*", false);
|
||||||
|
|
||||||
|
assert_refspec(GIT_DIR_FETCH, "refs/heads/*/*/for-linus:refs/remotes/mine/*", false);
|
||||||
|
assert_refspec(GIT_DIR_PUSH, "refs/heads/*/*/for-linus:refs/remotes/mine/*", false);
|
||||||
|
|
||||||
|
assert_refspec(GIT_DIR_FETCH, "refs/heads/*/for-linus:refs/remotes/mine/*", true);
|
||||||
|
assert_refspec(GIT_DIR_PUSH, "refs/heads/*/for-linus:refs/remotes/mine/*", true);
|
||||||
|
}
|
@ -27,7 +27,7 @@ void test_refs_create__symbolic(void)
|
|||||||
git_oid id;
|
git_oid id;
|
||||||
git_buf ref_path = GIT_BUF_INIT;
|
git_buf ref_path = GIT_BUF_INIT;
|
||||||
|
|
||||||
const char *new_head_tracker = "another-head-tracker";
|
const char *new_head_tracker = "ANOTHER_HEAD_TRACKER";
|
||||||
|
|
||||||
git_oid_fromstr(&id, current_master_tip);
|
git_oid_fromstr(&id, current_master_tip);
|
||||||
|
|
||||||
|
23
tests-clar/refs/isvalidname.c
Normal file
23
tests-clar/refs/isvalidname.c
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#include "clar_libgit2.h"
|
||||||
|
|
||||||
|
void test_refs_isvalidname__can_detect_invalid_formats(void)
|
||||||
|
{
|
||||||
|
cl_assert_equal_i(false, git_reference_is_valid_name("refs/tags/0.17.0^{}"));
|
||||||
|
cl_assert_equal_i(false, git_reference_is_valid_name("TWO/LEVELS"));
|
||||||
|
cl_assert_equal_i(false, git_reference_is_valid_name("ONE.LEVEL"));
|
||||||
|
cl_assert_equal_i(false, git_reference_is_valid_name("HEAD/"));
|
||||||
|
cl_assert_equal_i(false, git_reference_is_valid_name("NO_TRAILING_UNDERSCORE_"));
|
||||||
|
cl_assert_equal_i(false, git_reference_is_valid_name("_NO_LEADING_UNDERSCORE"));
|
||||||
|
cl_assert_equal_i(false, git_reference_is_valid_name("HEAD/aa"));
|
||||||
|
cl_assert_equal_i(false, git_reference_is_valid_name("lower_case"));
|
||||||
|
cl_assert_equal_i(false, git_reference_is_valid_name(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_refs_isvalidname__wont_hopefully_choke_on_valid_formats(void)
|
||||||
|
{
|
||||||
|
cl_assert_equal_i(true, git_reference_is_valid_name("refs/tags/0.17.0"));
|
||||||
|
cl_assert_equal_i(true, git_reference_is_valid_name("refs/LEVELS"));
|
||||||
|
cl_assert_equal_i(true, git_reference_is_valid_name("HEAD"));
|
||||||
|
cl_assert_equal_i(true, git_reference_is_valid_name("ONE_LEVEL"));
|
||||||
|
cl_assert_equal_i(true, git_reference_is_valid_name("refs/stash"));
|
||||||
|
}
|
@ -25,7 +25,7 @@ void test_refs_lookup__with_resolve(void)
|
|||||||
cl_assert(git_reference_cmp(a, b) == 0);
|
cl_assert(git_reference_cmp(a, b) == 0);
|
||||||
git_reference_free(b);
|
git_reference_free(b);
|
||||||
|
|
||||||
cl_git_pass(git_reference_lookup_resolved(&b, g_repo, "head-tracker", 5));
|
cl_git_pass(git_reference_lookup_resolved(&b, g_repo, "HEAD_TRACKER", 5));
|
||||||
cl_assert(git_reference_cmp(a, b) == 0);
|
cl_assert(git_reference_cmp(a, b) == 0);
|
||||||
git_reference_free(b);
|
git_reference_free(b);
|
||||||
|
|
||||||
|
@ -5,9 +5,10 @@
|
|||||||
#include "reflog.h"
|
#include "reflog.h"
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
static void ensure_refname_normalized(unsigned int flags,
|
static void ensure_refname_normalized(
|
||||||
const char *input_refname,
|
unsigned int flags,
|
||||||
const char *expected_refname)
|
const char *input_refname,
|
||||||
|
const char *expected_refname)
|
||||||
{
|
{
|
||||||
char buffer_out[GIT_REFNAME_MAX];
|
char buffer_out[GIT_REFNAME_MAX];
|
||||||
|
|
||||||
@ -38,17 +39,7 @@ void test_refs_normalize__can_normalize_a_direct_reference_name(void)
|
|||||||
ensure_refname_normalized(
|
ensure_refname_normalized(
|
||||||
GIT_REF_FORMAT_NORMAL, "refs/heads/v@ation", "refs/heads/v@ation");
|
GIT_REF_FORMAT_NORMAL, "refs/heads/v@ation", "refs/heads/v@ation");
|
||||||
ensure_refname_normalized(
|
ensure_refname_normalized(
|
||||||
GIT_REF_FORMAT_NORMAL, "/refs///heads///a", "refs/heads/a");
|
GIT_REF_FORMAT_NORMAL, "refs///heads///a", "refs/heads/a");
|
||||||
}
|
|
||||||
|
|
||||||
void test_refs_normalize__can_normalize_some_specific_one_level_direct_reference_names(void)
|
|
||||||
{
|
|
||||||
ensure_refname_normalized(
|
|
||||||
GIT_REF_FORMAT_NORMAL, "HEAD", "HEAD");
|
|
||||||
ensure_refname_normalized(
|
|
||||||
GIT_REF_FORMAT_NORMAL, "MERGE_HEAD", "MERGE_HEAD");
|
|
||||||
ensure_refname_normalized(
|
|
||||||
GIT_REF_FORMAT_NORMAL, "FETCH_HEAD", "FETCH_HEAD");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_refs_normalize__cannot_normalize_any_direct_reference_name(void)
|
void test_refs_normalize__cannot_normalize_any_direct_reference_name(void)
|
||||||
@ -61,6 +52,8 @@ void test_refs_normalize__cannot_normalize_any_direct_reference_name(void)
|
|||||||
GIT_REF_FORMAT_NORMAL, "//a");
|
GIT_REF_FORMAT_NORMAL, "//a");
|
||||||
ensure_refname_invalid(
|
ensure_refname_invalid(
|
||||||
GIT_REF_FORMAT_NORMAL, "");
|
GIT_REF_FORMAT_NORMAL, "");
|
||||||
|
ensure_refname_invalid(
|
||||||
|
GIT_REF_FORMAT_NORMAL, "/refs/heads/a/");
|
||||||
ensure_refname_invalid(
|
ensure_refname_invalid(
|
||||||
GIT_REF_FORMAT_NORMAL, "refs/heads/a/");
|
GIT_REF_FORMAT_NORMAL, "refs/heads/a/");
|
||||||
ensure_refname_invalid(
|
ensure_refname_invalid(
|
||||||
@ -97,9 +90,9 @@ void test_refs_normalize__symbolic(void)
|
|||||||
GIT_REF_FORMAT_ALLOW_ONELEVEL, "///");
|
GIT_REF_FORMAT_ALLOW_ONELEVEL, "///");
|
||||||
|
|
||||||
ensure_refname_normalized(
|
ensure_refname_normalized(
|
||||||
GIT_REF_FORMAT_ALLOW_ONELEVEL, "a", "a");
|
GIT_REF_FORMAT_ALLOW_ONELEVEL, "ALL_CAPS_AND_UNDERSCORES", "ALL_CAPS_AND_UNDERSCORES");
|
||||||
ensure_refname_normalized(
|
ensure_refname_normalized(
|
||||||
GIT_REF_FORMAT_ALLOW_ONELEVEL, "a/b", "a/b");
|
GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/MixedCasing", "refs/MixedCasing");
|
||||||
ensure_refname_normalized(
|
ensure_refname_normalized(
|
||||||
GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs///heads///a", "refs/heads/a");
|
GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs///heads///a", "refs/heads/a");
|
||||||
|
|
||||||
@ -115,7 +108,7 @@ void test_refs_normalize__symbolic(void)
|
|||||||
* See https://github.com/spearce/JGit/commit/e4bf8f6957bbb29362575d641d1e77a02d906739 */
|
* See https://github.com/spearce/JGit/commit/e4bf8f6957bbb29362575d641d1e77a02d906739 */
|
||||||
void test_refs_normalize__jgit_suite(void)
|
void test_refs_normalize__jgit_suite(void)
|
||||||
{
|
{
|
||||||
// tests borrowed from JGit
|
// tests borrowed from JGit
|
||||||
|
|
||||||
/* EmptyString */
|
/* EmptyString */
|
||||||
ensure_refname_invalid(
|
ensure_refname_invalid(
|
||||||
@ -127,10 +120,9 @@ void test_refs_normalize__jgit_suite(void)
|
|||||||
ensure_refname_invalid(
|
ensure_refname_invalid(
|
||||||
GIT_REF_FORMAT_NORMAL, "master");
|
GIT_REF_FORMAT_NORMAL, "master");
|
||||||
ensure_refname_normalized(
|
ensure_refname_normalized(
|
||||||
GIT_REF_FORMAT_ALLOW_ONELEVEL, "heads/master", "heads/master");
|
GIT_REF_FORMAT_NORMAL, "heads/master", "heads/master");
|
||||||
|
|
||||||
/* ValidHead */
|
/* ValidHead */
|
||||||
|
|
||||||
ensure_refname_normalized(
|
ensure_refname_normalized(
|
||||||
GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/master", "refs/heads/master");
|
GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/master", "refs/heads/master");
|
||||||
ensure_refname_normalized(
|
ensure_refname_normalized(
|
||||||
@ -310,7 +302,61 @@ void test_refs_normalize__buffer_has_to_be_big_enough_to_hold_the_normalized_ver
|
|||||||
char buffer_out[21];
|
char buffer_out[21];
|
||||||
|
|
||||||
cl_git_pass(git_reference_normalize_name(
|
cl_git_pass(git_reference_normalize_name(
|
||||||
buffer_out, 21, "//refs//heads/long///name", GIT_REF_FORMAT_NORMAL));
|
buffer_out, 21, "refs//heads///long///name", GIT_REF_FORMAT_NORMAL));
|
||||||
cl_git_fail(git_reference_normalize_name(
|
cl_git_fail(git_reference_normalize_name(
|
||||||
buffer_out, 20, "//refs//heads/long///name", GIT_REF_FORMAT_NORMAL));
|
buffer_out, 20, "refs//heads///long///name", GIT_REF_FORMAT_NORMAL));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ONE_LEVEL_AND_REFSPEC \
|
||||||
|
GIT_REF_FORMAT_ALLOW_ONELEVEL \
|
||||||
|
| GIT_REF_FORMAT_REFSPEC_PATTERN
|
||||||
|
|
||||||
|
void test_refs_normalize__refspec_pattern(void)
|
||||||
|
{
|
||||||
|
ensure_refname_invalid(
|
||||||
|
GIT_REF_FORMAT_REFSPEC_PATTERN, "heads/*foo/bar");
|
||||||
|
ensure_refname_invalid(
|
||||||
|
GIT_REF_FORMAT_REFSPEC_PATTERN, "heads/foo*/bar");
|
||||||
|
ensure_refname_invalid(
|
||||||
|
GIT_REF_FORMAT_REFSPEC_PATTERN, "heads/f*o/bar");
|
||||||
|
|
||||||
|
ensure_refname_invalid(
|
||||||
|
GIT_REF_FORMAT_REFSPEC_PATTERN, "foo");
|
||||||
|
ensure_refname_normalized(
|
||||||
|
ONE_LEVEL_AND_REFSPEC, "FOO", "FOO");
|
||||||
|
|
||||||
|
ensure_refname_normalized(
|
||||||
|
GIT_REF_FORMAT_REFSPEC_PATTERN, "foo/bar", "foo/bar");
|
||||||
|
ensure_refname_normalized(
|
||||||
|
ONE_LEVEL_AND_REFSPEC, "foo/bar", "foo/bar");
|
||||||
|
|
||||||
|
ensure_refname_normalized(
|
||||||
|
GIT_REF_FORMAT_REFSPEC_PATTERN, "*/foo", "*/foo");
|
||||||
|
ensure_refname_normalized(
|
||||||
|
ONE_LEVEL_AND_REFSPEC, "*/foo", "*/foo");
|
||||||
|
|
||||||
|
ensure_refname_normalized(
|
||||||
|
GIT_REF_FORMAT_REFSPEC_PATTERN, "foo/*/bar", "foo/*/bar");
|
||||||
|
ensure_refname_normalized(
|
||||||
|
ONE_LEVEL_AND_REFSPEC, "foo/*/bar", "foo/*/bar");
|
||||||
|
|
||||||
|
ensure_refname_invalid(
|
||||||
|
GIT_REF_FORMAT_REFSPEC_PATTERN, "*");
|
||||||
|
ensure_refname_normalized(
|
||||||
|
ONE_LEVEL_AND_REFSPEC, "*", "*");
|
||||||
|
|
||||||
|
ensure_refname_invalid(
|
||||||
|
GIT_REF_FORMAT_REFSPEC_PATTERN, "foo/*/*");
|
||||||
|
ensure_refname_invalid(
|
||||||
|
ONE_LEVEL_AND_REFSPEC, "foo/*/*");
|
||||||
|
|
||||||
|
ensure_refname_invalid(
|
||||||
|
GIT_REF_FORMAT_REFSPEC_PATTERN, "*/foo/*");
|
||||||
|
ensure_refname_invalid(
|
||||||
|
ONE_LEVEL_AND_REFSPEC, "*/foo/*");
|
||||||
|
|
||||||
|
ensure_refname_invalid(
|
||||||
|
GIT_REF_FORMAT_REFSPEC_PATTERN, "*/*/foo");
|
||||||
|
ensure_refname_invalid(
|
||||||
|
ONE_LEVEL_AND_REFSPEC, "*/*/foo");
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
static const char *loose_tag_ref_name = "refs/tags/e90810b";
|
static const char *loose_tag_ref_name = "refs/tags/e90810b";
|
||||||
static const char *non_existing_tag_ref_name = "refs/tags/i-do-not-exist";
|
static const char *non_existing_tag_ref_name = "refs/tags/i-do-not-exist";
|
||||||
static const char *head_tracker_sym_ref_name = "head-tracker";
|
static const char *head_tracker_sym_ref_name = "HEAD_TRACKER";
|
||||||
static const char *current_head_target = "refs/heads/master";
|
static const char *current_head_target = "refs/heads/master";
|
||||||
static const char *current_master_tip = "a65fedf39aefe402d3bb6e24df4d4f5fe4547750";
|
static const char *current_master_tip = "a65fedf39aefe402d3bb6e24df4d4f5fe4547750";
|
||||||
static const char *packed_head_name = "refs/heads/packed";
|
static const char *packed_head_name = "refs/heads/packed";
|
||||||
@ -221,7 +221,7 @@ void test_refs_read__unfound_return_ENOTFOUND(void)
|
|||||||
{
|
{
|
||||||
git_reference *reference;
|
git_reference *reference;
|
||||||
|
|
||||||
cl_assert_equal_i(GIT_ENOTFOUND, git_reference_lookup(&reference, g_repo, "test/master"));
|
cl_assert_equal_i(GIT_ENOTFOUND, git_reference_lookup(&reference, g_repo, "TEST_MASTER"));
|
||||||
cl_assert_equal_i(GIT_ENOTFOUND, git_reference_lookup(&reference, g_repo, "refs/test/master"));
|
cl_assert_equal_i(GIT_ENOTFOUND, git_reference_lookup(&reference, g_repo, "refs/test/master"));
|
||||||
cl_assert_equal_i(GIT_ENOTFOUND, git_reference_lookup(&reference, g_repo, "refs/tags/test/master"));
|
cl_assert_equal_i(GIT_ENOTFOUND, git_reference_lookup(&reference, g_repo, "refs/tags/test/master"));
|
||||||
cl_assert_equal_i(GIT_ENOTFOUND, git_reference_lookup(&reference, g_repo, "refs/tags/test/farther/master"));
|
cl_assert_equal_i(GIT_ENOTFOUND, git_reference_lookup(&reference, g_repo, "refs/tags/test/farther/master"));
|
||||||
|
Loading…
Reference in New Issue
Block a user