mirror of
https://git.proxmox.com/git/libgit2
synced 2026-02-01 17:27:18 +00:00
Split packed from unpacked references
These two reference types are now stored separately to eventually allow the removal/renaming of loose references and rewriting of the refs packfile. Signed-off-by: Vicent Marti <tanoku@gmail.com>
This commit is contained in:
parent
32054c24a2
commit
86194b2433
@ -53,6 +53,5 @@ typedef SSIZE_T ssize_t;
|
||||
#include "bswap.h"
|
||||
|
||||
#define GIT_PATH_MAX 4096
|
||||
#define GIT_FILELOCK_EXTENSION ".lock\0"
|
||||
|
||||
#endif /* INCLUDE_common_h__ */
|
||||
|
||||
@ -28,9 +28,6 @@
|
||||
#include "filebuf.h"
|
||||
#include "fileops.h"
|
||||
|
||||
static const char *GIT_FILELOCK_EXTENSION = ".lock\0";
|
||||
static const size_t GIT_FILELOCK_EXTLENGTH = 6;
|
||||
|
||||
static const size_t WRITE_BUFFER_SIZE = (4096 * 2);
|
||||
|
||||
static int lock_file(git_filebuf *file, int flags)
|
||||
|
||||
@ -12,6 +12,9 @@
|
||||
#define GIT_FILEBUF_APPEND 0x2
|
||||
#define GIT_FILEBUF_FORCE 0x4
|
||||
|
||||
#define GIT_FILELOCK_EXTENSION ".lock\0"
|
||||
#define GIT_FILELOCK_EXTLENGTH 6
|
||||
|
||||
struct git_filebuf {
|
||||
char *path_original;
|
||||
char *path_lock;
|
||||
|
||||
@ -140,10 +140,11 @@ typedef struct git_reference git_reference;
|
||||
|
||||
/** Basic type of any Git reference. */
|
||||
typedef enum {
|
||||
GIT_REF_ANY = -2, /** Reference can be an object id reference or a symbolic reference */
|
||||
GIT_REF_INVALID = -1, /** Invalid reference */
|
||||
GIT_REF_INVALID = 0, /** Invalid reference */
|
||||
GIT_REF_OID = 1, /** A reference which points at an object id */
|
||||
GIT_REF_SYMBOLIC = 2, /** A reference which points at another reference */
|
||||
GIT_REF_PACKED = 4,
|
||||
GIT_REF_HAS_PEEL = 8,
|
||||
} git_rtype;
|
||||
|
||||
/** @} */
|
||||
|
||||
255
src/refs.c
255
src/refs.c
@ -30,7 +30,20 @@
|
||||
|
||||
#define MAX_NESTING_LEVEL 5
|
||||
|
||||
typedef struct {
|
||||
git_reference ref;
|
||||
git_oid oid;
|
||||
git_oid peel_target;
|
||||
} reference_oid;
|
||||
|
||||
typedef struct {
|
||||
git_reference ref;
|
||||
char *target;
|
||||
} reference_symbolic;
|
||||
|
||||
|
||||
static int reference_write(git_reference *ref);
|
||||
static int normalize_name(char *buffer_out, const char *name, int is_oid_ref);
|
||||
|
||||
static const int default_table_size = 32;
|
||||
|
||||
@ -54,30 +67,34 @@ static void reference_free(git_reference *reference)
|
||||
free(reference->name);
|
||||
|
||||
if (reference->type == GIT_REF_SYMBOLIC)
|
||||
free(reference->target.ref);
|
||||
free(((reference_symbolic *)reference)->target);
|
||||
|
||||
free(reference);
|
||||
}
|
||||
|
||||
static int reference_create(git_reference **ref_out, git_repository *repo, const char *name, git_rtype type) {
|
||||
char normalized[MAX_GITDIR_TREE_STRUCTURE_PATH_LENGTH];
|
||||
int error = GIT_SUCCESS;
|
||||
int error = GIT_SUCCESS, size;
|
||||
git_reference *reference = NULL;
|
||||
|
||||
assert(ref_out && repo && name);
|
||||
|
||||
if (type != GIT_REF_SYMBOLIC && type != GIT_REF_OID)
|
||||
return GIT_EMISSINGOBJDATA;
|
||||
if (type == GIT_REF_SYMBOLIC)
|
||||
size = sizeof(reference_symbolic);
|
||||
else if (type == GIT_REF_OID)
|
||||
size = sizeof(reference_oid);
|
||||
else
|
||||
return GIT_EINVALIDREFSTATE;
|
||||
|
||||
reference = git__malloc(sizeof(git_reference));
|
||||
reference = git__malloc(size);
|
||||
if (reference == NULL)
|
||||
return GIT_ENOMEM;
|
||||
|
||||
memset(reference, 0x0, sizeof(git_reference));
|
||||
memset(reference, 0x0, size);
|
||||
reference->owner = repo;
|
||||
reference->type = type;
|
||||
|
||||
error = git_reference__normalize_name(normalized, name, type);
|
||||
error = normalize_name(normalized, name, (type & GIT_REF_OID));
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
@ -107,7 +124,7 @@ int git_reference_create_symbolic(git_reference **ref_out, git_repository *repo,
|
||||
goto cleanup;
|
||||
|
||||
/* The target can aither be the name of an object id reference or the name of another symbolic reference */
|
||||
error = git_reference__normalize_name(normalized, target, GIT_REF_ANY);
|
||||
error = normalize_name(normalized, target, 0);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
@ -116,6 +133,10 @@ int git_reference_create_symbolic(git_reference **ref_out, git_repository *repo,
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
error = git_hashtable_insert(repo->references.loose_refs, ref->name, ref);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
*ref_out = ref;
|
||||
|
||||
return error;
|
||||
@ -139,6 +160,10 @@ int git_reference_create_oid(git_reference **ref_out, git_repository *repo, cons
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
error = git_hashtable_insert(repo->references.loose_refs, ref->name, ref);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
*ref_out = ref;
|
||||
|
||||
return error;
|
||||
@ -153,8 +178,10 @@ static int parse_sym_ref(git_reference *ref, gitfo_buf *file_content)
|
||||
const unsigned int header_len = strlen(GIT_SYMREF);
|
||||
const char *refname_start;
|
||||
char *eol;
|
||||
reference_symbolic *ref_sym;
|
||||
|
||||
refname_start = (const char *)file_content->data;
|
||||
ref_sym = (reference_symbolic *)ref;
|
||||
|
||||
if (file_content->len < (header_len + 1))
|
||||
return GIT_EREFCORRUPTED;
|
||||
@ -166,12 +193,12 @@ static int parse_sym_ref(git_reference *ref, gitfo_buf *file_content)
|
||||
|
||||
refname_start += header_len;
|
||||
|
||||
ref->target.ref = git__strdup(refname_start);
|
||||
if (ref->target.ref == NULL)
|
||||
ref_sym->target = git__strdup(refname_start);
|
||||
if (ref_sym->target == NULL)
|
||||
return GIT_ENOMEM;
|
||||
|
||||
/* remove newline at the end of file */
|
||||
eol = strchr(ref->target.ref, '\n');
|
||||
eol = strchr(ref_sym->target, '\n');
|
||||
if (eol == NULL)
|
||||
return GIT_EREFCORRUPTED;
|
||||
|
||||
@ -184,19 +211,19 @@ static int parse_sym_ref(git_reference *ref, gitfo_buf *file_content)
|
||||
|
||||
static int parse_oid_ref(git_reference *ref, gitfo_buf *file_content)
|
||||
{
|
||||
reference_oid *ref_oid;
|
||||
char *buffer;
|
||||
git_oid id;
|
||||
|
||||
buffer = (char *)file_content->data;
|
||||
ref_oid = (reference_oid *)ref;
|
||||
|
||||
/* File format: 40 chars (OID) + newline */
|
||||
if (file_content->len < GIT_OID_HEXSZ + 1)
|
||||
return GIT_EREFCORRUPTED;
|
||||
|
||||
if (git_oid_mkstr(&id, buffer) < GIT_SUCCESS)
|
||||
if (git_oid_mkstr(&ref_oid->oid, buffer) < GIT_SUCCESS)
|
||||
return GIT_EREFCORRUPTED;
|
||||
|
||||
git_oid_cpy(&ref->target.oid, &id);
|
||||
|
||||
buffer = buffer + GIT_OID_HEXSZ;
|
||||
if (*buffer == '\r')
|
||||
buffer++;
|
||||
@ -261,7 +288,7 @@ static int lookup_loose_ref(
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
error = git_hashtable_insert(repo->references.cache, ref->name, ref);
|
||||
error = git_hashtable_insert(repo->references.loose_refs, ref->name, ref);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
@ -290,12 +317,10 @@ static int read_packed_refs(gitfo_buf *packfile, const char *repo_path)
|
||||
}
|
||||
|
||||
static int parse_packed_line_peel(
|
||||
git_reference **ref_out,
|
||||
const git_reference *tag_ref,
|
||||
reference_oid *tag_ref,
|
||||
const char **buffer_out,
|
||||
const char *buffer_end)
|
||||
{
|
||||
git_oid oid;
|
||||
const char *buffer = *buffer_out + 1;
|
||||
|
||||
assert(buffer[-1] == '^');
|
||||
@ -305,14 +330,14 @@ static int parse_packed_line_peel(
|
||||
return GIT_EPACKEDREFSCORRUPTED;
|
||||
|
||||
/* Ensure reference is a tag */
|
||||
if (git__prefixcmp(tag_ref->name, GIT_REFS_TAGS_DIR) != 0)
|
||||
if (git__prefixcmp(tag_ref->ref.name, GIT_REFS_TAGS_DIR) != 0)
|
||||
return GIT_EPACKEDREFSCORRUPTED;
|
||||
|
||||
if (buffer + GIT_OID_HEXSZ >= buffer_end)
|
||||
return GIT_EPACKEDREFSCORRUPTED;
|
||||
|
||||
/* Is this a valid object id? */
|
||||
if (git_oid_mkstr(&oid, buffer) < GIT_SUCCESS)
|
||||
if (git_oid_mkstr(&tag_ref->peel_target, buffer) < GIT_SUCCESS)
|
||||
return GIT_EPACKEDREFSCORRUPTED;
|
||||
|
||||
buffer = buffer + GIT_OID_HEXSZ;
|
||||
@ -323,24 +348,18 @@ static int parse_packed_line_peel(
|
||||
return GIT_EPACKEDREFSCORRUPTED;
|
||||
|
||||
*buffer_out = buffer + 1;
|
||||
tag_ref->ref.type |= GIT_REF_HAS_PEEL;
|
||||
|
||||
/*
|
||||
* TODO: do we need the packed line?
|
||||
* Right now we don't, so we don't create a new
|
||||
* reference.
|
||||
*/
|
||||
|
||||
*ref_out = NULL;
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
static int parse_packed_line(
|
||||
git_reference **ref_out,
|
||||
reference_oid **ref_out,
|
||||
git_repository *repo,
|
||||
const char **buffer_out,
|
||||
const char *buffer_end)
|
||||
{
|
||||
git_reference *ref;
|
||||
reference_oid *ref;
|
||||
|
||||
const char *buffer = *buffer_out;
|
||||
const char *refname_begin, *refname_end;
|
||||
@ -375,13 +394,12 @@ static int parse_packed_line(
|
||||
if (refname[refname_len - 1] == '\r')
|
||||
refname[refname_len - 1] = 0;
|
||||
|
||||
error = reference_create(&ref, repo, refname, GIT_REF_OID);
|
||||
error = reference_create((git_reference **)&ref, repo, refname, GIT_REF_OID);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
git_oid_cpy(&ref->target.oid, &id);
|
||||
|
||||
ref->packed = 1;
|
||||
git_oid_cpy(&ref->oid, &id);
|
||||
ref->ref.type |= GIT_REF_PACKED;
|
||||
|
||||
*ref_out = ref;
|
||||
*buffer_out = refname_end + 1;
|
||||
@ -389,11 +407,11 @@ static int parse_packed_line(
|
||||
return GIT_SUCCESS;
|
||||
|
||||
cleanup:
|
||||
reference_free(ref);
|
||||
reference_free((git_reference *)ref);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int parse_packed_refs(git_refcache *ref_cache, git_repository *repo)
|
||||
static int load_packed_refs(git_refcache *ref_cache, git_repository *repo)
|
||||
{
|
||||
int error = GIT_SUCCESS;
|
||||
gitfo_buf packfile = GITFO_BUF_INIT;
|
||||
@ -425,34 +443,21 @@ static int parse_packed_refs(git_refcache *ref_cache, git_repository *repo)
|
||||
|
||||
while (buffer_start < buffer_end) {
|
||||
|
||||
git_reference *ref = NULL;
|
||||
git_reference *ref_tag = NULL;
|
||||
reference_oid *ref = NULL;
|
||||
|
||||
error = parse_packed_line(&ref, repo, &buffer_start, buffer_end);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
if (buffer_start[0] == '^') {
|
||||
error = parse_packed_line_peel(&ref_tag, ref, &buffer_start, buffer_end);
|
||||
error = parse_packed_line_peel(ref, &buffer_start, buffer_end);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* If a loose reference exists with the same name,
|
||||
* we assume that the loose reference is more up-to-date.
|
||||
* We don't need to cache this ref from the packfile.
|
||||
*/
|
||||
if (read_loose_ref(NULL, ref->name, repo->path_repository) == GIT_SUCCESS) {
|
||||
reference_free(ref);
|
||||
reference_free(ref_tag);
|
||||
continue;
|
||||
}
|
||||
|
||||
error = git_hashtable_insert(ref_cache->cache, ref->name, ref);
|
||||
error = git_hashtable_insert(ref_cache->packed_refs, ref->ref.name, ref);
|
||||
if (error < GIT_SUCCESS) {
|
||||
reference_free(ref);
|
||||
reference_free(ref_tag);
|
||||
reference_free((git_reference *)ref);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
@ -466,22 +471,32 @@ cleanup:
|
||||
|
||||
int git_reference_set_oid(git_reference *ref, const git_oid *id)
|
||||
{
|
||||
if (ref->type != GIT_REF_OID)
|
||||
reference_oid *ref_oid;
|
||||
|
||||
if ((ref->type & GIT_REF_OID) == 0)
|
||||
return GIT_EINVALIDREFSTATE;
|
||||
|
||||
git_oid_cpy(&ref->target.oid, id);
|
||||
ref_oid = (reference_oid *)ref;
|
||||
git_oid_cpy(&ref_oid->oid, id);
|
||||
|
||||
ref->type &= ~GIT_REF_HAS_PEEL;
|
||||
/* TODO: set new peel target */
|
||||
|
||||
return reference_write(ref);
|
||||
}
|
||||
|
||||
int git_reference_set_target(git_reference *ref, const char *target)
|
||||
{
|
||||
if (ref->type != GIT_REF_SYMBOLIC)
|
||||
reference_symbolic *ref_sym;
|
||||
|
||||
if ((ref->type & GIT_REF_SYMBOLIC) == 0)
|
||||
return GIT_EINVALIDREFSTATE;
|
||||
|
||||
free(ref->target.ref);
|
||||
ref->target.ref = git__strdup(target);
|
||||
if (ref->target.ref == NULL)
|
||||
ref_sym = (reference_symbolic *)ref;
|
||||
|
||||
free(ref_sym->target);
|
||||
ref_sym->target = git__strdup(target);
|
||||
if (ref_sym->target == NULL)
|
||||
return GIT_ENOMEM;
|
||||
|
||||
return reference_write(ref);
|
||||
@ -491,26 +506,33 @@ const git_oid *git_reference_oid(git_reference *ref)
|
||||
{
|
||||
assert(ref);
|
||||
|
||||
if (ref->type != GIT_REF_OID)
|
||||
if ((ref->type & GIT_REF_OID) == 0)
|
||||
return NULL;
|
||||
|
||||
return &ref->target.oid;
|
||||
return &((reference_oid *)ref)->oid;
|
||||
}
|
||||
|
||||
const char *git_reference_target(git_reference *ref)
|
||||
{
|
||||
assert(ref);
|
||||
|
||||
if (ref->type != GIT_REF_SYMBOLIC)
|
||||
if ((ref->type & GIT_REF_SYMBOLIC) == 0)
|
||||
return NULL;
|
||||
|
||||
return ref->target.ref;
|
||||
return ((reference_symbolic *)ref)->target;
|
||||
}
|
||||
|
||||
git_rtype git_reference_type(git_reference *ref)
|
||||
{
|
||||
assert(ref);
|
||||
return ref->type;
|
||||
|
||||
if (ref->type & GIT_REF_OID)
|
||||
return GIT_REF_OID;
|
||||
|
||||
if (ref->type & GIT_REF_SYMBOLIC)
|
||||
return GIT_REF_SYMBOLIC;
|
||||
|
||||
return GIT_REF_INVALID;
|
||||
}
|
||||
|
||||
const char *git_reference_name(git_reference *ref)
|
||||
@ -536,13 +558,15 @@ int git_reference_resolve(git_reference **resolved_ref, git_reference *ref)
|
||||
repo = ref->owner;
|
||||
|
||||
for (i = 0; i < MAX_NESTING_LEVEL; ++i) {
|
||||
reference_symbolic *ref_sym;
|
||||
|
||||
if (ref->type == GIT_REF_OID) {
|
||||
if (ref->type & GIT_REF_OID) {
|
||||
*resolved_ref = ref;
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
if ((error = git_repository_lookup_ref(&ref, repo, ref->target.ref)) < GIT_SUCCESS)
|
||||
ref_sym = (reference_symbolic *)ref;
|
||||
if ((error = git_repository_lookup_ref(&ref, repo, ref_sym->target)) < GIT_SUCCESS)
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -556,14 +580,13 @@ static int reference_write(git_reference *ref)
|
||||
int error, contents_size;
|
||||
char *ref_contents = NULL;
|
||||
|
||||
assert(ref->type == GIT_REF_OID || ref->type == GIT_REF_SYMBOLIC);
|
||||
|
||||
git__joinpath(ref_path, ref->owner->path_repository, ref->name);
|
||||
|
||||
if ((error = git_filebuf_open(&file, ref_path, 0)) < GIT_SUCCESS)
|
||||
goto error_cleanup;
|
||||
return error;
|
||||
|
||||
if (ref->type == GIT_REF_OID) {
|
||||
if (ref->type & GIT_REF_OID) {
|
||||
reference_oid *ref_oid = (reference_oid *)ref;
|
||||
|
||||
contents_size = GIT_OID_HEXSZ + 1;
|
||||
ref_contents = git__malloc(contents_size);
|
||||
@ -572,11 +595,12 @@ static int reference_write(git_reference *ref)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
git_oid_fmt(ref_contents, &ref->target.oid);
|
||||
git_oid_fmt(ref_contents, &ref_oid->oid);
|
||||
|
||||
} else { /* GIT_REF_SYMBOLIC */
|
||||
} else if (ref->type & GIT_REF_SYMBOLIC) { /* GIT_REF_SYMBOLIC */
|
||||
reference_symbolic *ref_sym = (reference_symbolic *)ref;
|
||||
|
||||
contents_size = strlen(GIT_SYMREF) + strlen(ref->target.ref) + 1;
|
||||
contents_size = strlen(GIT_SYMREF) + strlen(ref_sym->target) + 1;
|
||||
ref_contents = git__malloc(contents_size);
|
||||
if (ref_contents == NULL) {
|
||||
error = GIT_ENOMEM;
|
||||
@ -584,28 +608,25 @@ static int reference_write(git_reference *ref)
|
||||
}
|
||||
|
||||
strcpy(ref_contents, GIT_SYMREF);
|
||||
strcat(ref_contents, ref->target.ref);
|
||||
strcat(ref_contents, ref_sym->target);
|
||||
} else {
|
||||
error = GIT_EINVALIDREFSTATE;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
/* TODO: win32 carriage return when writing references in Windows? */
|
||||
ref_contents[contents_size - 1] = '\n';
|
||||
|
||||
if ((error = git_filebuf_write(&file, ref_contents, contents_size)) < GIT_SUCCESS)
|
||||
goto error_cleanup;
|
||||
goto unlock;
|
||||
|
||||
error = git_filebuf_commit(&file);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto unlock;
|
||||
|
||||
error = git_hashtable_insert(ref->owner->references.cache, ref->name, ref);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto unlock;
|
||||
|
||||
free(ref_contents);
|
||||
return GIT_SUCCESS;
|
||||
return error;
|
||||
|
||||
unlock:
|
||||
git_filebuf_cleanup(&lock);
|
||||
git_filebuf_cleanup(&file);
|
||||
free(ref_contents);
|
||||
return error;
|
||||
}
|
||||
@ -619,7 +640,7 @@ int git_repository_lookup_ref(git_reference **ref_out, git_repository *repo, con
|
||||
|
||||
*ref_out = NULL;
|
||||
|
||||
error = git_reference__normalize_name(normalized_name, name, GIT_REF_ANY);
|
||||
error = normalize_name(normalized_name, name, 0);
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
|
||||
@ -627,7 +648,7 @@ int git_repository_lookup_ref(git_reference **ref_out, git_repository *repo, con
|
||||
* First, check if the reference is on the local cache;
|
||||
* references on the cache are assured to be up-to-date
|
||||
*/
|
||||
*ref_out = git_hashtable_lookup(repo->references.cache, normalized_name);
|
||||
*ref_out = git_hashtable_lookup(repo->references.loose_refs, normalized_name);
|
||||
if (*ref_out != NULL)
|
||||
return GIT_SUCCESS;
|
||||
|
||||
@ -644,28 +665,17 @@ int git_repository_lookup_ref(git_reference **ref_out, git_repository *repo, con
|
||||
if (error != GIT_ENOTFOUND)
|
||||
return error;
|
||||
|
||||
/*
|
||||
* Check if we have loaded the packed references.
|
||||
* If the packed references have been loaded, they would be
|
||||
* stored already on the cache: that means that the ref
|
||||
* we are looking for doesn't exist.
|
||||
*
|
||||
* If they haven't been loaded yet, we load the packfile
|
||||
* and check if our reference is inside of it.
|
||||
*/
|
||||
if (!repo->references.pack_loaded) {
|
||||
|
||||
/* load all the packed references */
|
||||
error = parse_packed_refs(&repo->references, repo);
|
||||
error = load_packed_refs(&repo->references, repo);
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
|
||||
/* check the cache again -- hopefully the reference will be there */
|
||||
*ref_out = git_hashtable_lookup(repo->references.cache, normalized_name);
|
||||
if (*ref_out != NULL)
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
*ref_out = git_hashtable_lookup(repo->references.packed_refs, normalized_name);
|
||||
if (*ref_out != NULL)
|
||||
return GIT_SUCCESS;
|
||||
|
||||
/* The reference doesn't exist anywhere */
|
||||
return GIT_ENOTFOUND;
|
||||
}
|
||||
@ -674,26 +684,36 @@ int git_repository__refcache_init(git_refcache *refs)
|
||||
{
|
||||
assert(refs);
|
||||
|
||||
refs->cache = git_hashtable_alloc(
|
||||
refs->loose_refs = git_hashtable_alloc(
|
||||
default_table_size,
|
||||
reftable_hash,
|
||||
(git_hash_keyeq_ptr)strcmp);
|
||||
|
||||
refs->packed_refs = git_hashtable_alloc(
|
||||
default_table_size,
|
||||
reftable_hash,
|
||||
(git_hash_keyeq_ptr)strcmp);
|
||||
|
||||
return refs->cache ? GIT_SUCCESS : GIT_ENOMEM;
|
||||
return (refs->loose_refs && refs->packed_refs) ? GIT_SUCCESS : GIT_ENOMEM;
|
||||
}
|
||||
|
||||
void git_repository__refcache_free(git_refcache *refs)
|
||||
{
|
||||
const char *ref_name;
|
||||
git_reference *reference;
|
||||
const void *_unused;
|
||||
|
||||
assert(refs);
|
||||
|
||||
GIT_HASHTABLE_FOREACH(refs->cache, ref_name, reference,
|
||||
reference_free(reference)
|
||||
GIT_HASHTABLE_FOREACH(refs->loose_refs, _unused, reference,
|
||||
reference_free(reference);
|
||||
);
|
||||
|
||||
git_hashtable_free(refs->cache);
|
||||
GIT_HASHTABLE_FOREACH(refs->packed_refs, _unused, reference,
|
||||
reference_free(reference);
|
||||
);
|
||||
|
||||
git_hashtable_free(refs->loose_refs);
|
||||
git_hashtable_free(refs->packed_refs);
|
||||
}
|
||||
|
||||
static int check_valid_ref_char(char ch)
|
||||
@ -717,7 +737,8 @@ static int check_valid_ref_char(char ch)
|
||||
}
|
||||
}
|
||||
|
||||
int git_reference__normalize_name(char *buffer_out, const char *name, git_rtype type)
|
||||
|
||||
static int normalize_name(char *buffer_out, const char *name, int is_oid_ref)
|
||||
{
|
||||
int error = GIT_SUCCESS;
|
||||
const char *name_end, *buffer_out_start;
|
||||
@ -730,9 +751,6 @@ int git_reference__normalize_name(char *buffer_out, const char *name, git_rtype
|
||||
current = (char *)name;
|
||||
name_end = name + strlen(name);
|
||||
|
||||
if (type == GIT_REF_INVALID)
|
||||
return GIT_EINVALIDTYPE;
|
||||
|
||||
/* A refname can not be empty */
|
||||
if (name_end == name)
|
||||
return GIT_EINVALIDREFNAME;
|
||||
@ -770,7 +788,7 @@ int git_reference__normalize_name(char *buffer_out, const char *name, git_rtype
|
||||
}
|
||||
|
||||
/* Object id refname have to contain at least one slash */
|
||||
if (type == GIT_REF_OID && !contains_a_slash)
|
||||
if (is_oid_ref && !contains_a_slash)
|
||||
return GIT_EINVALIDREFNAME;
|
||||
|
||||
/* A refname can not end with ".lock" */
|
||||
@ -780,10 +798,21 @@ int git_reference__normalize_name(char *buffer_out, const char *name, git_rtype
|
||||
*buffer_out = '\0';
|
||||
|
||||
/* For object id references, name has to start with refs/(heads|tags|remotes) */
|
||||
if (type == GIT_REF_OID && !(!git__prefixcmp(buffer_out_start, GIT_REFS_HEADS_DIR) ||
|
||||
if (is_oid_ref && !(!git__prefixcmp(buffer_out_start, GIT_REFS_HEADS_DIR) ||
|
||||
!git__prefixcmp(buffer_out_start, GIT_REFS_TAGS_DIR) || !git__prefixcmp(buffer_out_start, GIT_REFS_REMOTES_DIR)))
|
||||
return GIT_EINVALIDREFNAME;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_reference__normalize_name(char *buffer_out, const char *name)
|
||||
{
|
||||
return normalize_name(buffer_out, name, 0);
|
||||
}
|
||||
|
||||
int git_reference__normalize_name_oid(char *buffer_out, const char *name)
|
||||
{
|
||||
return normalize_name(buffer_out, name, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
17
src/refs.h
17
src/refs.h
@ -18,25 +18,22 @@
|
||||
|
||||
struct git_reference {
|
||||
git_repository *owner;
|
||||
git_rtype type;
|
||||
char *name;
|
||||
|
||||
unsigned packed:1;
|
||||
|
||||
union {
|
||||
char *ref;
|
||||
git_oid oid;
|
||||
} target;
|
||||
unsigned int type;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
git_hashtable *cache;
|
||||
git_hashtable *packed_refs;
|
||||
git_hashtable *loose_refs;
|
||||
|
||||
unsigned pack_loaded:1;
|
||||
} git_refcache;
|
||||
|
||||
|
||||
void git_repository__refcache_free(git_refcache *refs);
|
||||
int git_repository__refcache_init(git_refcache *refs);
|
||||
int git_reference__normalize_name(char *buffer_out, const char *name, git_rtype type);
|
||||
|
||||
int git_reference__normalize_name(char *buffer_out, const char *name);
|
||||
int git_reference__normalize_name_oid(char *buffer_out, const char *name);
|
||||
|
||||
#endif
|
||||
|
||||
17
src/vector.c
17
src/vector.c
@ -35,18 +35,13 @@ static int resize_vector(git_vector *v)
|
||||
void **new_contents;
|
||||
|
||||
v->_alloc_size = ((unsigned int)(v->_alloc_size * resize_factor)) + 1;
|
||||
if (v->_alloc_size == 0)
|
||||
if (v->_alloc_size < minimum_size)
|
||||
v->_alloc_size = minimum_size;
|
||||
|
||||
new_contents = git__malloc(v->_alloc_size * sizeof(void *));
|
||||
if (new_contents == NULL)
|
||||
v->contents = realloc(v->contents, v->_alloc_size * sizeof(void *));
|
||||
if (v->contents == NULL)
|
||||
return GIT_ENOMEM;
|
||||
|
||||
memcpy(new_contents, v->contents, v->length * sizeof(void *));
|
||||
|
||||
free(v->contents);
|
||||
v->contents = new_contents;
|
||||
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
@ -93,12 +88,6 @@ int git_vector_insert(git_vector *v, void *element)
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
void *git_vector_get(git_vector *v, unsigned int position)
|
||||
{
|
||||
assert(v);
|
||||
return (position < v->length) ? v->contents[position] : NULL;
|
||||
}
|
||||
|
||||
void git_vector_sort(git_vector *v)
|
||||
{
|
||||
assert(v);
|
||||
|
||||
@ -24,7 +24,10 @@ void git_vector_clear(git_vector *v);
|
||||
int git_vector_search(git_vector *v, const void *key);
|
||||
void git_vector_sort(git_vector *v);
|
||||
|
||||
void *git_vector_get(git_vector *v, unsigned int position);
|
||||
GIT_INLINE(void *) git_vector_get(git_vector *v, unsigned int position)
|
||||
{
|
||||
return (position < v->length) ? v->contents[position] : NULL;
|
||||
}
|
||||
|
||||
int git_vector_insert(git_vector *v, void *element);
|
||||
int git_vector_remove(git_vector *v, unsigned int idx);
|
||||
|
||||
225
tests/t10-refs.c
225
tests/t10-refs.c
@ -38,8 +38,8 @@ BEGIN_TEST("readtag", loose_tag_reference_looking_up)
|
||||
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
|
||||
|
||||
must_pass(git_repository_lookup_ref(&reference, repo, loose_tag_ref_name));
|
||||
must_be_true(reference->type == GIT_REF_OID);
|
||||
must_be_true(reference->packed == 0);
|
||||
must_be_true(reference->type & GIT_REF_OID);
|
||||
must_be_true((reference->type & GIT_REF_PACKED) == 0);
|
||||
must_be_true(strcmp(reference->name, loose_tag_ref_name) == 0);
|
||||
|
||||
must_pass(git_repository_lookup(&object, repo, git_reference_oid(reference), GIT_OBJ_ANY));
|
||||
@ -73,8 +73,8 @@ BEGIN_TEST("readsymref", symbolic_reference_looking_up)
|
||||
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
|
||||
|
||||
must_pass(git_repository_lookup_ref(&reference, repo, head_ref_name));
|
||||
must_be_true(reference->type == GIT_REF_SYMBOLIC);
|
||||
must_be_true(reference->packed == 0);
|
||||
must_be_true(reference->type & GIT_REF_SYMBOLIC);
|
||||
must_be_true((reference->type & GIT_REF_PACKED) == 0);
|
||||
must_be_true(strcmp(reference->name, head_ref_name) == 0);
|
||||
|
||||
must_pass(git_reference_resolve(&resolved_ref, reference));
|
||||
@ -99,8 +99,8 @@ BEGIN_TEST("readsymref", nested_symbolic_reference_looking_up)
|
||||
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
|
||||
|
||||
must_pass(git_repository_lookup_ref(&reference, repo, head_tracker_sym_ref_name));
|
||||
must_be_true(reference->type == GIT_REF_SYMBOLIC);
|
||||
must_be_true(reference->packed == 0);
|
||||
must_be_true(reference->type & GIT_REF_SYMBOLIC);
|
||||
must_be_true((reference->type & GIT_REF_PACKED) == 0);
|
||||
must_be_true(strcmp(reference->name, head_tracker_sym_ref_name) == 0);
|
||||
|
||||
must_pass(git_reference_resolve(&resolved_ref, reference));
|
||||
@ -163,8 +163,8 @@ BEGIN_TEST("readpackedref", packed_reference_looking_up)
|
||||
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
|
||||
|
||||
must_pass(git_repository_lookup_ref(&reference, repo, packed_head_name));
|
||||
must_be_true(reference->type == GIT_REF_OID);
|
||||
must_be_true(reference->packed == 1);
|
||||
must_be_true(reference->type & GIT_REF_OID);
|
||||
must_be_true((reference->type & GIT_REF_PACKED) != 0);
|
||||
must_be_true(strcmp(reference->name, packed_head_name) == 0);
|
||||
|
||||
must_pass(git_repository_lookup(&object, repo, git_reference_oid(reference), GIT_OBJ_ANY));
|
||||
@ -181,8 +181,8 @@ BEGIN_TEST("readpackedref", packed_exists_but_more_recent_loose_reference_is_ret
|
||||
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
|
||||
must_pass(git_repository_lookup_ref(&reference, repo, packed_head_name));
|
||||
must_pass(git_repository_lookup_ref(&reference, repo, packed_test_head_name));
|
||||
must_be_true(reference->type == GIT_REF_OID);
|
||||
must_be_true(reference->packed == 0);
|
||||
must_be_true(reference->type & GIT_REF_OID);
|
||||
must_be_true((reference->type & GIT_REF_PACKED) == 0);
|
||||
must_be_true(strcmp(reference->name, packed_test_head_name) == 0);
|
||||
|
||||
git_repository_free(repo);
|
||||
@ -208,8 +208,8 @@ BEGIN_TEST("createref", create_new_symbolic_ref)
|
||||
|
||||
/* Ensure the reference can be looked-up... */
|
||||
must_pass(git_repository_lookup_ref(&looked_up_ref, repo, new_head_tracker));
|
||||
must_be_true(looked_up_ref->type == GIT_REF_SYMBOLIC);
|
||||
must_be_true(looked_up_ref->packed == 0);
|
||||
must_be_true(looked_up_ref->type & GIT_REF_SYMBOLIC);
|
||||
must_be_true((looked_up_ref->type & GIT_REF_PACKED) == 0);
|
||||
must_be_true(strcmp(looked_up_ref->name, new_head_tracker) == 0);
|
||||
|
||||
/* ...peeled.. */
|
||||
@ -276,8 +276,8 @@ BEGIN_TEST("createref", create_new_object_id_ref)
|
||||
|
||||
/* Ensure the reference can be looked-up... */
|
||||
must_pass(git_repository_lookup_ref(&looked_up_ref, repo, new_head));
|
||||
must_be_true(looked_up_ref->type == GIT_REF_OID);
|
||||
must_be_true(looked_up_ref->packed == 0);
|
||||
must_be_true(looked_up_ref->type & GIT_REF_OID);
|
||||
must_be_true((looked_up_ref->type & GIT_REF_PACKED) == 0);
|
||||
must_be_true(strcmp(looked_up_ref->name, new_head) == 0);
|
||||
|
||||
/* ...and that it points to the current master tip */
|
||||
@ -296,12 +296,16 @@ BEGIN_TEST("createref", create_new_object_id_ref)
|
||||
must_pass(gitfo_unlink(ref_path)); /* TODO: replace with git_reference_delete() when available */
|
||||
END_TEST
|
||||
|
||||
static int ensure_refname_normalized(git_rtype ref_type, const char *input_refname, const char *expected_refname)
|
||||
static int ensure_refname_normalized(int is_oid_ref, const char *input_refname, const char *expected_refname)
|
||||
{
|
||||
int error = GIT_SUCCESS;
|
||||
char buffer_out[GIT_PATH_MAX];
|
||||
|
||||
error = git_reference__normalize_name(buffer_out, input_refname, ref_type);
|
||||
if (is_oid_ref)
|
||||
error = git_reference__normalize_name_oid(buffer_out, input_refname);
|
||||
else
|
||||
error = git_reference__normalize_name(buffer_out, input_refname);
|
||||
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
|
||||
@ -314,73 +318,69 @@ static int ensure_refname_normalized(git_rtype ref_type, const char *input_refna
|
||||
return error;
|
||||
}
|
||||
|
||||
BEGIN_TEST("normalizeref", normalize_unknown_ref_type)
|
||||
must_fail(ensure_refname_normalized(GIT_REF_INVALID, "a", NULL));
|
||||
END_TEST
|
||||
|
||||
BEGIN_TEST("normalizeref", normalize_object_id_ref)
|
||||
must_fail(ensure_refname_normalized(GIT_REF_OID, "a", NULL));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_OID, "", NULL));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_OID, "refs/heads/a/", NULL));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_OID, "refs/heads/a.", NULL));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_OID, "refs/heads/a.lock", NULL));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_OID, "refs/dummy/a", NULL));
|
||||
must_pass(ensure_refname_normalized(GIT_REF_OID, "refs/tags/a", "refs/tags/a"));
|
||||
must_pass(ensure_refname_normalized(GIT_REF_OID, "refs/heads/a/b", "refs/heads/a/b"));
|
||||
must_pass(ensure_refname_normalized(GIT_REF_OID, "refs/heads/a./b", "refs/heads/a./b"));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_OID, "refs/heads/foo?bar", NULL));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_OID, "refs/heads\foo", NULL));
|
||||
must_pass(ensure_refname_normalized(GIT_REF_OID, "refs/heads/v@ation", "refs/heads/v@ation"));
|
||||
must_pass(ensure_refname_normalized(GIT_REF_OID, "refs///heads///a", "refs/heads/a"));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_OID, "refs/heads/.a/b", NULL));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_OID, "refs/heads/foo/../bar", NULL));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_OID, "refs/heads/foo..bar", NULL));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_OID, "refs/heads/./foo", NULL));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_OID, "refs/heads/v@{ation", NULL));
|
||||
must_fail(ensure_refname_normalized(1, "a", NULL));
|
||||
must_fail(ensure_refname_normalized(1, "", NULL));
|
||||
must_fail(ensure_refname_normalized(1, "refs/heads/a/", NULL));
|
||||
must_fail(ensure_refname_normalized(1, "refs/heads/a.", NULL));
|
||||
must_fail(ensure_refname_normalized(1, "refs/heads/a.lock", NULL));
|
||||
must_fail(ensure_refname_normalized(1, "refs/dummy/a", NULL));
|
||||
must_pass(ensure_refname_normalized(1, "refs/tags/a", "refs/tags/a"));
|
||||
must_pass(ensure_refname_normalized(1, "refs/heads/a/b", "refs/heads/a/b"));
|
||||
must_pass(ensure_refname_normalized(1, "refs/heads/a./b", "refs/heads/a./b"));
|
||||
must_fail(ensure_refname_normalized(1, "refs/heads/foo?bar", NULL));
|
||||
must_fail(ensure_refname_normalized(1, "refs/heads\foo", NULL));
|
||||
must_pass(ensure_refname_normalized(1, "refs/heads/v@ation", "refs/heads/v@ation"));
|
||||
must_pass(ensure_refname_normalized(1, "refs///heads///a", "refs/heads/a"));
|
||||
must_fail(ensure_refname_normalized(1, "refs/heads/.a/b", NULL));
|
||||
must_fail(ensure_refname_normalized(1, "refs/heads/foo/../bar", NULL));
|
||||
must_fail(ensure_refname_normalized(1, "refs/heads/foo..bar", NULL));
|
||||
must_fail(ensure_refname_normalized(1, "refs/heads/./foo", NULL));
|
||||
must_fail(ensure_refname_normalized(1, "refs/heads/v@{ation", NULL));
|
||||
END_TEST
|
||||
|
||||
BEGIN_TEST("normalizeref", normalize_symbolic_ref)
|
||||
must_pass(ensure_refname_normalized(GIT_REF_SYMBOLIC, "a", "a"));
|
||||
must_pass(ensure_refname_normalized(GIT_REF_SYMBOLIC, "a/b", "a/b"));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_SYMBOLIC, "", NULL));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_SYMBOLIC, "heads\foo", NULL));
|
||||
must_pass(ensure_refname_normalized(0, "a", "a"));
|
||||
must_pass(ensure_refname_normalized(0, "a/b", "a/b"));
|
||||
must_fail(ensure_refname_normalized(0, "", NULL));
|
||||
must_fail(ensure_refname_normalized(0, "heads\foo", NULL));
|
||||
END_TEST
|
||||
|
||||
|
||||
BEGIN_TEST("normalizeref", normalize_any_ref) /* Slash related rules do not apply, neither do 'refs' prefix related rules */
|
||||
must_pass(ensure_refname_normalized(GIT_REF_ANY, "a", "a"));
|
||||
must_pass(ensure_refname_normalized(GIT_REF_ANY, "a/b", "a/b"));
|
||||
must_pass(ensure_refname_normalized(GIT_REF_ANY, "refs///heads///a", "refs/heads/a"));
|
||||
must_pass(ensure_refname_normalized(0, "a", "a"));
|
||||
must_pass(ensure_refname_normalized(0, "a/b", "a/b"));
|
||||
must_pass(ensure_refname_normalized(0, "refs///heads///a", "refs/heads/a"));
|
||||
END_TEST
|
||||
|
||||
/* Ported from JGit, BSD licence. See https://github.com/spearce/JGit/commit/e4bf8f6957bbb29362575d641d1e77a02d906739 */
|
||||
BEGIN_TEST("normalizeref", jgit_tests)
|
||||
|
||||
/* EmptyString */
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, "", NULL));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, "/", NULL));
|
||||
must_fail(ensure_refname_normalized(0, "", NULL));
|
||||
must_fail(ensure_refname_normalized(0, "/", NULL));
|
||||
|
||||
/* MustHaveTwoComponents */
|
||||
must_fail(ensure_refname_normalized(GIT_REF_OID, "master", NULL));
|
||||
must_pass(ensure_refname_normalized(GIT_REF_ANY, "heads/master", "heads/master"));
|
||||
must_fail(ensure_refname_normalized(1, "master", NULL));
|
||||
must_pass(ensure_refname_normalized(0, "heads/master", "heads/master"));
|
||||
|
||||
/* ValidHead */
|
||||
must_pass(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/master", "refs/heads/master"));
|
||||
must_pass(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/pu", "refs/heads/pu"));
|
||||
must_pass(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/z", "refs/heads/z"));
|
||||
must_pass(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/FoO", "refs/heads/FoO"));
|
||||
must_pass(ensure_refname_normalized(0, "refs/heads/master", "refs/heads/master"));
|
||||
must_pass(ensure_refname_normalized(0, "refs/heads/pu", "refs/heads/pu"));
|
||||
must_pass(ensure_refname_normalized(0, "refs/heads/z", "refs/heads/z"));
|
||||
must_pass(ensure_refname_normalized(0, "refs/heads/FoO", "refs/heads/FoO"));
|
||||
|
||||
/* ValidTag */
|
||||
must_pass(ensure_refname_normalized(GIT_REF_ANY, "refs/tags/v1.0", "refs/tags/v1.0"));
|
||||
must_pass(ensure_refname_normalized(0, "refs/tags/v1.0", "refs/tags/v1.0"));
|
||||
|
||||
/* NoLockSuffix */
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/master.lock", NULL));
|
||||
must_fail(ensure_refname_normalized(0, "refs/heads/master.lock", NULL));
|
||||
|
||||
/* NoDirectorySuffix */
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/master/", NULL));
|
||||
must_fail(ensure_refname_normalized(0, "refs/heads/master/", NULL));
|
||||
|
||||
/* NoSpace */
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/i haz space", NULL));
|
||||
must_fail(ensure_refname_normalized(0, "refs/heads/i haz space", NULL));
|
||||
|
||||
/* NoAsciiControlCharacters */
|
||||
{
|
||||
@ -391,81 +391,81 @@ BEGIN_TEST("normalizeref", jgit_tests)
|
||||
strncpy(buffer + 15, (const char *)&c, 1);
|
||||
strncpy(buffer + 16, "er", 2);
|
||||
buffer[18 - 1] = '\0';
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, buffer, NULL));
|
||||
must_fail(ensure_refname_normalized(0, buffer, NULL));
|
||||
}
|
||||
}
|
||||
|
||||
/* NoBareDot */
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/.", NULL));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/..", NULL));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/./master", NULL));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/../master", NULL));
|
||||
must_fail(ensure_refname_normalized(0, "refs/heads/.", NULL));
|
||||
must_fail(ensure_refname_normalized(0, "refs/heads/..", NULL));
|
||||
must_fail(ensure_refname_normalized(0, "refs/heads/./master", NULL));
|
||||
must_fail(ensure_refname_normalized(0, "refs/heads/../master", NULL));
|
||||
|
||||
/* NoLeadingOrTrailingDot */
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, ".", NULL));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/.bar", NULL));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/..bar", NULL));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/bar.", NULL));
|
||||
must_fail(ensure_refname_normalized(0, ".", NULL));
|
||||
must_fail(ensure_refname_normalized(0, "refs/heads/.bar", NULL));
|
||||
must_fail(ensure_refname_normalized(0, "refs/heads/..bar", NULL));
|
||||
must_fail(ensure_refname_normalized(0, "refs/heads/bar.", NULL));
|
||||
|
||||
/* ContainsDot */
|
||||
must_pass(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/m.a.s.t.e.r", "refs/heads/m.a.s.t.e.r"));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/master..pu", NULL));
|
||||
must_pass(ensure_refname_normalized(0, "refs/heads/m.a.s.t.e.r", "refs/heads/m.a.s.t.e.r"));
|
||||
must_fail(ensure_refname_normalized(0, "refs/heads/master..pu", NULL));
|
||||
|
||||
/* NoMagicRefCharacters */
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/master^", NULL));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/^master", NULL));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, "^refs/heads/master", NULL));
|
||||
must_fail(ensure_refname_normalized(0, "refs/heads/master^", NULL));
|
||||
must_fail(ensure_refname_normalized(0, "refs/heads/^master", NULL));
|
||||
must_fail(ensure_refname_normalized(0, "^refs/heads/master", NULL));
|
||||
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/master~", NULL));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/~master", NULL));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, "~refs/heads/master", NULL));
|
||||
must_fail(ensure_refname_normalized(0, "refs/heads/master~", NULL));
|
||||
must_fail(ensure_refname_normalized(0, "refs/heads/~master", NULL));
|
||||
must_fail(ensure_refname_normalized(0, "~refs/heads/master", NULL));
|
||||
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/master:", NULL));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/:master", NULL));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, ":refs/heads/master", NULL));
|
||||
must_fail(ensure_refname_normalized(0, "refs/heads/master:", NULL));
|
||||
must_fail(ensure_refname_normalized(0, "refs/heads/:master", NULL));
|
||||
must_fail(ensure_refname_normalized(0, ":refs/heads/master", NULL));
|
||||
|
||||
/* ShellGlob */
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/master?", NULL));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/?master", NULL));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, "?refs/heads/master", NULL));
|
||||
must_fail(ensure_refname_normalized(0, "refs/heads/master?", NULL));
|
||||
must_fail(ensure_refname_normalized(0, "refs/heads/?master", NULL));
|
||||
must_fail(ensure_refname_normalized(0, "?refs/heads/master", NULL));
|
||||
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/master[", NULL));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/[master", NULL));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, "[refs/heads/master", NULL));
|
||||
must_fail(ensure_refname_normalized(0, "refs/heads/master[", NULL));
|
||||
must_fail(ensure_refname_normalized(0, "refs/heads/[master", NULL));
|
||||
must_fail(ensure_refname_normalized(0, "[refs/heads/master", NULL));
|
||||
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/master*", NULL));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/*master", NULL));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, "*refs/heads/master", NULL));
|
||||
must_fail(ensure_refname_normalized(0, "refs/heads/master*", NULL));
|
||||
must_fail(ensure_refname_normalized(0, "refs/heads/*master", NULL));
|
||||
must_fail(ensure_refname_normalized(0, "*refs/heads/master", NULL));
|
||||
|
||||
/* ValidSpecialCharacters */
|
||||
must_pass(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/!", "refs/heads/!"));
|
||||
must_pass(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/\"", "refs/heads/\""));
|
||||
must_pass(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/#", "refs/heads/#"));
|
||||
must_pass(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/$", "refs/heads/$"));
|
||||
must_pass(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/%", "refs/heads/%"));
|
||||
must_pass(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/&", "refs/heads/&"));
|
||||
must_pass(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/'", "refs/heads/'"));
|
||||
must_pass(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/(", "refs/heads/("));
|
||||
must_pass(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/)", "refs/heads/)"));
|
||||
must_pass(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/+", "refs/heads/+"));
|
||||
must_pass(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/,", "refs/heads/,"));
|
||||
must_pass(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/-", "refs/heads/-"));
|
||||
must_pass(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/;", "refs/heads/;"));
|
||||
must_pass(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/<", "refs/heads/<"));
|
||||
must_pass(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/=", "refs/heads/="));
|
||||
must_pass(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/>", "refs/heads/>"));
|
||||
must_pass(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/@", "refs/heads/@"));
|
||||
must_pass(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/]", "refs/heads/]"));
|
||||
must_pass(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/_", "refs/heads/_"));
|
||||
must_pass(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/`", "refs/heads/`"));
|
||||
must_pass(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/{", "refs/heads/{"));
|
||||
must_pass(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/|", "refs/heads/|"));
|
||||
must_pass(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/}", "refs/heads/}"));
|
||||
must_pass(ensure_refname_normalized(0, "refs/heads/!", "refs/heads/!"));
|
||||
must_pass(ensure_refname_normalized(0, "refs/heads/\"", "refs/heads/\""));
|
||||
must_pass(ensure_refname_normalized(0, "refs/heads/#", "refs/heads/#"));
|
||||
must_pass(ensure_refname_normalized(0, "refs/heads/$", "refs/heads/$"));
|
||||
must_pass(ensure_refname_normalized(0, "refs/heads/%", "refs/heads/%"));
|
||||
must_pass(ensure_refname_normalized(0, "refs/heads/&", "refs/heads/&"));
|
||||
must_pass(ensure_refname_normalized(0, "refs/heads/'", "refs/heads/'"));
|
||||
must_pass(ensure_refname_normalized(0, "refs/heads/(", "refs/heads/("));
|
||||
must_pass(ensure_refname_normalized(0, "refs/heads/)", "refs/heads/)"));
|
||||
must_pass(ensure_refname_normalized(0, "refs/heads/+", "refs/heads/+"));
|
||||
must_pass(ensure_refname_normalized(0, "refs/heads/,", "refs/heads/,"));
|
||||
must_pass(ensure_refname_normalized(0, "refs/heads/-", "refs/heads/-"));
|
||||
must_pass(ensure_refname_normalized(0, "refs/heads/;", "refs/heads/;"));
|
||||
must_pass(ensure_refname_normalized(0, "refs/heads/<", "refs/heads/<"));
|
||||
must_pass(ensure_refname_normalized(0, "refs/heads/=", "refs/heads/="));
|
||||
must_pass(ensure_refname_normalized(0, "refs/heads/>", "refs/heads/>"));
|
||||
must_pass(ensure_refname_normalized(0, "refs/heads/@", "refs/heads/@"));
|
||||
must_pass(ensure_refname_normalized(0, "refs/heads/]", "refs/heads/]"));
|
||||
must_pass(ensure_refname_normalized(0, "refs/heads/_", "refs/heads/_"));
|
||||
must_pass(ensure_refname_normalized(0, "refs/heads/`", "refs/heads/`"));
|
||||
must_pass(ensure_refname_normalized(0, "refs/heads/{", "refs/heads/{"));
|
||||
must_pass(ensure_refname_normalized(0, "refs/heads/|", "refs/heads/|"));
|
||||
must_pass(ensure_refname_normalized(0, "refs/heads/}", "refs/heads/}"));
|
||||
|
||||
// This is valid on UNIX, but not on Windows
|
||||
// hence we make in invalid due to non-portability
|
||||
//
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/\\", NULL));
|
||||
must_fail(ensure_refname_normalized(0, "refs/heads/\\", NULL));
|
||||
|
||||
/* UnicodeNames */
|
||||
/*
|
||||
@ -474,8 +474,8 @@ BEGIN_TEST("normalizeref", jgit_tests)
|
||||
*/
|
||||
|
||||
/* RefLogQueryIsValidRef */
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/master@{1}", NULL));
|
||||
must_fail(ensure_refname_normalized(GIT_REF_ANY, "refs/heads/master@{1.hour.ago}", NULL));
|
||||
must_fail(ensure_refname_normalized(0, "refs/heads/master@{1}", NULL));
|
||||
must_fail(ensure_refname_normalized(0, "refs/heads/master@{1.hour.ago}", NULL));
|
||||
END_TEST
|
||||
|
||||
git_testsuite *libgit2_suite_refs(void)
|
||||
@ -493,7 +493,6 @@ git_testsuite *libgit2_suite_refs(void)
|
||||
ADD_TEST(suite, "createref", create_new_symbolic_ref);
|
||||
ADD_TEST(suite, "createref", create_deep_symbolic_ref);
|
||||
ADD_TEST(suite, "createref", create_new_object_id_ref);
|
||||
ADD_TEST(suite, "normalizeref", normalize_unknown_ref_type);
|
||||
ADD_TEST(suite, "normalizeref", normalize_object_id_ref);
|
||||
ADD_TEST(suite, "normalizeref", normalize_symbolic_ref);
|
||||
ADD_TEST(suite, "normalizeref", normalize_any_ref);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user