Commit ca8d2dfc by Carlos Martín Nieto

Merge remote-tracking branch 'upstream/development' into config

parents 094aaaae cc3b82e3
......@@ -28,7 +28,7 @@
#define LIBGIT2_VERSION "0.11.0"
#define LIBGIT2_VER_MAJOR 0
#define LIBGIT2_VER_MINOR 10
#define LIBGIT2_VER_MINOR 11
#define LIBGIT2_VER_REVISION 0
#include "git2/common.h"
......
......@@ -51,39 +51,29 @@ GIT_BEGIN_DECL
*
* In-memory only flags:
*/
#define GIT_IDXENTRY_UPDATE (1 << 16)
#define GIT_IDXENTRY_REMOVE (1 << 17)
#define GIT_IDXENTRY_UPTODATE (1 << 18)
#define GIT_IDXENTRY_ADDED (1 << 19)
#define GIT_IDXENTRY_UPDATE (1 << 0)
#define GIT_IDXENTRY_REMOVE (1 << 1)
#define GIT_IDXENTRY_UPTODATE (1 << 2)
#define GIT_IDXENTRY_ADDED (1 << 3)
#define GIT_IDXENTRY_HASHED (1 << 20)
#define GIT_IDXENTRY_UNHASHED (1 << 21)
#define GIT_IDXENTRY_WT_REMOVE (1 << 22) /* remove in work directory */
#define GIT_IDXENTRY_CONFLICTED (1 << 23)
#define GIT_IDXENTRY_HASHED (1 << 4)
#define GIT_IDXENTRY_UNHASHED (1 << 5)
#define GIT_IDXENTRY_WT_REMOVE (1 << 6) /* remove in work directory */
#define GIT_IDXENTRY_CONFLICTED (1 << 7)
#define GIT_IDXENTRY_UNPACKED (1 << 24)
#define GIT_IDXENTRY_NEW_SKIP_WORKTREE (1 << 25)
#define GIT_IDXENTRY_UNPACKED (1 << 8)
#define GIT_IDXENTRY_NEW_SKIP_WORKTREE (1 << 9)
/*
* Extended on-disk flags:
*/
#define GIT_IDXENTRY_INTENT_TO_ADD (1 << 29)
#define GIT_IDXENTRY_SKIP_WORKTREE (1 << 30)
#define GIT_IDXENTRY_INTENT_TO_ADD (1 << 13)
#define GIT_IDXENTRY_SKIP_WORKTREE (1 << 14)
/* GIT_IDXENTRY_EXTENDED2 is for future extension */
#define GIT_IDXENTRY_EXTENDED2 (1 << 31)
#define GIT_IDXENTRY_EXTENDED2 (1 << 15)
#define GIT_IDXENTRY_EXTENDED_FLAGS (GIT_IDXENTRY_INTENT_TO_ADD | GIT_IDXENTRY_SKIP_WORKTREE)
/*
* Safeguard to avoid saving wrong flags:
* - GIT_IDXENTRY_EXTENDED2 won't get saved until its semantic is known
* - Bits in 0x0000FFFF have been saved in flags already
* - Bits in 0x003F0000 are currently in-memory flags
*/
#if GIT_IDXENTRY_EXTENDED_FLAGS & 0x803FFFFF
#error "GIT_IDXENTRY_EXTENDED_FLAGS out of range"
#endif
/** Time used in a git index entry */
typedef struct {
git_time_t seconds;
......@@ -182,7 +172,12 @@ GIT_EXTERN(int) git_index_write(git_index *index);
GIT_EXTERN(int) git_index_find(git_index *index, const char *path);
/**
* Add or update an index entry from a file in disk.
* Add or update an index entry from a file in disk
*
* The file `path` must be relative to the repository's
* working folder and must be readable.
*
* This method will fail in bare index instances.
*
* @param index an existing index object
* @param path filename to add
......@@ -192,26 +187,62 @@ GIT_EXTERN(int) git_index_find(git_index *index, const char *path);
GIT_EXTERN(int) git_index_add(git_index *index, const char *path, int stage);
/**
* Remove an entry from the index
* Add or update an index entry from an in-memory struct
*
* A full copy (including the 'path' string) of the given
* 'source_entry' will be inserted on the index.
*
* @param index an existing index object
* @param position position of the entry to remove
* @param source_entry new entry object
* @return 0 on success, otherwise an error code
*/
GIT_EXTERN(int) git_index_remove(git_index *index, int position);
GIT_EXTERN(int) git_index_add2(git_index *index, const git_index_entry *source_entry);
/**
* Insert an entry into the index.
* Add (append) an index entry from a file in disk
*
* A new entry will always be inserted into the index;
* if the index already contains an entry for such
* path, the old entry will **not** be replaced.
*
* The file `path` must be relative to the repository's
* working folder and must be readable.
*
* This method will fail in bare index instances.
*
* @param index an existing index object
* @param path filename to add
* @param stage stage for the entry
* @return 0 on success, otherwise an error code
*/
GIT_EXTERN(int) git_index_append(git_index *index, const char *path, int stage);
/**
* Add (append) an index entry from an in-memory struct
*
* A new entry will always be inserted into the index;
* if the index already contains an entry for the path
* in the `entry` struct, the old entry will **not** be
* replaced.
*
* A full copy (including the 'path' string) of the given
* 'source_entry' will be inserted on the index; if the index
* already contains an entry for the same path, the entry
* will be updated.
* 'source_entry' will be inserted on the index.
*
* @param index an existing index object
* @param source_entry new entry object
* @return 0 on success, otherwise an error code
*/
GIT_EXTERN(int) git_index_insert(git_index *index, const git_index_entry *source_entry);
GIT_EXTERN(int) git_index_apppend2(git_index *index, const git_index_entry *source_entry);
/**
* Remove an entry from the index
*
* @param index an existing index object
* @param position position of the entry to remove
* @return 0 on success, otherwise an error code
*/
GIT_EXTERN(int) git_index_remove(git_index *index, int position);
/**
* Get a pointer to one of the entries in the index
......
......@@ -275,6 +275,23 @@ GIT_EXTERN(int) git_tag_delete(
git_repository *repo,
const char *tag_name);
/**
* Fill a list with all the tags in the Repository
*
* The string array will be filled with the names of the
* matching tags; these values are owned by the user and
* should be free'd manually when no longer needed, using
* `git_strarray_free`.
*
* @param array Pointer to a git_strarray structure where
* the tag names will be stored
* @param repo Repository where to find the tags
* @return 0 on success; error code otherwise
*/
GIT_EXTERN(int) git_tag_list(
git_strarray *tag_names,
git_repository *repo);
/** @} */
GIT_END_DECL
#endif
......@@ -115,6 +115,7 @@ int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *pat
error = stream->finalize_write(oid, stream);
stream->free(stream);
gitfo_close(fd);
return error;
}
......
......@@ -224,9 +224,18 @@ int git_commit_create(
if (error < GIT_SUCCESS)
return error;
if (git_reference_type(head) == GIT_REF_SYMBOLIC) {
if ((error = git_reference_resolve(&head, head)) < GIT_SUCCESS)
error = git_reference_resolve(&head, head);
if (error < GIT_SUCCESS) {
if (error != GIT_ENOTFOUND)
return error;
/*
* The target of the reference was not found. This can happen
* just after a repository has been initialized (the master
* branch doesn't exist yet, as it doesn't have anything to
* point to) or after an orphan checkout, so if the target
* branch doesn't exist yet, create it and return.
*/
return git_reference_create_oid_f(&head, repo, git_reference_target(head), oid);
}
error = git_reference_set_oid(head, oid);
......
......@@ -101,6 +101,7 @@ static int read_tree(git_index *index, const char *buffer, size_t buffer_size);
static git_index_tree *read_tree_internal(const char **, const char *, git_index_tree *);
static int parse_index(git_index *index, const char *buffer, size_t buffer_size);
static int is_index_extended(git_index *index);
static void sort_index(git_index *index);
static int write_index(git_index *index, git_filebuf *file);
......@@ -289,56 +290,12 @@ git_index_entry *git_index_get(git_index *index, int n)
return git_vector_get(&index->entries, (unsigned int)n);
}
int git_index_add(git_index *index, const char *rel_path, int stage)
{
git_index_entry entry;
char full_path[GIT_PATH_MAX];
struct stat st;
int error;
if (index->repository == NULL)
return GIT_EBAREINDEX;
git__joinpath(full_path, index->repository->path_workdir, rel_path);
if (gitfo_exists(full_path) < 0)
return GIT_ENOTFOUND;
if (gitfo_stat(full_path, &st) < 0)
return GIT_EOSERR;
if (stage < 0 || stage > 3)
return GIT_ERROR;
memset(&entry, 0x0, sizeof(git_index_entry));
entry.ctime.seconds = (git_time_t)st.st_ctime;
entry.mtime.seconds = (git_time_t)st.st_mtime;
/* entry.mtime.nanoseconds = st.st_mtimensec; */
/* entry.ctime.nanoseconds = st.st_ctimensec; */
entry.dev= st.st_rdev;
entry.ino = st.st_ino;
entry.mode = st.st_mode;
entry.uid = st.st_uid;
entry.gid = st.st_gid;
entry.file_size = st.st_size;
/* write the blob to disk and get the oid */
if ((error = git_blob_create_fromfile(&entry.oid, index->repository, rel_path)) < GIT_SUCCESS)
return error;
entry.flags |= (stage << GIT_IDXENTRY_STAGESHIFT);
entry.path = (char *)rel_path; /* do not duplicate; index_insert already does this */
return git_index_insert(index, &entry);
}
void sort_index(git_index *index)
static void sort_index(git_index *index)
{
git_vector_sort(&index->entries);
}
int git_index_insert(git_index *index, const git_index_entry *source_entry)
static int index_insert(git_index *index, const git_index_entry *source_entry, int replace)
{
git_index_entry *entry;
size_t path_length;
......@@ -374,13 +331,15 @@ int git_index_insert(git_index *index, const git_index_entry *source_entry)
/* look if an entry with this path already exists */
position = git_index_find(index, source_entry->path);
/* if no entry exists, add the entry at the end;
/* if no entry exists and replace is not set,
* add the entry at the end;
* the index is no longer sorted */
if (position == GIT_ENOTFOUND) {
if (!replace || position == GIT_ENOTFOUND) {
if (git_vector_insert(&index->entries, entry) < GIT_SUCCESS)
return GIT_ENOMEM;
/* if a previous entry exists, replace it */
/* if a previous entry exists and replace is set,
* replace it */
} else {
git_index_entry **entry_array = (git_index_entry **)index->entries.contents;
......@@ -393,6 +352,81 @@ int git_index_insert(git_index *index, const git_index_entry *source_entry)
return GIT_SUCCESS;
}
static int index_init_entry(git_index_entry *entry, git_index *index, const char *rel_path, int stage)
{
char full_path[GIT_PATH_MAX];
struct stat st;
int error;
if (index->repository == NULL)
return GIT_EBAREINDEX;
git__joinpath(full_path, index->repository->path_workdir, rel_path);
if (gitfo_exists(full_path) < 0)
return GIT_ENOTFOUND;
if (gitfo_stat(full_path, &st) < 0)
return GIT_EOSERR;
if (stage < 0 || stage > 3)
return GIT_ERROR;
memset(entry, 0x0, sizeof(git_index_entry));
entry->ctime.seconds = (git_time_t)st.st_ctime;
entry->mtime.seconds = (git_time_t)st.st_mtime;
/* entry.mtime.nanoseconds = st.st_mtimensec; */
/* entry.ctime.nanoseconds = st.st_ctimensec; */
entry->dev= st.st_rdev;
entry->ino = st.st_ino;
entry->mode = st.st_mode;
entry->uid = st.st_uid;
entry->gid = st.st_gid;
entry->file_size = st.st_size;
/* write the blob to disk and get the oid */
if ((error = git_blob_create_fromfile(&entry->oid, index->repository, rel_path)) < GIT_SUCCESS)
return error;
entry->flags |= (stage << GIT_IDXENTRY_STAGESHIFT);
entry->path = (char *)rel_path; /* do not duplicate; index_insert already does this */
return GIT_SUCCESS;
}
int git_index_add(git_index *index, const char *path, int stage)
{
int error;
git_index_entry entry;
if ((error = index_init_entry(&entry, index, path, stage)) < GIT_SUCCESS)
return error;
return index_insert(index, &entry, 1);
}
int git_index_append(git_index *index, const char *path, int stage)
{
int error;
git_index_entry entry;
if ((error = index_init_entry(&entry, index, path, stage)) < GIT_SUCCESS)
return error;
return index_insert(index, &entry, 0);
}
int git_index_add2(git_index *index, const git_index_entry *source_entry)
{
return index_insert(index, source_entry, 1);
}
int git_index_apppend2(git_index *index, const git_index_entry *source_entry)
{
return index_insert(index, source_entry, 0);
}
int git_index_remove(git_index *index, int position)
{
assert(index);
......@@ -685,6 +719,24 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
return GIT_SUCCESS;
}
static int is_index_extended(git_index *index)
{
unsigned int i, extended;
extended = 0;
for (i = 0; i < index->entries.length; ++i) {
git_index_entry *entry;
entry = git_vector_get(&index->entries, i);
entry->flags &= ~GIT_IDXENTRY_EXTENDED;
if (entry->flags_extended & GIT_IDXENTRY_EXTENDED_FLAGS) {
extended++;
entry->flags |= GIT_IDXENTRY_EXTENDED;
}
}
return extended;
}
static int write_disk_entry(git_filebuf *file, git_index_entry *entry)
{
struct entry_short *ondisk;
......@@ -753,12 +805,14 @@ static int write_index(git_index *index, git_filebuf *file)
struct index_header header;
int is_extended = 1;
int is_extended;
assert(index && file);
is_extended = is_index_extended(index);
header.signature = htonl(INDEX_HEADER_SIG);
header.version = htonl(is_extended ? INDEX_VERSION_NUMBER : INDEX_VERSION_NUMBER_EXT);
header.version = htonl(is_extended ? INDEX_VERSION_NUMBER_EXT : INDEX_VERSION_NUMBER);
header.entry_count = htonl(index->entries.length);
git_filebuf_write(file, &header, sizeof(struct index_header));
......
......@@ -434,6 +434,9 @@ static int read_header_loose(git_rawobj *out, const char *loc)
if ((read_bytes = read(fd, raw_buffer, sizeof(raw_buffer))) > 0) {
set_stream_input(&zs, raw_buffer, read_bytes);
z_return = inflate(&zs, 0);
} else {
z_return = Z_STREAM_END;
break;
}
} while (z_return == Z_OK);
......
......@@ -108,15 +108,12 @@ struct pack_entry {
struct pack_file *p;
};
struct pack__dirent {
struct pack_backend *backend;
int is_pack_local;
};
struct pack_backend {
git_odb_backend parent;
git_vector packs;
struct pack_file *last_found;
char *pack_folder;
time_t pack_folder_mtime;
size_t window_size; /* needs default value */
......@@ -259,9 +256,9 @@ static int pack_index_open(struct pack_file *p);
static struct pack_file *packfile_alloc(int extra);
static int packfile_open(struct pack_file *p);
static int packfile_check(struct pack_file **pack_out, const char *path, int local);
static int packfile_check(struct pack_file **pack_out, const char *path);
static int packfile_load__cb(void *_data, char *path);
static int packfile_load_all(struct pack_backend *backend, const char *odb_path, int local);
static int packfile_refresh_all(struct pack_backend *backend);
static off_t nth_packed_object_offset(const struct pack_file *p, uint32_t n);
......@@ -790,7 +787,7 @@ cleanup:
return GIT_EPACKCORRUPTED;
}
static int packfile_check(struct pack_file **pack_out, const char *path, int local)
static int packfile_check(struct pack_file **pack_out, const char *path)
{
struct stat st;
struct pack_file *p;
......@@ -826,7 +823,7 @@ static int packfile_check(struct pack_file **pack_out, const char *path, int loc
* actually mapping the pack file.
*/
p->pack_size = (off_t)st.st_size;
p->pack_local = local;
p->pack_local = 1;
p->mtime = (git_time_t)st.st_mtime;
/* see if we can parse the sha1 oid in the packfile name */
......@@ -840,22 +837,25 @@ static int packfile_check(struct pack_file **pack_out, const char *path, int loc
static int packfile_load__cb(void *_data, char *path)
{
struct pack__dirent *data = (struct pack__dirent *)_data;
struct pack_backend *backend = (struct pack_backend *)_data;
struct pack_file *pack;
int error;
size_t i;
if (git__suffixcmp(path, ".idx") != 0)
return GIT_SUCCESS; /* not an index */
/* FIXME: git.git checks for duplicate packs.
* But that makes no fucking sense. Our dirent is not
* going to generate dupicate entries */
for (i = 0; i < backend->packs.length; ++i) {
struct pack_file *p = git_vector_get(&backend->packs, i);
if (memcmp(p->pack_name, path, strlen(path) - STRLEN(".idx")) == 0)
return GIT_SUCCESS;
}
error = packfile_check(&pack, path, data->is_pack_local);
error = packfile_check(&pack, path);
if (error < GIT_SUCCESS)
return error;
if (git_vector_insert(&data->backend->packs, pack) < GIT_SUCCESS) {
if (git_vector_insert(&backend->packs, pack) < GIT_SUCCESS) {
free(pack);
return GIT_ENOMEM;
}
......@@ -863,25 +863,29 @@ static int packfile_load__cb(void *_data, char *path)
return GIT_SUCCESS;
}
static int packfile_load_all(struct pack_backend *backend, const char *odb_path, int local)
static int packfile_refresh_all(struct pack_backend *backend)
{
int error;
char path[GIT_PATH_MAX];
struct pack__dirent data;
data.backend = backend;
data.is_pack_local = local;
struct stat st;
git__joinpath(path, odb_path, "pack");
if (gitfo_isdir(path) < GIT_SUCCESS)
if (backend->pack_folder == NULL)
return GIT_SUCCESS;
error = gitfo_dirent(path, GIT_PATH_MAX, packfile_load__cb, (void *)&data);
if (error < GIT_SUCCESS)
return error;
if (gitfo_stat(backend->pack_folder, &st) < 0 || !S_ISDIR(st.st_mode))
return GIT_ENOTFOUND;
git_vector_sort(&backend->packs);
backend->last_found = git_vector_get(&backend->packs, 0);
if (st.st_mtime != backend->pack_folder_mtime) {
char path[GIT_PATH_MAX];
strcpy(path, backend->pack_folder);
/* reload all packs */
error = gitfo_dirent(path, GIT_PATH_MAX, packfile_load__cb, (void *)backend);
if (error < GIT_SUCCESS)
return error;
git_vector_sort(&backend->packs);
backend->pack_folder_mtime = st.st_mtime;
}
return GIT_SUCCESS;
}
......@@ -1026,8 +1030,12 @@ static int pack_entry_find1(
static int pack_entry_find(struct pack_entry *e, struct pack_backend *backend, const git_oid *oid)
{
int error;
size_t i;
if ((error = packfile_refresh_all(backend)) < GIT_SUCCESS)
return error;
if (backend->last_found &&
pack_entry_find1(e, backend->last_found, oid) == GIT_SUCCESS)
return GIT_SUCCESS;
......@@ -1377,13 +1385,14 @@ void pack_backend__free(git_odb_backend *_backend)
}
git_vector_free(&backend->packs);
free(backend->pack_folder);
free(backend);
}
int git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir)
{
int error;
struct pack_backend *backend;
char path[GIT_PATH_MAX];
backend = git__calloc(1, sizeof(struct pack_backend));
if (backend == NULL)
......@@ -1397,10 +1406,15 @@ int git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir)
backend->window_size = DEFAULT_WINDOW_SIZE;
backend->mapped_limit = DEFAULT_MAPPED_LIMIT;
error = packfile_load_all(backend, objects_dir, 1);
if (error < GIT_SUCCESS) {
pack_backend__free((git_odb_backend *)backend);
return error;
git__joinpath(path, objects_dir, "pack");
if (gitfo_isdir(path) == GIT_SUCCESS) {
backend->pack_folder = git__strdup(path);
backend->pack_folder_mtime = 0;
if (backend->pack_folder == NULL) {
free(backend);
return GIT_ENOMEM;
}
}
backend->parent.read = &pack_backend__read;
......
......@@ -684,7 +684,7 @@ static int packed_loadloose(git_repository *repository)
/* Remove any loose references from the cache */
{
const void *_unused;
const void *GIT_UNUSED(_unused);
git_reference *reference;
GIT_HASHTABLE_FOREACH(repository->references.loose_cache, _unused, reference,
......@@ -787,6 +787,8 @@ static int packed_find_peel(reference_oid *ref)
*/
}
git_object_close(object);
return GIT_SUCCESS;
}
......@@ -868,7 +870,7 @@ static int packed_write(git_repository *repo)
/* Load all the packfile into a vector */
{
git_reference *reference;
const void *_unused;
const void *GIT_UNUSED(_unused);
GIT_HASHTABLE_FOREACH(repo->references.packfile, _unused, reference,
git_vector_insert(&packing_list, reference); /* cannot fail: vector already has the right size */
......@@ -1480,8 +1482,9 @@ int git_reference_resolve(git_reference **resolved_ref, git_reference *ref)
for (i = 0; i < MAX_NESTING_LEVEL; ++i) {
reference_symbolic *ref_sym;
*resolved_ref = ref;
if (ref->type & GIT_REF_OID) {
*resolved_ref = ref;
return GIT_SUCCESS;
}
......@@ -1518,7 +1521,7 @@ int git_reference_listcb(git_repository *repo, unsigned int list_flags, int (*ca
/* list all the packed references first */
if (list_flags & GIT_REF_PACKED) {
const char *ref_name;
void *_unused;
void *GIT_UNUSED(_unused);
if ((error = packed_load(repo)) < GIT_SUCCESS)
return error;
......@@ -1597,7 +1600,7 @@ int git_repository__refcache_init(git_refcache *refs)
void git_repository__refcache_free(git_refcache *refs)
{
git_reference *reference;
const void *_unused;
const void *GIT_UNUSED(_unused);
assert(refs);
......@@ -1692,8 +1695,9 @@ static int normalize_name(char *buffer_out, const char *name, int is_oid_ref)
}
/* Object id refname have to contain at least one slash, except
* for HEAD in a detached state */
if (is_oid_ref && !contains_a_slash && strcmp(name, GIT_HEAD_FILE))
* for HEAD in a detached state or MERGE_HEAD if we're in the
* middle of a merge */
if (is_oid_ref && !contains_a_slash && (strcmp(name, GIT_HEAD_FILE) && strcmp(name, GIT_MERGE_HEAD_FILE)))
return GIT_EINVALIDREFNAME;
/* A refname can not end with ".lock" */
......
......@@ -17,6 +17,7 @@
#define MAX_GITDIR_TREE_STRUCTURE_PATH_LENGTH 100
#define GIT_HEAD_FILE "HEAD"
#define GIT_MERGE_HEAD_FILE "MERGE_HEAD"
#define GIT_REFS_HEADS_MASTER_FILE GIT_REFS_HEADS_DIR "master"
struct git_reference {
......
......@@ -58,7 +58,6 @@ static int assign_repository_dirs(
const char *git_work_tree)
{
char path_aux[GIT_PATH_MAX];
size_t git_dir_path_len;
int error = GIT_SUCCESS;
assert(repo);
......@@ -70,8 +69,6 @@ static int assign_repository_dirs(
if (error < GIT_SUCCESS)
return error;
git_dir_path_len = strlen(path_aux);
/* store GIT_DIR */
repo->path_repository = git__strdup(path_aux);
if (repo->path_repository == NULL)
......
......@@ -483,7 +483,7 @@ int git_revwalk_new(git_revwalk **revwalk_out, git_repository *repo)
void git_revwalk_free(git_revwalk *walk)
{
unsigned int i;
const void *_unused;
const void *GIT_UNUSED(_unused);
commit_object *commit;
if (walk == NULL)
......@@ -558,7 +558,7 @@ int git_revwalk_next(git_oid *oid, git_revwalk *walk)
void git_revwalk_reset(git_revwalk *walk)
{
const void *_unused;
const void *GIT_UNUSED(_unused);
commit_object *commit;
assert(walk);
......
......@@ -377,3 +377,29 @@ int git_tag__parse(git_tag *tag, git_odb_object *obj)
return parse_tag_buffer(tag, obj->raw.data, (char *)obj->raw.data + obj->raw.len);
}
static int tag_list_cb(const char *tag_name, void *payload)
{
if (git__prefixcmp(tag_name, GIT_REFS_TAGS_DIR) == 0)
return git_vector_insert((git_vector *)payload, git__strdup(tag_name));
return GIT_SUCCESS;
}
int git_tag_list(git_strarray *tag_names, git_repository *repo)
{
int error;
git_vector taglist;
if (git_vector_init(&taglist, 8, NULL) < GIT_SUCCESS)
return GIT_ENOMEM;
error = git_reference_listcb(repo, GIT_REF_OID|GIT_REF_PACKED, &tag_list_cb, (void *)&taglist);
if (error < GIT_SUCCESS) {
git_vector_free(&taglist);
return error;
}
tag_names->strings = (char **)taglist.contents;
tag_names->count = taglist.length;
return GIT_SUCCESS;
}
......@@ -424,7 +424,8 @@ int git_treebuilder_write(git_oid *oid, git_repository *repo, git_treebuilder *b
if (entry->removed)
continue;
size += (entry->attr > 0x7FF) ? 7 : 6;
snprintf(filemode, sizeof(filemode), "%o ", entry->attr);
size += strlen(filemode);
size += entry->filename_len + 1;
size += GIT_OID_RAWSZ;
}
......
......@@ -368,7 +368,7 @@ BEGIN_TEST(details0, "query the details on a parsed commit")
const char *message, *message_short;
git_time_t commit_time;
unsigned int parents, p;
git_commit *parent;
git_commit *parent = NULL, *old_parent = NULL;
git_oid_mkstr(&id, commit_ids[i]);
......@@ -390,11 +390,19 @@ BEGIN_TEST(details0, "query the details on a parsed commit")
must_be_true(commit_time > 0);
must_be_true(parents <= 2);
for (p = 0;p < parents;p++) {
if (old_parent != NULL)
git_commit_close(old_parent);
old_parent = parent;
must_pass(git_commit_parent(&parent, commit, p));
must_be_true(parent != NULL);
must_be_true(git_commit_author(parent) != NULL); // is it really a commit?
}
git_commit_close(old_parent);
git_commit_close(parent);
must_fail(git_commit_parent(&parent, commit, parents));
git_commit_close(commit);
}
git_repository_free(repo);
......@@ -462,9 +470,76 @@ BEGIN_TEST(write0, "write a new commit object from memory to disk")
must_pass(remove_loose_object(REPOSITORY_FOLDER, (git_object *)commit));
git_commit_close(commit);
git_repository_free(repo);
END_TEST
#define ROOT_COMMIT_MESSAGE "This is a root commit\n\
This is a root commit and should be the only one in this branch\n"
BEGIN_TEST(root0, "create a root commit")
git_repository *repo;
git_commit *commit;
git_oid tree_id, commit_id;
const git_oid *branch_oid;
const git_signature *author, *committer;
const char *branch_name = "refs/heads/root-commit-branch";
git_reference *head, *branch;
char *head_old;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
git_oid_mkstr(&tree_id, tree_oid);
/* create signatures */
committer = git_signature_new(COMMITTER_NAME, COMMITTER_EMAIL, 123456789, 60);
must_be_true(committer != NULL);
author = git_signature_new(COMMITTER_NAME, COMMITTER_EMAIL, 987654321, 90);
must_be_true(author != NULL);
/* First we need to update HEAD so it points to our non-existant branch */
must_pass(git_reference_lookup(&head, repo, "HEAD"));
must_be_true(git_reference_type(head) == GIT_REF_SYMBOLIC);
head_old = git__strdup(git_reference_target(head));
must_be_true(head_old != NULL);
must_pass(git_reference_set_target(head, branch_name));
must_pass(git_commit_create_v(
&commit_id, /* out id */
repo,
"HEAD",
author,
committer,
ROOT_COMMIT_MESSAGE,
&tree_id,
0));
git_signature_free((git_signature *)committer);
git_signature_free((git_signature *)author);
/*
* The fact that creating a commit works has already been
* tested. Here we just make sure it's our commit and that it was
* written as a root commit.
*/
must_pass(git_commit_lookup(&commit, repo, &commit_id));
must_be_true(git_commit_parentcount(commit) == 0);
must_pass(git_reference_lookup(&branch, repo, branch_name));
branch_oid = git_reference_oid(branch);
must_pass(git_oid_cmp(branch_oid, &commit_id));
must_be_true(!strcmp(git_commit_message(commit), ROOT_COMMIT_MESSAGE));
/* Remove the data we just added to the repo */
must_pass(git_reference_lookup(&head, repo, "HEAD"));
must_pass(git_reference_set_target(head, head_old));
must_pass(git_reference_delete(branch));
must_pass(remove_loose_object(REPOSITORY_FOLDER, (git_object *)commit));
free(head_old);
git_commit_close(commit);
git_repository_free(repo);
END_TEST
BEGIN_SUITE(commit)
ADD_TEST(parse0);
......@@ -474,4 +549,6 @@ BEGIN_SUITE(commit)
ADD_TEST(write0);
//ADD_TEST(write1);
ADD_TEST(root0);
END_SUITE
......@@ -155,7 +155,7 @@ BEGIN_TEST(tableit0, "iterate through all the contents of the table")
const int objects_n = 32;
int i;
table_item *objects, *ob;
const void *_unused;
const void *GIT_UNUSED(_unused);
git_hashtable *table = NULL;
......
......@@ -64,6 +64,19 @@ BEGIN_TEST(read0, "read and parse a tag from the repository")
git_repository_free(repo);
END_TEST
BEGIN_TEST(read1, "list all tag names from the repository")
git_repository *repo;
git_strarray tag_list;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
must_pass(git_tag_list(&tag_list, repo));
must_be_true(tag_list.count == 3);
git_strarray_free(&tag_list);
git_repository_free(repo);
END_TEST
#define TAGGER_NAME "Vicent Marti"
#define TAGGER_EMAIL "vicent@github.com"
......@@ -227,6 +240,7 @@ END_TEST
BEGIN_SUITE(tag)
ADD_TEST(read0);
ADD_TEST(read1);
ADD_TEST(write0);
ADD_TEST(write1);
ADD_TEST(write2);
......
......@@ -32,6 +32,7 @@ static const char *tree_oid = "1810dff58d8a660512d4832e740f692884338ccd";
static const char *blob_oid = "fa49b077972391ad58037050f2a75f74e3671e92";
static const char *first_tree = "181037049a54a1eb5fab404658a3a250b44335d7";
static const char *second_tree = "f60079018b664e4e79329a7ef9559c8d9e0378d1";
static const char *third_tree = "eb86d8b81d6adbd5290a935d6c9976882de98488";
#if 0
static int print_tree(git_repository *repo, const git_oid *tree_oid, int depth)
......@@ -82,6 +83,7 @@ BEGIN_TEST(read0, "acces randomly the entries on a loaded tree")
must_be_true(git_tree_entry_byindex(tree, 3) == NULL);
must_be_true(git_tree_entry_byindex(tree, -1) == NULL);
git_tree_close(tree);
git_repository_free(repo);
END_TEST
......@@ -102,7 +104,9 @@ BEGIN_TEST(read1, "read a tree from the repository")
/* GH-86: git_object_lookup() should also check the type if the object comes from the cache */
must_be_true(git_object_lookup(&obj, repo, &id, GIT_OBJ_TREE) == 0);
git_object_close(obj);
must_be_true(git_object_lookup(&obj, repo, &id, GIT_OBJ_BLOB) == GIT_EINVALIDTYPE);
git_object_close(obj);
entry = git_tree_entry_byname(tree, "README");
must_be_true(entry != NULL);
......@@ -111,6 +115,8 @@ BEGIN_TEST(read1, "read a tree from the repository")
must_pass(git_tree_entry_2object(&obj, repo, entry));
git_object_close(obj);
git_tree_close(tree);
git_repository_free(repo);
END_TEST
......@@ -148,9 +154,50 @@ BEGIN_TEST(write2, "write a tree from a memory")
must_pass(git_treebuilder_write(&rid,repo,builder));
must_be_true(git_oid_cmp(&rid, &id2) == 0);
git_treebuilder_free(builder);
git_tree_close(tree);
close_temp_repo(repo);
END_TEST
BEGIN_TEST(write3, "write a hierarchical tree from a memory")
git_repository *repo;
git_treebuilder *builder;
git_tree *tree;
git_oid id, bid, subtree_id, id2, id3;
git_oid id_hiearar;
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
git_oid_mkstr(&id, first_tree);
git_oid_mkstr(&id2, second_tree);
git_oid_mkstr(&id3, third_tree);
git_oid_mkstr(&bid, blob_oid);
//create subtree
must_pass(git_treebuilder_create(&builder, NULL));
must_pass(git_treebuilder_insert(NULL,builder,"new.txt",&bid,0100644));
must_pass(git_treebuilder_write(&subtree_id,repo,builder));
git_treebuilder_free(builder);
// create parent tree
must_pass(git_tree_lookup(&tree, repo, &id));
must_pass(git_treebuilder_create(&builder, tree));
must_pass(git_treebuilder_insert(NULL,builder,"new",&subtree_id,040000));
must_pass(git_treebuilder_write(&id_hiearar,repo,builder));
git_treebuilder_free(builder);
git_tree_close(tree);
must_be_true(git_oid_cmp(&id_hiearar, &id3) == 0);
// check data is correct
must_pass(git_tree_lookup(&tree, repo, &id_hiearar));
must_be_true(2 == git_tree_entrycount(tree));
git_tree_close(tree);
close_temp_repo(repo);
END_TEST
BEGIN_SUITE(tree)
//ADD_TEST(print0);
ADD_TEST(read0);
......@@ -158,5 +205,6 @@ BEGIN_SUITE(tree)
//ADD_TEST(write0);
//ADD_TEST(write1);
ADD_TEST(write2);
ADD_TEST(write3);
END_SUITE
......@@ -51,6 +51,7 @@ BEGIN_TEST(readtag0, "lookup a loose tag reference")
git__joinpath(ref_name_from_tag_name, GIT_REFS_TAGS_DIR, git_tag_name((git_tag *)object));
must_be_true(strcmp(ref_name_from_tag_name, loose_tag_ref_name) == 0);
git_object_close(object);
git_repository_free(repo);
END_TEST
......@@ -91,6 +92,7 @@ BEGIN_TEST(readsym0, "lookup a symbolic reference")
git_oid_mkstr(&id, current_master_tip);
must_be_true(git_oid_cmp(&id, git_object_id(object)) == 0);
git_object_close(object);
git_repository_free(repo);
END_TEST
......@@ -117,6 +119,7 @@ BEGIN_TEST(readsym1, "lookup a nested symbolic reference")
git_oid_mkstr(&id, current_master_tip);
must_be_true(git_oid_cmp(&id, git_object_id(object)) == 0);
git_object_close(object);
git_repository_free(repo);
END_TEST
......@@ -175,6 +178,7 @@ BEGIN_TEST(readpacked0, "lookup a packed reference")
must_be_true(object != NULL);
must_be_true(git_object_type(object) == GIT_OBJ_COMMIT);
git_object_close(object);
git_repository_free(repo);
END_TEST
......@@ -194,7 +198,7 @@ END_TEST
BEGIN_TEST(create0, "create a new symbolic reference")
git_reference *new_reference, *looked_up_ref, *resolved_ref;
git_repository *repo;
git_repository *repo, *repo2;
git_oid id;
char ref_path[GIT_PATH_MAX];
......@@ -202,7 +206,7 @@ BEGIN_TEST(create0, "create a new symbolic reference")
git_oid_mkstr(&id, current_master_tip);
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
/* Retrieve the physical path to the symbolic ref for further cleaning */
git__joinpath(ref_path, repo->path_repository, new_head_tracker);
......@@ -226,14 +230,13 @@ BEGIN_TEST(create0, "create a new symbolic reference")
git_repository_free(repo);
/* Similar test with a fresh new repository */
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
must_pass(git_repository_open(&repo2, TEMP_REPO_FOLDER));
must_pass(git_reference_lookup(&looked_up_ref, repo, new_head_tracker));
must_pass(git_reference_lookup(&looked_up_ref, repo2, new_head_tracker));
must_pass(git_reference_resolve(&resolved_ref, looked_up_ref));
must_be_true(git_oid_cmp(&id, git_reference_oid(resolved_ref)) == 0);
git_reference_delete(looked_up_ref);
git_repository_free(repo);
close_temp_repo(repo2);
END_TEST
BEGIN_TEST(create1, "create a deep symbolic reference")
......@@ -246,7 +249,7 @@ BEGIN_TEST(create1, "create a deep symbolic reference")
git_oid_mkstr(&id, current_master_tip);
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
git__joinpath(ref_path, repo->path_repository, new_head_tracker);
must_pass(git_reference_create_symbolic(&new_reference, repo, new_head_tracker, current_head_target));
......@@ -254,13 +257,12 @@ BEGIN_TEST(create1, "create a deep symbolic reference")
must_pass(git_reference_resolve(&resolved_ref, looked_up_ref));
must_be_true(git_oid_cmp(&id, git_reference_oid(resolved_ref)) == 0);
git_reference_delete(looked_up_ref);
git_repository_free(repo);
close_temp_repo(repo);
END_TEST
BEGIN_TEST(create2, "create a new OID reference")
git_reference *new_reference, *looked_up_ref;
git_repository *repo;
git_repository *repo, *repo2;
git_oid id;
char ref_path[GIT_PATH_MAX];
......@@ -268,7 +270,7 @@ BEGIN_TEST(create2, "create a new OID reference")
git_oid_mkstr(&id, current_master_tip);
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
/* Retrieve the physical path to the symbolic ref for further cleaning */
git__joinpath(ref_path, repo->path_repository, new_head);
......@@ -288,13 +290,12 @@ BEGIN_TEST(create2, "create a new OID reference")
git_repository_free(repo);
/* Similar test with a fresh new repository */
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
must_pass(git_repository_open(&repo2, TEMP_REPO_FOLDER));
must_pass(git_reference_lookup(&looked_up_ref, repo, new_head));
must_be_true(git_oid_cmp(&id, git_reference_oid(looked_up_ref)) == 0);
git_reference_delete(looked_up_ref);
git_repository_free(repo);
close_temp_repo(repo2);
END_TEST
BEGIN_TEST(create3, "Can not create a new OID reference which targets at an unknown id")
......@@ -325,7 +326,7 @@ BEGIN_TEST(overwrite0, "Overwrite an existing symbolic reference")
git_reference *ref, *branch_ref;
git_repository *repo;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
/* The target needds to exist and we need to check the name has changed */
must_pass(git_reference_create_symbolic(&branch_ref, repo, ref_branch_name, ref_master_name));
......@@ -344,9 +345,7 @@ BEGIN_TEST(overwrite0, "Overwrite an existing symbolic reference")
must_be_true(git_reference_type(ref) & GIT_REF_SYMBOLIC);
must_be_true(!strcmp(git_reference_target(ref), ref_master_name));
must_pass(git_reference_delete(ref));
must_pass(git_reference_delete(branch_ref));
git_repository_free(repo);
close_temp_repo(repo);
END_TEST
BEGIN_TEST(overwrite1, "Overwrite an existing object id reference")
......@@ -354,7 +353,7 @@ BEGIN_TEST(overwrite1, "Overwrite an existing object id reference")
git_repository *repo;
git_oid id;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
must_pass(git_reference_lookup(&ref, repo, ref_master_name));
must_be_true(ref->type & GIT_REF_OID);
......@@ -375,8 +374,7 @@ BEGIN_TEST(overwrite1, "Overwrite an existing object id reference")
must_pass(git_reference_lookup(&ref, repo, ref_name));
must_be_true(!git_oid_cmp(&id, git_reference_oid(ref)));
git_reference_delete(ref);
git_repository_free(repo);
close_temp_repo(repo);
END_TEST
BEGIN_TEST(overwrite2, "Overwrite an existing object id reference with a symbolic one")
......@@ -384,7 +382,7 @@ BEGIN_TEST(overwrite2, "Overwrite an existing object id reference with a symboli
git_repository *repo;
git_oid id;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
must_pass(git_reference_lookup(&ref, repo, ref_master_name));
must_be_true(ref->type & GIT_REF_OID);
......@@ -399,8 +397,7 @@ BEGIN_TEST(overwrite2, "Overwrite an existing object id reference with a symboli
must_be_true(git_reference_type(ref) & GIT_REF_SYMBOLIC);
must_be_true(!strcmp(git_reference_target(ref), ref_master_name));
git_reference_delete(ref);
git_repository_free(repo);
close_temp_repo(repo);
END_TEST
BEGIN_TEST(overwrite3, "Overwrite an existing symbolic reference with an object id one")
......@@ -408,7 +405,7 @@ BEGIN_TEST(overwrite3, "Overwrite an existing symbolic reference with an object
git_repository *repo;
git_oid id;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
must_pass(git_reference_lookup(&ref, repo, ref_master_name));
must_be_true(ref->type & GIT_REF_OID);
......@@ -425,8 +422,7 @@ BEGIN_TEST(overwrite3, "Overwrite an existing symbolic reference with an object
must_be_true(git_reference_type(ref) & GIT_REF_OID);
must_be_true(!git_oid_cmp(git_reference_oid(ref), &id));
git_reference_delete(ref);
git_repository_free(repo);
close_temp_repo(repo);
END_TEST
BEGIN_TEST(pack0, "create a packfile for an empty folder")
......
......@@ -130,6 +130,7 @@ static void free_suite(git_testsuite *ts)
if (ts->list[n])
test_free(ts->list[n]);
free(ts->name);
free(ts);
}
......
......@@ -4,7 +4,7 @@ from waflib.Build import BuildContext, CleanContext, \
InstallContext, UninstallContext
# Unix flags
CFLAGS_UNIX = ["-O2", "-Wall", "-Wextra"]
CFLAGS_UNIX = ["-O2", "-Wall", "-Wextra", "-fPIC"]
CFLAGS_UNIX_DBG = ['-g', '-O0']
# Windows MSVC flags
......@@ -65,6 +65,9 @@ def configure(conf):
else:
conf.env.PLATFORM = 'unix'
if conf.env.DEST_OS == 'sunos':
conf.env.DEFINES += ['NO_VIZ']
if conf.options.threadsafe:
if conf.env.PLATFORM == 'unix':
conf.check_cc(lib='pthread', uselib_store='pthread')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment