Commit 4c0b6a6d by Jakob Pfender

index: Add API for unmerged entries

New external functions:
	- git_index_unmerged_entrycount: Counts the unmerged entries in
	  the index
	- git_index_get_unmerged: Gets an unmerged entry from the index
	  by name

New internal functions:
	- read_unmerged: Wrapper for read_unmerged_internal
	- read_unmerged_internal: Reads unmerged entries from the index
	  if the index has the INDEX_EXT_UNMERGED_SIG set
	- unmerged_srch: Search function for unmerged vector
	- unmerged_cmp: Compare function for unmerged vector

New data structures:
	- git_index now contains a git_vector unmerged that stores
	  unmerged entries
	- git_index_entry_unmerged: Representation of an unmerged file
	  entry. It represents all three versions of the file at the
	  same time, with one name, three modes and three OIDs
parent fee4c425
...@@ -111,6 +111,12 @@ typedef struct git_index_entry { ...@@ -111,6 +111,12 @@ typedef struct git_index_entry {
char *path; char *path;
} git_index_entry; } git_index_entry;
/** Representation of an unmerged file entry in the index. */
typedef struct git_index_entry_unmerged {
unsigned int mode[3];
git_oid oid[3];
char *path;
} git_index_entry_unmerged;
/** /**
* Create a new Git index object as a memory representation * Create a new Git index object as a memory representation
...@@ -233,6 +239,24 @@ GIT_EXTERN(git_index_entry *) git_index_get(git_index *index, int n); ...@@ -233,6 +239,24 @@ GIT_EXTERN(git_index_entry *) git_index_get(git_index *index, int n);
*/ */
GIT_EXTERN(unsigned int) git_index_entrycount(git_index *index); GIT_EXTERN(unsigned int) git_index_entrycount(git_index *index);
/**
* Get the count of unmerged entries currently in the index
*
* @param index an existing index object
* @return integer of count of current unmerged entries
*/
GIT_EXTERN(unsigned int) git_index_unmerged_entrycount(git_index *index);
/**
* Get an unmerged entry from the index.
*
* @param entry the pointer to the new unmerged entry
* @param index an existing index object
* @param path path to search
* @return 0 on success, otherwise an error code
*/
GIT_EXTERN(int) git_index_get_unmerged(git_index_entry_unmerged **entry, git_index *index, const char *path);
/** @} */ /** @} */
GIT_END_DECL GIT_END_DECL
......
...@@ -46,6 +46,7 @@ static const unsigned int INDEX_VERSION_NUMBER_EXT = 3; ...@@ -46,6 +46,7 @@ static const unsigned int INDEX_VERSION_NUMBER_EXT = 3;
static const unsigned int INDEX_HEADER_SIG = 0x44495243; static const unsigned int INDEX_HEADER_SIG = 0x44495243;
static const char INDEX_EXT_TREECACHE_SIG[] = {'T', 'R', 'E', 'E'}; static const char INDEX_EXT_TREECACHE_SIG[] = {'T', 'R', 'E', 'E'};
static const char INDEX_EXT_UNMERGED_SIG[] = {'R', 'E', 'U', 'C'};
struct index_header { struct index_header {
uint32_t signature; uint32_t signature;
...@@ -98,7 +99,9 @@ static size_t read_entry(git_index_entry *dest, const void *buffer, size_t buffe ...@@ -98,7 +99,9 @@ static size_t read_entry(git_index_entry *dest, const void *buffer, size_t buffe
static int read_header(struct index_header *dest, const void *buffer); static int read_header(struct index_header *dest, const void *buffer);
static int read_tree(git_index *index, const char *buffer, size_t buffer_size); static int read_tree(git_index *index, const char *buffer, size_t buffer_size);
static int read_unmerged_internal(git_index *, const char **, size_t buffer_size);
static git_index_tree *read_tree_internal(const char **, const char *, git_index_tree *); static git_index_tree *read_tree_internal(const char **, const char *, git_index_tree *);
static int read_unmerged_internal(git_index *, const char **, size_t buffer_size);
static int parse_index(git_index *index, const char *buffer, size_t buffer_size); static int parse_index(git_index *index, const char *buffer, size_t buffer_size);
static void sort_index(git_index *index); static void sort_index(git_index *index);
...@@ -120,6 +123,21 @@ int index_cmp(const void *a, const void *b) ...@@ -120,6 +123,21 @@ int index_cmp(const void *a, const void *b)
return strcmp(entry_a->path, entry_b->path); return strcmp(entry_a->path, entry_b->path);
} }
int unmerged_srch(const void *key, const void *array_member)
{
const char *path = (const char *) key;
const git_index_entry_unmerged *entry = *(const git_index_entry_unmerged **) (array_member);
return strcmp(path, entry->path);
}
int unmerged_cmp(const void *a, const void *b)
{
const git_index_entry_unmerged *info_a = *(const git_index_entry_unmerged **)(a);
const git_index_entry_unmerged *info_b = *(const git_index_entry_unmerged **)(b);
return strcmp(info_a->path, info_b->path);
}
static int index_initialize(git_index **index_out, git_repository *owner, const char *index_path) static int index_initialize(git_index **index_out, git_repository *owner, const char *index_path)
{ {
...@@ -142,6 +160,7 @@ static int index_initialize(git_index **index_out, git_repository *owner, const ...@@ -142,6 +160,7 @@ static int index_initialize(git_index **index_out, git_repository *owner, const
index->repository = owner; index->repository = owner;
git_vector_init(&index->entries, 32, index_cmp); git_vector_init(&index->entries, 32, index_cmp);
git_vector_init(&index->unmerged, 32, unmerged_cmp);
/* Check if index file is stored on disk already */ /* Check if index file is stored on disk already */
if (gitfo_exists(index->index_file_path) == 0) if (gitfo_exists(index->index_file_path) == 0)
...@@ -282,6 +301,16 @@ unsigned int git_index_entrycount(git_index *index) ...@@ -282,6 +301,16 @@ unsigned int git_index_entrycount(git_index *index)
return index->entries.length; return index->entries.length;
} }
unsigned int git_index_unmerged_entrycount(git_index *index)
{
assert(index);
if (!&index->unmerged)
return 0;
return index->unmerged.length;
}
git_index_entry *git_index_get(git_index *index, int n) git_index_entry *git_index_get(git_index *index, int n)
{ {
assert(index); assert(index);
...@@ -406,6 +435,22 @@ int git_index_find(git_index *index, const char *path) ...@@ -406,6 +435,22 @@ int git_index_find(git_index *index, const char *path)
return git_vector_bsearch2(&index->entries, index_srch, path); return git_vector_bsearch2(&index->entries, index_srch, path);
} }
int git_index_get_unmerged(git_index_entry_unmerged **entry, git_index *index, const char *path)
{
int pos;
assert(index);
if ((pos = git_vector_bsearch2(&index->unmerged, unmerged_srch, path)) < GIT_SUCCESS)
return pos;
if ((*entry = git_vector_get(&index->unmerged, pos)) == NULL) {
return GIT_ENOTFOUND;
}
return GIT_SUCCESS;
}
static git_index_tree *read_tree_internal( static git_index_tree *read_tree_internal(
const char **buffer_in, const char *buffer_end, git_index_tree *parent) const char **buffer_in, const char *buffer_end, git_index_tree *parent)
{ {
...@@ -488,6 +533,68 @@ static int read_tree(git_index *index, const char *buffer, size_t buffer_size) ...@@ -488,6 +533,68 @@ static int read_tree(git_index *index, const char *buffer, size_t buffer_size)
return (index->tree != NULL && buffer == buffer_end) ? GIT_SUCCESS : GIT_EOBJCORRUPTED; return (index->tree != NULL && buffer == buffer_end) ? GIT_SUCCESS : GIT_EOBJCORRUPTED;
} }
static int read_unmerged_internal(
git_index *index, const char **buffer_in, size_t buffer_size)
{
const char *buffer, *endptr;
size_t size, len;
int i;
size = buffer_size;
while (size) {
git_index_entry_unmerged *lost;
buffer = *buffer_in;
len = strlen(buffer) + 1;
if (size <= len)
return GIT_ERROR;
if ((lost = git__malloc(sizeof(git_index_entry_unmerged))) == NULL)
return GIT_ERROR;
if ((lost->path = git__malloc(strlen(buffer))) == NULL)
return GIT_ERROR;
strcpy(lost->path, buffer);
if (git_vector_insert(&index->unmerged, lost) < GIT_SUCCESS)
return GIT_ERROR;
size -= len;
buffer += len;
for (i = 0; i < 3; i++) {
if (git__strtol32((long int *) &lost->mode[i], buffer, &endptr, 8) < GIT_SUCCESS || !endptr || endptr == buffer || *endptr)
return GIT_ERROR;
len = (endptr + 1) - (char *) buffer;
if (size <= len)
return GIT_ERROR;
size -= len;
buffer += len;
}
for (i = 0; i < 3; i++) {
if (!lost->mode[i])
continue;
if (size < 20)
return GIT_ERROR;
git_oid_mkraw(&lost->oid[i], (unsigned char *) buffer);
size -= 20;
buffer += 20;
}
}
*buffer_in = buffer;
return GIT_SUCCESS;
}
static int read_unmerged(git_index *index, const char *buffer, size_t buffer_size)
{
read_unmerged_internal(index, &buffer, buffer_size);
return (&index->unmerged != NULL) ? GIT_SUCCESS : GIT_EOBJCORRUPTED;
}
static size_t read_entry(git_index_entry *dest, const void *buffer, size_t buffer_size) static size_t read_entry(git_index_entry *dest, const void *buffer, size_t buffer_size)
{ {
size_t path_length, entry_size; size_t path_length, entry_size;
...@@ -593,6 +700,13 @@ static size_t read_extension(git_index *index, const char *buffer, size_t buffer ...@@ -593,6 +700,13 @@ static size_t read_extension(git_index *index, const char *buffer, size_t buffer
if (read_tree(index, buffer + 8, dest.extension_size) < GIT_SUCCESS) if (read_tree(index, buffer + 8, dest.extension_size) < GIT_SUCCESS)
return 0; return 0;
} else if (memcmp(dest.signature, INDEX_EXT_UNMERGED_SIG, 4) == 0) {
if (read_unmerged(index, buffer + 8, dest.extension_size) < GIT_SUCCESS)
return 0;
} else {
;
} }
} else { } else {
/* we cannot handle non-ignorable extensions; /* we cannot handle non-ignorable extensions;
......
...@@ -29,6 +29,8 @@ struct git_index { ...@@ -29,6 +29,8 @@ struct git_index {
unsigned int on_disk:1; unsigned int on_disk:1;
git_index_tree *tree; git_index_tree *tree;
git_vector unmerged;
}; };
#endif #endif
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