Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/libgit2.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2013-04-30 23:56:41 +0400
committerEdward Thomson <ethomson@edwardthomson.com>2013-05-01 01:01:11 +0400
commit0462fba538b380551cbd5d8c05281352ba7a7471 (patch)
treeea9c353de8f20b0ed68fb0cf3c747677d876b9fe /src/index.c
parentbec65a5e994bc4701216c9ca2c7dae83770b3edc (diff)
renames!
Diffstat (limited to 'src/index.c')
-rw-r--r--src/index.c218
1 files changed, 218 insertions, 0 deletions
diff --git a/src/index.c b/src/index.c
index fe3a2104b..656fb5bc5 100644
--- a/src/index.c
+++ b/src/index.c
@@ -35,6 +35,7 @@ static const unsigned int INDEX_VERSION_NUMBER_EXT = 3;
static const unsigned int INDEX_HEADER_SIG = 0x44495243;
static const char INDEX_EXT_TREECACHE_SIG[] = {'T', 'R', 'E', 'E'};
static const char INDEX_EXT_UNMERGED_SIG[] = {'R', 'E', 'U', 'C'};
+static const char INDEX_EXT_CONFLICT_NAME_SIG[] = {'N', 'A', 'M', 'E'};
#define INDEX_OWNER(idx) ((git_repository *)(GIT_REFCOUNT_OWNER(idx)))
@@ -187,6 +188,46 @@ static int index_icmp(const void *a, const void *b)
return diff;
}
+static int conflict_name_cmp(const void *a, const void *b)
+{
+ const git_index_name_entry *name_a = a;
+ const git_index_name_entry *name_b = b;
+
+ if (name_a->ancestor && !name_b->ancestor)
+ return 1;
+
+ if (!name_a->ancestor && name_b->ancestor)
+ return -1;
+
+ if (name_a->ancestor)
+ return strcmp(name_a->ancestor, name_b->ancestor);
+
+ if (!name_a->ours || !name_b->ours)
+ return 0;
+
+ return strcmp(name_a->ours, name_b->ours);
+}
+
+static int conflict_name_icmp(const void *a, const void *b)
+{
+ const git_index_name_entry *name_a = a;
+ const git_index_name_entry *name_b = b;
+
+ if (name_a->ancestor && !name_b->ancestor)
+ return 1;
+
+ if (!name_a->ancestor && name_b->ancestor)
+ return -1;
+
+ if (name_a->ancestor)
+ return strcasecmp(name_a->ancestor, name_b->ancestor);
+
+ if (!name_a->ours || !name_b->ours)
+ return 0;
+
+ return strcasecmp(name_a->ours, name_b->ours);
+}
+
static int reuc_srch(const void *key, const void *array_member)
{
const git_index_reuc_entry *reuc = array_member;
@@ -278,6 +319,7 @@ int git_index_open(git_index **index_out, const char *index_path)
}
if (git_vector_init(&index->entries, 32, index_cmp) < 0 ||
+ git_vector_init(&index->names, 32, conflict_name_cmp) < 0 ||
git_vector_init(&index->reuc, 32, reuc_cmp) < 0)
return -1;
@@ -331,6 +373,8 @@ void git_index_clear(git_index *index)
git_index_reuc_clear(index);
+ git_index_name_clear(index);
+
git_futils_filestamp_set(&index->stamp, NULL);
git_tree_cache_free(index->tree);
@@ -1042,6 +1086,72 @@ int git_index_has_conflicts(const git_index *index)
return 0;
}
+unsigned int git_index_name_entrycount(git_index *index)
+{
+ assert(index);
+ return (unsigned int)index->names.length;
+}
+
+const git_index_name_entry *git_index_name_get_byindex(
+ git_index *index, size_t n)
+{
+ assert(index);
+
+ git_vector_sort(&index->names);
+ return git_vector_get(&index->names, n);
+}
+
+int git_index_name_add(git_index *index,
+ const char *ancestor, const char *ours, const char *theirs)
+{
+ git_index_name_entry *conflict_name;
+
+ assert ((ancestor && ours) || (ancestor && theirs) || (ours && theirs));
+
+ conflict_name = git__calloc(1, sizeof(git_index_name_entry));
+ GITERR_CHECK_ALLOC(conflict_name);
+
+ if (ancestor) {
+ conflict_name->ancestor = git__strdup(ancestor);
+ GITERR_CHECK_ALLOC(conflict_name->ancestor);
+ }
+
+ if (ours) {
+ conflict_name->ours = git__strdup(ours);
+ GITERR_CHECK_ALLOC(conflict_name->ours);
+ }
+
+ if (theirs) {
+ conflict_name->theirs = git__strdup(theirs);
+ GITERR_CHECK_ALLOC(conflict_name->theirs);
+ }
+
+ return git_vector_insert(&index->names, conflict_name);
+}
+
+void git_index_name_clear(git_index *index)
+{
+ size_t i;
+ git_index_name_entry *conflict_name;
+
+ assert(index);
+
+ git_vector_foreach(&index->names, i, conflict_name) {
+ if (conflict_name->ancestor)
+ git__free(conflict_name->ancestor);
+
+ if (conflict_name->ours)
+ git__free(conflict_name->ours);
+
+ if (conflict_name->theirs)
+ git__free(conflict_name->theirs);
+
+ git__free(conflict_name);
+ }
+
+ git_vector_clear(&index->names);
+}
+
unsigned int git_index_reuc_entrycount(git_index *index)
{
assert(index);
@@ -1228,6 +1338,52 @@ static int read_reuc(git_index *index, const char *buffer, size_t size)
return 0;
}
+
+static int read_conflict_names(git_index *index, const char *buffer, size_t size)
+{
+ size_t len;
+
+ /* This gets called multiple times, the vector might already be initialized */
+ if (index->names._alloc_size == 0 &&
+ git_vector_init(&index->names, 16, conflict_name_cmp) < 0)
+ return -1;
+
+#define read_conflict_name(ptr) \
+ len = strlen(buffer) + 1; \
+ if (size < len) \
+ return index_error_invalid("reading conflict name entries"); \
+ \
+ if (len == 1) \
+ ptr = NULL; \
+ else { \
+ ptr = git__malloc(len); \
+ GITERR_CHECK_ALLOC(ptr); \
+ memcpy(ptr, buffer, len); \
+ } \
+ \
+ buffer += len; \
+ size -= len;
+
+ while (size) {
+ git_index_name_entry *conflict_name = git__calloc(1, sizeof(git_index_name_entry));
+ GITERR_CHECK_ALLOC(conflict_name);
+
+ read_conflict_name(conflict_name->ancestor);
+ read_conflict_name(conflict_name->ours);
+ read_conflict_name(conflict_name->theirs);
+
+ if (git_vector_insert(&index->names, conflict_name) < 0)
+ return -1;
+ }
+
+#undef read_conflict_name
+
+ /* entries are guaranteed to be sorted on-disk */
+ index->names.sorted = 1;
+
+ return 0;
+}
+
static size_t read_entry(git_index_entry *dest, const void *buffer, size_t buffer_size)
{
size_t path_length, entry_size;
@@ -1332,6 +1488,9 @@ static size_t read_extension(git_index *index, const char *buffer, size_t buffer
} else if (memcmp(dest.signature, INDEX_EXT_UNMERGED_SIG, 4) == 0) {
if (read_reuc(index, buffer + 8, dest.extension_size) < 0)
return 0;
+ } else if (memcmp(dest.signature, INDEX_EXT_CONFLICT_NAME_SIG, 4) == 0) {
+ if (read_conflict_names(index, buffer + 8, dest.extension_size) < 0)
+ return 0;
}
/* else, unsupported extension. We cannot parse this, but we can skip
* it by returning `total_size */
@@ -1545,6 +1704,61 @@ static int write_extension(git_filebuf *file, struct index_extension *header, gi
return error;
}
+static int create_name_extension_data(git_buf *name_buf, git_index_name_entry *conflict_name)
+{
+ int error = 0;
+
+ if (conflict_name->ancestor == NULL)
+ error = git_buf_put(name_buf, "\0", 1);
+ else
+ error = git_buf_put(name_buf, conflict_name->ancestor, strlen(conflict_name->ancestor) + 1);
+
+ if (error != 0)
+ goto on_error;
+
+ if (conflict_name->ours == NULL)
+ error = git_buf_put(name_buf, "\0", 1);
+ else
+ error = git_buf_put(name_buf, conflict_name->ours, strlen(conflict_name->ours) + 1);
+
+ if (error != 0)
+ goto on_error;
+
+ if (conflict_name->theirs == NULL)
+ error = git_buf_put(name_buf, "\0", 1);
+ else
+ error = git_buf_put(name_buf, conflict_name->theirs, strlen(conflict_name->theirs) + 1);
+
+on_error:
+ return error;
+}
+
+static int write_name_extension(git_index *index, git_filebuf *file)
+{
+ git_buf name_buf = GIT_BUF_INIT;
+ git_vector *out = &index->names;
+ git_index_name_entry *conflict_name;
+ struct index_extension extension;
+ size_t i;
+ int error = 0;
+
+ git_vector_foreach(out, i, conflict_name) {
+ if ((error = create_name_extension_data(&name_buf, conflict_name)) < 0)
+ goto done;
+ }
+
+ memset(&extension, 0x0, sizeof(struct index_extension));
+ memcpy(&extension.signature, INDEX_EXT_CONFLICT_NAME_SIG, 4);
+ extension.extension_size = (uint32_t)name_buf.size;
+
+ error = write_extension(file, &extension, &name_buf);
+
+ git_buf_free(&name_buf);
+
+done:
+ return error;
+}
+
static int create_reuc_extension_data(git_buf *reuc_buf, git_index_reuc_entry *reuc)
{
int i;
@@ -1615,6 +1829,10 @@ static int write_index(git_index *index, git_filebuf *file)
/* TODO: write tree cache extension */
+ /* write the rename conflict extension */
+ if (index->names.length > 0 && write_name_extension(index, file) < 0)
+ return -1;
+
/* write the reuc extension */
if (index->reuc.length > 0 && write_reuc_extension(index, file) < 0)
return -1;