summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarlos Martín Nieto <cmn@elego.de>2011-05-05 16:22:06 +0200
committerCarlos Martín Nieto <cmn@elego.de>2011-05-05 16:22:06 +0200
commitca8d2dfc0cea0c16e2d6bae16d95d652e292f473 (patch)
treef98e0c362a388f9a9efe644ac3e38828f5f14807 /src
parent094aaaaee92f4fc98a6c3c3af36183cb217948a8 (diff)
parentcc3b82e376e0216c1af4ad46d24327d61e9efd99 (diff)
downloadlibgit2-ca8d2dfc0cea0c16e2d6bae16d95d652e292f473.tar.gz
Merge remote-tracking branch 'upstream/development' into config
Diffstat (limited to 'src')
-rw-r--r--src/blob.c1
-rw-r--r--src/commit.c13
-rw-r--r--src/index.c156
-rw-r--r--src/odb_loose.c3
-rw-r--r--src/odb_pack.c80
-rw-r--r--src/refs.c18
-rw-r--r--src/refs.h1
-rw-r--r--src/repository.c3
-rw-r--r--src/revwalk.c4
-rw-r--r--src/tag.c26
-rw-r--r--src/tree.c3
11 files changed, 209 insertions, 99 deletions
diff --git a/src/blob.c b/src/blob.c
index bc0a08a8a..5e3c22fbf 100644
--- a/src/blob.c
+++ b/src/blob.c
@@ -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;
}
diff --git a/src/commit.c b/src/commit.c
index 9621703c3..0c37ec59b 100644
--- a/src/commit.c
+++ b/src/commit.c
@@ -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);
diff --git a/src/index.c b/src/index.c
index 68bb9e2b9..130d1fd36 100644
--- a/src/index.c
+++ b/src/index.c
@@ -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));
diff --git a/src/odb_loose.c b/src/odb_loose.c
index 8ee01cd2c..4f475f2c3 100644
--- a/src/odb_loose.c
+++ b/src/odb_loose.c
@@ -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);
diff --git a/src/odb_pack.c b/src/odb_pack.c
index 8c527bcf3..57ad5e34b 100644
--- a/src/odb_pack.c
+++ b/src/odb_pack.c
@@ -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;
diff --git a/src/refs.c b/src/refs.c
index 00b9ff6b2..ea968196f 100644
--- a/src/refs.c
+++ b/src/refs.c
@@ -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" */
diff --git a/src/refs.h b/src/refs.h
index bebb1b97d..b8f3e2f6d 100644
--- a/src/refs.h
+++ b/src/refs.h
@@ -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 {
diff --git a/src/repository.c b/src/repository.c
index c428b00af..8cc2644ca 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -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)
diff --git a/src/revwalk.c b/src/revwalk.c
index b62b09961..78798480f 100644
--- a/src/revwalk.c
+++ b/src/revwalk.c
@@ -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);
diff --git a/src/tag.c b/src/tag.c
index a3400957f..148eb280c 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -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;
+}
diff --git a/src/tree.c b/src/tree.c
index 64f81d780..b7daf39c4 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -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;
}