diff --git a/examples/general.c b/examples/general.c index e001a6889..d9467f5b5 100644 --- a/examples/general.c +++ b/examples/general.c @@ -371,7 +371,7 @@ int main (int argc, char** argv) // All these properties are exported publicly in the `git_index_entry` struct ecount = git_index_entrycount(index); for (i = 0; i < ecount; ++i) { - git_index_entry *e = git_index_get(index, i); + git_index_entry *e = git_index_get_byindex(index, i); printf("path: %s\n", e->path); printf("mtime: %d\n", (int)e->mtime.seconds); diff --git a/examples/showindex.c b/examples/showindex.c index 7f2130b90..d26fbaebd 100644 --- a/examples/showindex.c +++ b/examples/showindex.c @@ -19,12 +19,13 @@ int main (int argc, char** argv) ecount = git_index_entrycount(index); for (i = 0; i < ecount; ++i) { - git_index_entry *e = git_index_get(index, i); + git_index_entry *e = git_index_get_byindex(index, i); oid = e->oid; git_oid_fmt(out, &oid); printf("File Path: %s\n", e->path); + printf(" Stage: %d\n", git_index_entry_stage(e)); printf(" Blob SHA: %s\n", out); printf("File Size: %d\n", (int)e->file_size); printf(" Device: %d\n", (int)e->dev); diff --git a/include/git2/index.h b/include/git2/index.h index e8af3620d..1d91663d8 100644 --- a/include/git2/index.h +++ b/include/git2/index.h @@ -84,12 +84,12 @@ typedef struct git_index_entry { char *path; } git_index_entry; -/** Representation of an unmerged file entry in the index. */ -typedef struct git_index_entry_unmerged { +/** Representation of a resolve undo entry in the index. */ +typedef struct git_index_reuc_entry { unsigned int mode[3]; git_oid oid[3]; char *path; -} git_index_entry_unmerged; +} git_index_reuc_entry; /** Capabilities of system that affect index actions. */ enum { @@ -99,6 +99,12 @@ enum { GIT_INDEXCAP_FROM_OWNER = ~0u }; +/** @name Index File Functions + * + * These functions work on the index file itself. + */ +/**@{*/ + /** * Create a new bare Git index object as a memory representation * of the Git index file in 'index_path', without a repository @@ -119,15 +125,6 @@ enum { */ GIT_EXTERN(int) git_index_open(git_index **index, const char *index_path); -/** - * Clear the contents (all the entries) of an index object. - * This clears the index object in memory; changes must be manually - * written to disk for them to take effect. - * - * @param index an existing index object - */ -GIT_EXTERN(void) git_index_clear(git_index *index); - /** * Free an existing index object. * @@ -135,6 +132,14 @@ GIT_EXTERN(void) git_index_clear(git_index *index); */ GIT_EXTERN(void) git_index_free(git_index *index); +/** + * Get the repository this index relates to + * + * @param index The index + * @return A pointer to the repository + */ +GIT_EXTERN(git_repository *) git_index_owner(const git_index *index); + /** * Read index capabilities flags. * @@ -175,112 +180,26 @@ GIT_EXTERN(int) git_index_read(git_index *index); GIT_EXTERN(int) git_index_write(git_index *index); /** - * Find the first index of any entries which point to given - * path in the Git index. + * Read a tree into the index file with stats + * + * The current index contents will be replaced by the specified tree. * * @param index an existing index object - * @param path path to search - * @return an index >= 0 if found, -1 otherwise - */ -GIT_EXTERN(int) git_index_find(git_index *index, const char *path); - -/** - * Remove all entries with equal path except last added - * - * @param index an existing index object - */ -GIT_EXTERN(void) git_index_uniq(git_index *index); - -/** - * 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. - * - * This forces the file to be added to the index, not looking - * at gitignore rules. Those rules can be evaluated through - * the git_status APIs (in status.h) before calling this. - * - * @param index an existing index object - * @param path filename to add - * @param stage stage for the entry + * @param tree tree to read * @return 0 or an error code */ -GIT_EXTERN(int) git_index_add(git_index *index, const char *path, int stage); +GIT_EXTERN(int) git_index_read_tree(git_index *index, git_tree *tree); -/** - * Add or update an index entry from an in-memory struct +/**@}*/ + +/** @name Raw Index Entry Functions * - * 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 source_entry new entry object - * @return 0 or an error code + * These functions work on index entries, and allow for raw manipulation + * of the entries. */ -GIT_EXTERN(int) git_index_add2(git_index *index, const git_index_entry *source_entry); +/**@{*/ -/** - * 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 or 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. - * - * @param index an existing index object - * @param source_entry new entry object - * @return 0 or an error code - */ -GIT_EXTERN(int) git_index_append2(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 or 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 - * - * This entry can be modified, and the changes will be written - * back to disk on the next write() call. - * - * The entry should not be freed by the caller. - * - * @param index an existing index object - * @param n the position of the entry - * @return a pointer to the entry; NULL if out of bounds - */ -GIT_EXTERN(git_index_entry *) git_index_get(git_index *index, size_t n); +/* Index entry manipulation */ /** * Get the count of entries currently in the index @@ -291,36 +210,70 @@ GIT_EXTERN(git_index_entry *) git_index_get(git_index *index, size_t n); GIT_EXTERN(unsigned int) git_index_entrycount(git_index *index); /** - * Get the count of unmerged entries currently in the index + * Clear the contents (all the entries) of an index object. + * This clears the index object in memory; changes must be manually + * written to disk for them to take effect. * * @param index an existing index object - * @return integer of count of current unmerged entries */ -GIT_EXTERN(unsigned int) git_index_entrycount_unmerged(git_index *index); +GIT_EXTERN(void) git_index_clear(git_index *index); /** - * Get an unmerged entry from the index. + * Get a pointer to one of the entries in the index * - * The returned entry is read-only and should not be modified - * of freed by the caller. + * The values of this entry can be modified (except the path) + * and the changes will be written back to disk on the next + * write() call. * - * @param index an existing index object - * @param path path to search - * @return the unmerged entry; NULL if not found - */ -GIT_EXTERN(const git_index_entry_unmerged *) git_index_get_unmerged_bypath(git_index *index, const char *path); - -/** - * Get an unmerged entry from the index. - * - * The returned entry is read-only and should not be modified - * of freed by the caller. + * The entry should not be freed by the caller. * * @param index an existing index object * @param n the position of the entry - * @return a pointer to the unmerged entry; NULL if out of bounds + * @return a pointer to the entry; NULL if out of bounds */ -GIT_EXTERN(const git_index_entry_unmerged *) git_index_get_unmerged_byindex(git_index *index, size_t n); +GIT_EXTERN(git_index_entry *) git_index_get_byindex(git_index *index, size_t n); + +/** + * Get a pointer to one of the entries in the index + * + * The values of this entry can be modified (except the path) + * and the changes will be written back to disk on the next + * write() call. + * + * The entry should not be freed by the caller. + * + * @param index an existing index object + * @param path path to search + * @param stage stage to search + * @return a pointer to the entry; NULL if it was not found + */ +GIT_EXTERN(git_index_entry *) git_index_get_bypath(git_index *index, const char *path, int stage); + +/** + * Remove an entry from the index + * + * @param index an existing index object + * @param path path to search + * @param stage stage to search + * @return 0 or an error code + */ +GIT_EXTERN(int) git_index_remove(git_index *index, const char *path, int stage); + +/** + * Add or update an index entry from an in-memory struct + * + * If a previous index entry exists that has the same path and stage + * as the given 'source_entry', it will be replaced. Otherwise, the + * 'source_entry' will be added. + * + * 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 source_entry new entry object + * @return 0 or an error code + */ +GIT_EXTERN(int) git_index_add(git_index *index, const git_index_entry *source_entry); /** * Return the stage number from a git index entry @@ -335,25 +288,192 @@ GIT_EXTERN(const git_index_entry_unmerged *) git_index_get_unmerged_byindex(git_ */ GIT_EXTERN(int) git_index_entry_stage(const git_index_entry *entry); -/** - * Read a tree into the index file with stats +/**@}*/ + +/** @name Workdir Index Entry Functions * - * The current index contents will be replaced by the specified tree. The total - * node count is collected in stats. - * - * @param index an existing index object - * @param tree tree to read - * @return 0 or an error code + * These functions work on index entries specifically in the working + * directory (ie, stage 0). */ -GIT_EXTERN(int) git_index_read_tree(git_index *index, git_tree *tree); +/**@{*/ /** - * Get the repository this index relates to + * Add or update an index entry from a file in disk * - * @param index The index - * @return A pointer to the repository + * The file `path` must be relative to the repository's + * working folder and must be readable. + * + * This method will fail in bare index instances. + * + * This forces the file to be added to the index, not looking + * at gitignore rules. Those rules can be evaluated through + * the git_status APIs (in status.h) before calling this. + * + * If this file currently is the result of a merge conflict, this + * file will no longer be marked as conflicting. The data about + * the conflict will be moved to the "resolve undo" (REUC) section. + * + * @param index an existing index object + * @param path filename to add + * @return 0 or an error code */ -GIT_EXTERN(git_repository *) git_index_owner(const git_index *index); +GIT_EXTERN(int) git_index_add_from_workdir(git_index *index, const char *path); + +/** + * Find the first index of any entries which point to given + * path in the Git index. + * + * @param index an existing index object + * @param path path to search + * @return an index >= 0 if found, -1 otherwise + */ +GIT_EXTERN(int) git_index_find(git_index *index, const char *path); + +/**@}*/ + +/** @name Conflict Index Entry Functions + * + * These functions work on conflict index entries specifically (ie, stages 1-3) + */ +/**@{*/ + +/** + * Add or update index entries to represent a conflict + * + * The entries are the entries from the tree included in the merge. Any + * entry may be null to indicate that that file was not present in the + * trees during the merge. For example, ancestor_entry may be NULL to + * indicate that a file was added in both branches and must be resolved. + * + * @param index an existing index object + * @param ancestor_entry the entry data for the ancestor of the conflict + * @param our_entry the entry data for our side of the merge conflict + * @param their_entry the entry data for their side of the merge conflict + * @return 0 or an error code + */ +GIT_EXTERN(int) git_index_conflict_add(git_index *index, + const git_index_entry *ancestor_entry, + const git_index_entry *our_entry, + const git_index_entry *their_entry); + +/** + * Get the index entries that represent a conflict of a single file. + * + * The values of this entry can be modified (except the paths) + * and the changes will be written back to disk on the next + * write() call. + * + * @param ancestor_out Pointer to store the ancestor entry + * @param our_out Pointer to store the our entry + * @param their_out Pointer to store the their entry + * @param index an existing index object + * @param path path to search + */ +GIT_EXTERN(int) git_index_conflict_get(git_index_entry **ancestor_out, git_index_entry **our_out, git_index_entry **their_out, git_index *index, const char *path); + +/** + * Removes the index entries that represent a conflict of a single file. + * + * @param index an existing index object + * @param path to search + */ +GIT_EXTERN(int) git_index_conflict_remove(git_index *index, const char *path); + +/** + * Remove all conflicts in the index (entries with a stage greater than 0.) + * + * @param index an existing index object + */ +GIT_EXTERN(void) git_index_conflict_cleanup(git_index *index); + +/**@}*/ + +/** @name Resolve Undo (REUC) index entry manipulation. + * + * These functions work on the Resolve Undo index extension and contains + * data about the original files that led to a merge conflict. + */ +/**@{*/ + +/** + * Get the count of resolve undo entries currently in the index. + * + * @param index an existing index object + * @return integer of count of current resolve undo entries + */ +GIT_EXTERN(unsigned int) git_index_reuc_entrycount(git_index *index); + +/** + * Finds the resolve undo entry that points to the given path in the Git + * index. + * + * @param index an existing index object + * @param path path to search + * @return an index >= 0 if found, -1 otherwise + */ +GIT_EXTERN(int) git_index_reuc_find(git_index *index, const char *path); + +/** + * Get a resolve undo entry from the index. + * + * The returned entry is read-only and should not be modified + * of freed by the caller. + * + * @param index an existing index object + * @param path path to search + * @return the resolve undo entry; NULL if not found + */ +GIT_EXTERN(const git_index_reuc_entry *) git_index_reuc_get_bypath(git_index *index, const char *path); + +/** + * Get a resolve undo entry from the index. + * + * The returned entry is read-only and should not be modified + * of freed by the caller. + * + * @param index an existing index object + * @param n the position of the entry + * @return a pointer to the resolve undo entry; NULL if out of bounds + */ +GIT_EXTERN(const git_index_reuc_entry *) git_index_reuc_get_byindex(git_index *index, size_t n); + +/** + * Adds an resolve undo entry for a file based on the given parameters. + * + * The resolve undo entry contains the OIDs of files that were involved + * in a merge conflict after the conflict has been resolved. This allows + * conflicts to be re-resolved later. + * + * If there exists a resolve undo entry for the given path in the index, + * it will be removed. + * + * This method will fail in bare index instances. + * + * @param index an existing index object + * @param path filename to add + * @param ancestor_mode mode of the ancestor file + * @param ancestor_oid oid of the ancestor file + * @param our_mode mode of our file + * @param our_oid oid of our file + * @param their_mode mode of their file + * @param their_oid oid of their file + * @return 0 or an error code + */ +GIT_EXTERN(int) git_index_reuc_add(git_index *index, const char *path, + int ancestor_mode, git_oid *ancestor_oid, + int our_mode, git_oid *our_oid, + int their_mode, git_oid *their_oid); + +/** + * Remove an resolve undo entry from the index + * + * @param index an existing index object + * @param position position of the resolve undo entry to remove + * @return 0 or an error code + */ +GIT_EXTERN(int) git_index_reuc_remove(git_index *index, int position); + +/**@}*/ /** @} */ GIT_END_DECL diff --git a/src/attr.c b/src/attr.c index 025ad3c87..f5e09cc08 100644 --- a/src/attr.c +++ b/src/attr.c @@ -307,7 +307,7 @@ static int load_attr_blob_from_index( (error = git_index_find(index, relfile)) < 0) return error; - entry = git_index_get(index, error); + entry = git_index_get_byindex(index, error); if (old_oid && git_oid_cmp(old_oid, &entry->oid) == 0) return GIT_ENOTFOUND; diff --git a/src/index.c b/src/index.c index 38e83d007..44dd93417 100644 --- a/src/index.c +++ b/src/index.c @@ -81,6 +81,11 @@ struct entry_long { char path[1]; /* arbitrary length */ }; +struct entry_srch_key { + const char *path; + int stage; +}; + /* local declarations */ static size_t read_extension(git_index *index, const char *buffer, size_t buffer_size); static size_t read_entry(git_index_entry *dest, const void *buffer, size_t buffer_size); @@ -90,53 +95,126 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size) static int is_index_extended(git_index *index); static int write_index(git_index *index, git_filebuf *file); +static int index_find(git_index *index, const char *path, int stage); + static void index_entry_free(git_index_entry *entry); +static void index_entry_reuc_free(git_index_reuc_entry *reuc); + +GIT_INLINE(int) index_entry_stage(const git_index_entry *entry) +{ + return (entry->flags & GIT_IDXENTRY_STAGEMASK) >> GIT_IDXENTRY_STAGESHIFT; +} static int index_srch(const void *key, const void *array_member) { + const struct entry_srch_key *srch_key = key; const git_index_entry *entry = array_member; + int ret; - return strcmp(key, entry->path); + ret = strcmp(srch_key->path, entry->path); + + if (ret == 0) + ret = srch_key->stage - index_entry_stage(entry); + + return ret; } static int index_isrch(const void *key, const void *array_member) +{ + const struct entry_srch_key *srch_key = key; + const git_index_entry *entry = array_member; + int ret; + + ret = strcasecmp(srch_key->path, entry->path); + + if (ret == 0) + ret = srch_key->stage - index_entry_stage(entry); + + return ret; +} + +static int index_cmp_path(const void *a, const void *b) +{ + return strcmp((const char *)a, (const char *)b); +} + +static int index_icmp_path(const void *a, const void *b) +{ + return strcasecmp((const char *)a, (const char *)b); +} + +static int index_srch_path(const void *path, const void *array_member) { const git_index_entry *entry = array_member; - return strcasecmp(key, entry->path); + return strcmp((const char *)path, entry->path); +} + +static int index_isrch_path(const void *path, const void *array_member) +{ + const git_index_entry *entry = array_member; + + return strcasecmp((const char *)path, entry->path); } static int index_cmp(const void *a, const void *b) { + int diff; const git_index_entry *entry_a = a; const git_index_entry *entry_b = b; - return strcmp(entry_a->path, entry_b->path); + diff = strcmp(entry_a->path, entry_b->path); + + if (diff == 0) + diff = (index_entry_stage(entry_a) - index_entry_stage(entry_b)); + + return diff; } static int index_icmp(const void *a, const void *b) { + int diff; const git_index_entry *entry_a = a; const git_index_entry *entry_b = b; - return strcasecmp(entry_a->path, entry_b->path); + diff = strcasecmp(entry_a->path, entry_b->path); + + if (diff == 0) + diff = (index_entry_stage(entry_a) - index_entry_stage(entry_b)); + + return diff; } -static int unmerged_srch(const void *key, const void *array_member) +static int reuc_srch(const void *key, const void *array_member) { - const git_index_entry_unmerged *entry = array_member; + const git_index_reuc_entry *reuc = array_member; - return strcmp(key, entry->path); + return strcmp(key, reuc->path); } -static int unmerged_cmp(const void *a, const void *b) +static int reuc_isrch(const void *key, const void *array_member) { - const git_index_entry_unmerged *info_a = a; - const git_index_entry_unmerged *info_b = b; + const git_index_reuc_entry *reuc = array_member; + + return strcasecmp(key, reuc->path); +} + +static int reuc_cmp(const void *a, const void *b) +{ + const git_index_reuc_entry *info_a = a; + const git_index_reuc_entry *info_b = b; return strcmp(info_a->path, info_b->path); } +static int reuc_icmp(const void *a, const void *b) +{ + const git_index_reuc_entry *info_a = a; + const git_index_reuc_entry *info_b = b; + + return strcasecmp(info_a->path, info_b->path); +} + static unsigned int index_create_mode(unsigned int mode) { if (S_ISLNK(mode)) @@ -165,9 +243,16 @@ static unsigned int index_merge_mode( static void index_set_ignore_case(git_index *index, bool ignore_case) { index->entries._cmp = ignore_case ? index_icmp : index_cmp; + index->entries_cmp_path = ignore_case ? index_icmp_path : index_cmp_path; index->entries_search = ignore_case ? index_isrch : index_srch; + index->entries_search_path = ignore_case ? index_isrch_path : index_srch_path; index->entries.sorted = 0; git_vector_sort(&index->entries); + + index->reuc._cmp = ignore_case ? reuc_icmp : reuc_cmp; + index->reuc_search = ignore_case ? reuc_isrch : reuc_srch; + index->reuc.sorted = 0; + git_vector_sort(&index->reuc); } int git_index_open(git_index **index_out, const char *index_path) @@ -185,7 +270,10 @@ int git_index_open(git_index **index_out, const char *index_path) if (git_vector_init(&index->entries, 32, index_cmp) < 0) return -1; + index->entries_cmp_path = index_cmp_path; index->entries_search = index_srch; + index->entries_search_path = index_srch_path; + index->reuc_search = reuc_srch; /* Check if index file is stored on disk already */ if (git_path_exists(index->index_file_path) == true) @@ -199,6 +287,7 @@ int git_index_open(git_index **index_out, const char *index_path) static void index_free(git_index *index) { git_index_entry *e; + git_index_reuc_entry *reuc; unsigned int i; git_index_clear(index); @@ -206,10 +295,10 @@ static void index_free(git_index *index) index_entry_free(e); } git_vector_free(&index->entries); - git_vector_foreach(&index->unmerged, i, e) { - index_entry_free(e); + git_vector_foreach(&index->reuc, i, reuc) { + index_entry_reuc_free(reuc); } - git_vector_free(&index->unmerged); + git_vector_free(&index->reuc); git__free(index->index_file_path); git__free(index); @@ -236,15 +325,15 @@ void git_index_clear(git_index *index) git__free(e); } - for (i = 0; i < index->unmerged.length; ++i) { - git_index_entry_unmerged *e; - e = git_vector_get(&index->unmerged, i); + for (i = 0; i < index->reuc.length; ++i) { + git_index_reuc_entry *e; + e = git_vector_get(&index->reuc, i); git__free(e->path); git__free(e); } git_vector_clear(&index->entries); - git_vector_clear(&index->unmerged); + git_vector_clear(&index->reuc); index->last_modified = 0; git_tree_cache_free(index->tree); @@ -340,6 +429,7 @@ int git_index_write(git_index *index) int error; git_vector_sort(&index->entries); + git_vector_sort(&index->reuc); if ((error = git_filebuf_open( &file, index->index_file_path, GIT_FILEBUF_HASH_CONTENTS)) < 0) @@ -367,18 +457,27 @@ unsigned int git_index_entrycount(git_index *index) return (unsigned int)index->entries.length; } -unsigned int git_index_entrycount_unmerged(git_index *index) +git_index_entry *git_index_get_byindex(git_index *index, size_t n) { assert(index); - return (unsigned int)index->unmerged.length; -} - -git_index_entry *git_index_get(git_index *index, size_t n) -{ git_vector_sort(&index->entries); return git_vector_get(&index->entries, n); } +git_index_entry *git_index_get_bypath(git_index *index, const char *path, int stage) +{ + int pos; + + assert(index); + + git_vector_sort(&index->entries); + + if((pos = index_find(index, path, stage)) < 0) + return NULL; + + return git_index_get_byindex(index, pos); +} + void git_index__init_entry_from_stat(struct stat *st, git_index_entry *entry) { entry->ctime.seconds = (git_time_t)st->st_ctime; @@ -393,7 +492,7 @@ void git_index__init_entry_from_stat(struct stat *st, git_index_entry *entry) entry->file_size = st->st_size; } -static int index_entry_init(git_index_entry **entry_out, git_index *index, const char *rel_path, int stage) +static int index_entry_init(git_index_entry **entry_out, git_index *index, const char *rel_path) { git_index_entry *entry = NULL; struct stat st; @@ -402,8 +501,6 @@ static int index_entry_init(git_index_entry **entry_out, git_index *index, const git_buf full_path = GIT_BUF_INIT; int error; - assert(stage >= 0 && stage <= 3); - if (INDEX_OWNER(index) == NULL || (workdir = git_repository_workdir(INDEX_OWNER(index))) == NULL) { @@ -436,7 +533,6 @@ static int index_entry_init(git_index_entry **entry_out, git_index *index, const git_index__init_entry_from_stat(&st, entry); entry->oid = oid; - entry->flags |= (stage << GIT_IDXENTRY_STAGESHIFT); entry->path = git__strdup(rel_path); GITERR_CHECK_ALLOC(entry->path); @@ -444,6 +540,46 @@ static int index_entry_init(git_index_entry **entry_out, git_index *index, const return 0; } +static int index_entry_reuc_init(git_index_reuc_entry **reuc_out, + const char *path, + int ancestor_mode, git_oid *ancestor_oid, + int our_mode, git_oid *our_oid, int their_mode, git_oid *their_oid) +{ + git_index_reuc_entry *reuc = NULL; + + assert(reuc_out && path); + + *reuc_out = NULL; + + reuc = git__calloc(1, sizeof(git_index_reuc_entry)); + GITERR_CHECK_ALLOC(reuc); + + reuc->path = git__strdup(path); + if (reuc->path == NULL) + return -1; + + reuc->mode[0] = ancestor_mode; + git_oid_cpy(&reuc->oid[0], ancestor_oid); + + reuc->mode[1] = our_mode; + git_oid_cpy(&reuc->oid[1], our_oid); + + reuc->mode[2] = their_mode; + git_oid_cpy(&reuc->oid[2], their_oid); + + *reuc_out = reuc; + return 0; +} + +static void index_entry_reuc_free(git_index_reuc_entry *reuc) +{ + if (!reuc) + return; + + git__free(reuc->path); + git__free(reuc); +} + static git_index_entry *index_entry_dup(const git_index_entry *source_entry) { git_index_entry *entry; @@ -486,10 +622,10 @@ static int index_insert(git_index *index, git_index_entry *entry, int replace) if (path_length < GIT_IDXENTRY_NAMEMASK) entry->flags |= path_length & GIT_IDXENTRY_NAMEMASK; else - entry->flags |= GIT_IDXENTRY_NAMEMASK;; + entry->flags |= GIT_IDXENTRY_NAMEMASK; /* look if an entry with this path already exists */ - if ((position = git_index_find(index, entry->path)) >= 0) { + if ((position = index_find(index, entry->path, index_entry_stage(entry))) >= 0) { existing = (git_index_entry **)&index->entries.contents[position]; /* update filemode to existing values if stat is not trusted */ @@ -510,34 +646,56 @@ static int index_insert(git_index *index, git_index_entry *entry, int replace) return 0; } -static int index_add(git_index *index, const char *path, int stage, int replace) +static int index_conflict_to_reuc(git_index *index, const char *path) +{ + git_index_entry *conflict_entries[3]; + int ancestor_mode, our_mode, their_mode; + git_oid *ancestor_oid, *our_oid, *their_oid; + int ret; + + if ((ret = git_index_conflict_get(&conflict_entries[0], + &conflict_entries[1], &conflict_entries[2], index, path)) < 0) + return ret; + + ancestor_mode = conflict_entries[0] == NULL ? 0 : conflict_entries[0]->mode; + our_mode = conflict_entries[1] == NULL ? 0 : conflict_entries[1]->mode; + their_mode = conflict_entries[2] == NULL ? 0 : conflict_entries[2]->mode; + + ancestor_oid = conflict_entries[0] == NULL ? NULL : &conflict_entries[0]->oid; + our_oid = conflict_entries[1] == NULL ? NULL : &conflict_entries[1]->oid; + their_oid = conflict_entries[2] == NULL ? NULL : &conflict_entries[2]->oid; + + if ((ret = git_index_reuc_add(index, path, ancestor_mode, ancestor_oid, + our_mode, our_oid, their_mode, their_oid)) >= 0) + ret = git_index_conflict_remove(index, path); + + return ret; +} + +int git_index_add_from_workdir(git_index *index, const char *path) { git_index_entry *entry = NULL; int ret; - if ((ret = index_entry_init(&entry, index, path, stage)) < 0 || - (ret = index_insert(index, entry, replace)) < 0) - { - index_entry_free(entry); - return ret; - } + assert(index && path); + + if ((ret = index_entry_init(&entry, index, path)) < 0 || + (ret = index_insert(index, entry, 1)) < 0) + goto on_error; + + /* Adding implies conflict was resolved, move conflict entries to REUC */ + if ((ret = index_conflict_to_reuc(index, path)) < 0 && ret != GIT_ENOTFOUND) + goto on_error; git_tree_cache_invalidate_path(index->tree, entry->path); return 0; + +on_error: + index_entry_free(entry); + return ret; } -int git_index_add(git_index *index, const char *path, int stage) -{ - return index_add(index, path, stage, 1); -} - -int git_index_append(git_index *index, const char *path, int stage) -{ - return index_add(index, path, stage, 0); -} - -static int index_add2( - git_index *index, const git_index_entry *source_entry, int replace) +int git_index_add(git_index *index, const git_index_entry *source_entry) { git_index_entry *entry = NULL; int ret; @@ -546,7 +704,7 @@ static int index_add2( if (entry == NULL) return -1; - if ((ret = index_insert(index, entry, replace)) < 0) { + if ((ret = index_insert(index, entry, 1)) < 0) { index_entry_free(entry); return ret; } @@ -555,23 +713,17 @@ static int index_add2( return 0; } -int git_index_add2(git_index *index, const git_index_entry *source_entry) -{ - return index_add2(index, source_entry, 1); -} - -int git_index_append2(git_index *index, const git_index_entry *source_entry) -{ - return index_add2(index, source_entry, 0); -} - -int git_index_remove(git_index *index, int position) +int git_index_remove(git_index *index, const char *path, int stage) { + int position; int error; git_index_entry *entry; git_vector_sort(&index->entries); + if ((position = index_find(index, path, stage)) < 0) + return position; + entry = git_vector_get(&index->entries, position); if (entry != NULL) git_tree_cache_invalidate_path(index->tree, entry->path); @@ -584,45 +736,277 @@ int git_index_remove(git_index *index, int position) return error; } -int git_index_find(git_index *index, const char *path) +static int index_find(git_index *index, const char *path, int stage) { - return git_vector_bsearch2(&index->entries, index->entries_search, path); + struct entry_srch_key srch_key; + + assert(path); + + srch_key.path = path; + srch_key.stage = stage; + + return git_vector_bsearch2(&index->entries, index->entries_search, &srch_key); } -unsigned int git_index__prefix_position(git_index *index, const char *path) +int git_index_find(git_index *index, const char *path) { - unsigned int pos; + int pos; - git_vector_bsearch3(&pos, &index->entries, index->entries_search, path); + assert(index && path); + + if ((pos = git_vector_bsearch2(&index->entries, index->entries_search_path, path)) < 0) + return pos; + + /* Since our binary search only looked at path, we may be in the + * middle of a list of stages. */ + while (pos > 0) { + git_index_entry *prev = git_vector_get(&index->entries, pos-1); + + if (index->entries_cmp_path(prev->path, path) != 0) + break; + + --pos; + } return pos; } -void git_index_uniq(git_index *index) +unsigned int git_index__prefix_position(git_index *index, const char *path) { - git_vector_uniq(&index->entries); + struct entry_srch_key srch_key; + unsigned int pos; + + srch_key.path = path; + srch_key.stage = 0; + + git_vector_bsearch3(&pos, &index->entries, index->entries_search, &srch_key); + + return pos; } -const git_index_entry_unmerged *git_index_get_unmerged_bypath( +int git_index_conflict_add(git_index *index, + const git_index_entry *ancestor_entry, + const git_index_entry *our_entry, + const git_index_entry *their_entry) +{ + git_index_entry *entries[3] = { 0 }; + size_t i; + int ret = 0; + + assert (index); + + if ((ancestor_entry != NULL && (entries[0] = index_entry_dup(ancestor_entry)) == NULL) || + (our_entry != NULL && (entries[1] = index_entry_dup(our_entry)) == NULL) || + (their_entry != NULL && (entries[2] = index_entry_dup(their_entry)) == NULL)) + return -1; + + for (i = 0; i < 3; i++) { + if (entries[i] == NULL) + continue; + + /* Make sure stage is correct */ + entries[i]->flags = (entries[i]->flags & ~GIT_IDXENTRY_STAGEMASK) | + ((i+1) << GIT_IDXENTRY_STAGESHIFT); + + if ((ret = index_insert(index, entries[i], 1)) < 0) + goto on_error; + } + + return 0; + +on_error: + for (i = 0; i < 3; i++) { + if (entries[i] != NULL) + index_entry_free(entries[i]); + } + + return ret; +} + +int git_index_conflict_get(git_index_entry **ancestor_out, + git_index_entry **our_out, + git_index_entry **their_out, + git_index *index, const char *path) +{ + int pos, stage; + git_index_entry *conflict_entry; + int error = GIT_ENOTFOUND; + + assert(ancestor_out && our_out && their_out && index && path); + + *ancestor_out = NULL; + *our_out = NULL; + *their_out = NULL; + + if ((pos = git_index_find(index, path)) < 0) + return pos; + + while ((unsigned int)pos < git_index_entrycount(index)) { + conflict_entry = git_vector_get(&index->entries, pos); + + if (index->entries_cmp_path(conflict_entry->path, path) != 0) + break; + + stage = index_entry_stage(conflict_entry); + + switch (stage) { + case 3: + *their_out = conflict_entry; + error = 0; + break; + case 2: + *our_out = conflict_entry; + error = 0; + break; + case 1: + *ancestor_out = conflict_entry; + error = 0; + break; + default: + break; + }; + + ++pos; + } + + return error; +} + +int git_index_conflict_remove(git_index *index, const char *path) +{ + int pos; + git_index_entry *conflict_entry; + + assert(index && path); + + if ((pos = git_index_find(index, path)) < 0) + return pos; + + while ((unsigned int)pos < git_index_entrycount(index)) { + conflict_entry = git_vector_get(&index->entries, pos); + + if (index->entries_cmp_path(conflict_entry->path, path) != 0) + break; + + if (index_entry_stage(conflict_entry) == 0) { + pos++; + continue; + } + + git_vector_remove(&index->entries, (unsigned int)pos); + } + + return 0; +} + +static int index_conflicts_match(git_vector *v, size_t idx) +{ + git_index_entry *entry = git_vector_get(v, idx); + + if (index_entry_stage(entry) > 0) + return 1; + + return 0; +} + +void git_index_conflict_cleanup(git_index *index) +{ + assert(index); + git_vector_remove_matching(&index->entries, index_conflicts_match); +} + +unsigned int git_index_reuc_entrycount(git_index *index) +{ + assert(index); + return (unsigned int)index->reuc.length; +} + +static int index_reuc_insert(git_index *index, git_index_reuc_entry *reuc, int replace) +{ + git_index_reuc_entry **existing = NULL; + int position; + + assert(index && reuc && reuc->path != NULL); + + if ((position = git_index_reuc_find(index, reuc->path)) >= 0) + existing = (git_index_reuc_entry **)&index->reuc.contents[position]; + + if (!replace || !existing) + return git_vector_insert(&index->reuc, reuc); + + /* exists, replace it */ + git__free((*existing)->path); + git__free(*existing); + *existing = reuc; + + return 0; +} + +int git_index_reuc_add(git_index *index, const char *path, + int ancestor_mode, git_oid *ancestor_oid, + int our_mode, git_oid *our_oid, + int their_mode, git_oid *their_oid) +{ + git_index_reuc_entry *reuc = NULL; + int error = 0; + + assert(index && path); + + if ((error = index_entry_reuc_init(&reuc, path, ancestor_mode, ancestor_oid, our_mode, our_oid, their_mode, their_oid)) < 0 || + (error = index_reuc_insert(index, reuc, 1)) < 0) + { + index_entry_reuc_free(reuc); + return error; + } + + return error; +} + +int git_index_reuc_find(git_index *index, const char *path) +{ + return git_vector_bsearch2(&index->reuc, index->reuc_search, path); +} + +const git_index_reuc_entry *git_index_reuc_get_bypath( git_index *index, const char *path) { int pos; assert(index && path); - if (!index->unmerged.length) + if (!index->reuc.length) return NULL; - if ((pos = git_vector_bsearch2(&index->unmerged, unmerged_srch, path)) < 0) + git_vector_sort(&index->reuc); + + if ((pos = git_index_reuc_find(index, path)) < 0) return NULL; - return git_vector_get(&index->unmerged, pos); + return git_vector_get(&index->reuc, pos); } -const git_index_entry_unmerged *git_index_get_unmerged_byindex( +const git_index_reuc_entry *git_index_reuc_get_byindex( git_index *index, size_t n) { assert(index); - return git_vector_get(&index->unmerged, n); + + git_vector_sort(&index->reuc); + return git_vector_get(&index->reuc, n); +} + +int git_index_reuc_remove(git_index *index, int position) +{ + int error; + git_index_reuc_entry *reuc; + + git_vector_sort(&index->reuc); + + reuc = git_vector_get(&index->reuc, position); + error = git_vector_remove(&index->reuc, (unsigned int)position); + + if (!error) + index_entry_reuc_free(reuc); + + return error; } static int index_error_invalid(const char *message) @@ -631,26 +1015,26 @@ static int index_error_invalid(const char *message) return -1; } -static int read_unmerged(git_index *index, const char *buffer, size_t size) +static int read_reuc(git_index *index, const char *buffer, size_t size) { const char *endptr; size_t len; int i; - if (git_vector_init(&index->unmerged, 16, unmerged_cmp) < 0) + if (git_vector_init(&index->reuc, 16, reuc_cmp) < 0) return -1; while (size) { - git_index_entry_unmerged *lost; + git_index_reuc_entry *lost; len = strlen(buffer) + 1; if (size <= len) - return index_error_invalid("reading unmerged entries"); + return index_error_invalid("reading reuc entries"); - lost = git__malloc(sizeof(git_index_entry_unmerged)); + lost = git__malloc(sizeof(git_index_reuc_entry)); GITERR_CHECK_ALLOC(lost); - if (git_vector_insert(&index->unmerged, lost) < 0) + if (git_vector_insert(&index->reuc, lost) < 0) return -1; /* read NUL-terminated pathname for entry */ @@ -667,13 +1051,13 @@ static int read_unmerged(git_index *index, const char *buffer, size_t size) if (git__strtol32(&tmp, buffer, &endptr, 8) < 0 || !endptr || endptr == buffer || *endptr || (unsigned)tmp > UINT_MAX) - return index_error_invalid("reading unmerged entry stage"); + return index_error_invalid("reading reuc entry stage"); lost->mode[i] = tmp; len = (endptr + 1) - buffer; if (size <= len) - return index_error_invalid("reading unmerged entry stage"); + return index_error_invalid("reading reuc entry stage"); size -= len; buffer += len; @@ -684,7 +1068,7 @@ static int read_unmerged(git_index *index, const char *buffer, size_t size) if (!lost->mode[i]) continue; if (size < 20) - return index_error_invalid("reading unmerged entry oid"); + return index_error_invalid("reading reuc entry oid"); git_oid_fromraw(&lost->oid[i], (const unsigned char *) buffer); size -= 20; @@ -692,6 +1076,9 @@ static int read_unmerged(git_index *index, const char *buffer, size_t size) } } + /* entries are guaranteed to be sorted on-disk */ + index->reuc.sorted = 1; + return 0; } @@ -797,7 +1184,7 @@ static size_t read_extension(git_index *index, const char *buffer, size_t buffer if (git_tree_cache_read(&index->tree, buffer + 8, dest.extension_size) < 0) return 0; } else if (memcmp(dest.signature, INDEX_EXT_UNMERGED_SIG, 4) == 0) { - if (read_unmerged(index, buffer + 8, dest.extension_size) < 0) + if (read_reuc(index, buffer + 8, dest.extension_size) < 0) return 0; } /* else, unsupported extension. We cannot parse this, but we can skip @@ -996,6 +1383,69 @@ static int write_entries(git_index *index, git_filebuf *file) return error; } +static int write_extension(git_filebuf *file, struct index_extension *header, git_buf *data) +{ + struct index_extension ondisk; + int error = 0; + + memset(&ondisk, 0x0, sizeof(struct index_extension)); + memcpy(&ondisk, header, 4); + ondisk.extension_size = htonl(header->extension_size); + + if ((error = git_filebuf_write(file, &ondisk, sizeof(struct index_extension))) == 0) + error = git_filebuf_write(file, data->ptr, data->size); + + return error; +} + +static int create_reuc_extension_data(git_buf *reuc_buf, git_index_reuc_entry *reuc) +{ + int i; + int error = 0; + + if ((error = git_buf_put(reuc_buf, reuc->path, strlen(reuc->path) + 1)) < 0) + return error; + + for (i = 0; i < 3; i++) { + if ((error = git_buf_printf(reuc_buf, "%o", reuc->mode[i])) < 0 || + (error = git_buf_put(reuc_buf, "\0", 1)) < 0) + return error; + } + + for (i = 0; i < 3; i++) { + if (reuc->mode[i] && (error = git_buf_put(reuc_buf, (char *)&reuc->oid[i].id, GIT_OID_RAWSZ)) < 0) + return error; + } + + return 0; +} + +static int write_reuc_extension(git_index *index, git_filebuf *file) +{ + git_buf reuc_buf = GIT_BUF_INIT; + git_vector *out = &index->reuc; + git_index_reuc_entry *reuc; + struct index_extension extension; + unsigned int i; + int error = 0; + + git_vector_foreach(out, i, reuc) { + if ((error = create_reuc_extension_data(&reuc_buf, reuc)) < 0) + goto done; + } + + memset(&extension, 0x0, sizeof(struct index_extension)); + memcpy(&extension.signature, INDEX_EXT_UNMERGED_SIG, 4); + extension.extension_size = reuc_buf.size; + + error = write_extension(file, &extension, &reuc_buf); + + git_buf_free(&reuc_buf); + +done: + return error; +} + static int write_index(git_index *index, git_filebuf *file) { git_oid hash_final; @@ -1018,7 +1468,11 @@ static int write_index(git_index *index, git_filebuf *file) if (write_entries(index, file) < 0) return -1; - /* TODO: write extensions (tree cache) */ + /* TODO: write tree cache extension */ + + /* write the reuc extension */ + if (index->reuc.length > 0 && write_reuc_extension(index, file) < 0) + return -1; /* get out the hash for all the contents we've appended to the file */ git_filebuf_hash(&hash_final, file); @@ -1029,7 +1483,7 @@ static int write_index(git_index *index, git_filebuf *file) int git_index_entry_stage(const git_index_entry *entry) { - return (entry->flags & GIT_IDXENTRY_STAGEMASK) >> GIT_IDXENTRY_STAGESHIFT; + return index_entry_stage(entry); } typedef struct read_tree_data { diff --git a/src/index.h b/src/index.h index 7dd23ee60..0fd59dd45 100644 --- a/src/index.h +++ b/src/index.h @@ -33,9 +33,12 @@ struct git_index { git_tree_cache *tree; - git_vector unmerged; + git_vector reuc; + git_vector_cmp entries_cmp_path; git_vector_cmp entries_search; + git_vector_cmp entries_search_path; + git_vector_cmp reuc_search; }; extern void git_index__init_entry_from_stat(struct stat *st, git_index_entry *entry); diff --git a/src/iterator.c b/src/iterator.c index df6da9a87..5fac41046 100644 --- a/src/iterator.c +++ b/src/iterator.c @@ -336,7 +336,7 @@ static int index_iterator__current( git_iterator *self, const git_index_entry **entry) { index_iterator *ii = (index_iterator *)self; - git_index_entry *ie = git_index_get(ii->index, ii->current); + git_index_entry *ie = git_index_get_byindex(ii->index, ii->current); if (ie != NULL && ii->base.end != NULL && diff --git a/src/stash.c b/src/stash.c index 3011f00f0..9c9c5dce7 100644 --- a/src/stash.c +++ b/src/stash.c @@ -183,13 +183,13 @@ static int update_index_cb( if (!data->include_ignored) break; - return git_index_add(data->index, delta->new_file.path, 0); + return git_index_add_from_workdir(data->index, delta->new_file.path); case GIT_DELTA_UNTRACKED: if (!data->include_untracked) break; - return git_index_add(data->index, delta->new_file.path, 0); + return git_index_add_from_workdir(data->index, delta->new_file.path); case GIT_DELTA_ADDED: /* Fall through */ @@ -197,7 +197,7 @@ static int update_index_cb( if (!data->include_changed) break; - return git_index_add(data->index, delta->new_file.path, 0); + return git_index_add_from_workdir(data->index, delta->new_file.path); case GIT_DELTA_DELETED: if (!data->include_changed) @@ -206,7 +206,7 @@ static int update_index_cb( if ((pos = git_index_find(data->index, delta->new_file.path)) < 0) return -1; - if (git_index_remove(data->index, pos) < 0) + if (git_index_remove(data->index, delta->new_file.path, 0) < 0) return -1; default: diff --git a/src/submodule.c b/src/submodule.c index e3657f9ad..d69559dc2 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -332,7 +332,7 @@ int git_submodule_add_finalize(git_submodule *sm) assert(sm); if ((error = git_repository_index__weakptr(&index, sm->owner)) < 0 || - (error = git_index_add(index, GIT_MODULES_FILE, 0)) < 0) + (error = git_index_add_from_workdir(index, GIT_MODULES_FILE)) < 0) return error; return git_submodule_add_to_index(sm, true); @@ -393,7 +393,7 @@ int git_submodule_add_to_index(git_submodule *sm, int write_index) git_commit_free(head); /* add it */ - error = git_index_add2(index, &entry); + error = git_index_add(index, &entry); /* write it, if requested */ if (!error && write_index) { @@ -733,7 +733,7 @@ int git_submodule_reload(git_submodule *submodule) pos = git_index_find(index, submodule->path); if (pos >= 0) { - git_index_entry *entry = git_index_get(index, pos); + git_index_entry *entry = git_index_get_byindex(index, pos); if (S_ISGITLINK(entry->mode)) { if ((error = submodule_load_from_index(repo, entry)) < 0) diff --git a/src/tree.c b/src/tree.c index 8d3f2665c..9ecefbb61 100644 --- a/src/tree.c +++ b/src/tree.c @@ -353,7 +353,7 @@ static unsigned int find_next_dir(const char *dirname, git_index *index, unsigne dirlen = strlen(dirname); for (i = start; i < entries; ++i) { - git_index_entry *entry = git_index_get(index, i); + git_index_entry *entry = git_index_get_byindex(index, i); if (strlen(entry->path) < dirlen || memcmp(entry->path, dirname, dirlen) || (dirlen > 0 && entry->path[dirlen] != '/')) { @@ -415,7 +415,7 @@ static int write_tree( * need to keep track of the current position. */ for (i = start; i < entries; ++i) { - git_index_entry *entry = git_index_get(index, i); + git_index_entry *entry = git_index_get_byindex(index, i); char *filename, *next_slash; /* diff --git a/src/vector.c b/src/vector.c index c6a644cc3..d9c4c9900 100644 --- a/src/vector.c +++ b/src/vector.c @@ -223,6 +223,20 @@ void git_vector_uniq(git_vector *v) v->length -= j - i - 1; } +void git_vector_remove_matching(git_vector *v, int (*match)(git_vector *v, size_t idx)) +{ + unsigned int i, j; + + for (i = 0, j = 0; j < v->length; ++j) { + v->contents[i] = v->contents[j]; + + if (!match(v, i)) + i++; + } + + v->length = i; +} + void git_vector_clear(git_vector *v) { assert(v); diff --git a/src/vector.h b/src/vector.h index 49ba754f0..32f790c71 100644 --- a/src/vector.h +++ b/src/vector.h @@ -75,5 +75,6 @@ int git_vector_insert_sorted(git_vector *v, void *element, int git_vector_remove(git_vector *v, unsigned int idx); void git_vector_pop(git_vector *v); void git_vector_uniq(git_vector *v); +void git_vector_remove_matching(git_vector *v, int (*match)(git_vector *v, size_t idx)); #endif diff --git a/tests-clar/attr/repo.c b/tests-clar/attr/repo.c index 4a317e4f3..b51d5e335 100644 --- a/tests-clar/attr/repo.c +++ b/tests-clar/attr/repo.c @@ -270,12 +270,12 @@ static void assert_proper_normalization(git_index *index, const char *filename, git_index_entry *entry; add_to_workdir(filename, CONTENT); - cl_git_pass(git_index_add(index, filename, 0)); + cl_git_pass(git_index_add_from_workdir(index, filename)); index_pos = git_index_find(index, filename); cl_assert(index_pos >= 0); - entry = git_index_get(index, index_pos); + entry = git_index_get_byindex(index, index_pos); cl_assert_equal_i(0, git_oid_streq(&entry->oid, expected_sha)); } diff --git a/tests-clar/core/vector.c b/tests-clar/core/vector.c index ef3d6c36d..b165905ae 100644 --- a/tests-clar/core/vector.c +++ b/tests-clar/core/vector.c @@ -189,3 +189,87 @@ void test_core_vector__5(void) git_vector_free(&x); } + +static int remove_ones(git_vector *v, size_t idx) +{ + return (git_vector_get(v, idx) == (void *)0x001); +} + +/* Test removal based on callback */ +void test_core_vector__remove_matching(void) +{ + git_vector x; + size_t i; + void *compare; + + git_vector_init(&x, 1, NULL); + git_vector_insert(&x, (void*) 0x001); + + cl_assert(x.length == 1); + git_vector_remove_matching(&x, remove_ones); + cl_assert(x.length == 0); + + git_vector_insert(&x, (void*) 0x001); + git_vector_insert(&x, (void*) 0x001); + git_vector_insert(&x, (void*) 0x001); + + cl_assert(x.length == 3); + git_vector_remove_matching(&x, remove_ones); + cl_assert(x.length == 0); + + git_vector_insert(&x, (void*) 0x002); + git_vector_insert(&x, (void*) 0x001); + git_vector_insert(&x, (void*) 0x002); + git_vector_insert(&x, (void*) 0x001); + + cl_assert(x.length == 4); + git_vector_remove_matching(&x, remove_ones); + cl_assert(x.length == 2); + + git_vector_foreach(&x, i, compare) { + cl_assert(compare != (void *)0x001); + } + + git_vector_clear(&x); + + git_vector_insert(&x, (void*) 0x001); + git_vector_insert(&x, (void*) 0x002); + git_vector_insert(&x, (void*) 0x002); + git_vector_insert(&x, (void*) 0x001); + + cl_assert(x.length == 4); + git_vector_remove_matching(&x, remove_ones); + cl_assert(x.length == 2); + + git_vector_foreach(&x, i, compare) { + cl_assert(compare != (void *)0x001); + } + + git_vector_clear(&x); + + git_vector_insert(&x, (void*) 0x002); + git_vector_insert(&x, (void*) 0x001); + git_vector_insert(&x, (void*) 0x002); + git_vector_insert(&x, (void*) 0x001); + + cl_assert(x.length == 4); + git_vector_remove_matching(&x, remove_ones); + cl_assert(x.length == 2); + + git_vector_foreach(&x, i, compare) { + cl_assert(compare != (void *)0x001); + } + + git_vector_clear(&x); + + git_vector_insert(&x, (void*) 0x002); + git_vector_insert(&x, (void*) 0x003); + git_vector_insert(&x, (void*) 0x002); + git_vector_insert(&x, (void*) 0x003); + + cl_assert(x.length == 4); + git_vector_remove_matching(&x, remove_ones); + cl_assert(x.length == 4); + + git_vector_free(&x); +} diff --git a/tests-clar/index/conflicts.c b/tests-clar/index/conflicts.c new file mode 100644 index 000000000..59df257c5 --- /dev/null +++ b/tests-clar/index/conflicts.c @@ -0,0 +1,217 @@ +#include "clar_libgit2.h" +#include "index.h" +#include "git2/repository.h" + +static git_repository *repo; +static git_index *repo_index; + +#define TEST_REPO_PATH "mergedrepo" +#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index" + +#define CONFLICTS_ONE_ANCESTOR_OID "1f85ca51b8e0aac893a621b61a9c2661d6aa6d81" +#define CONFLICTS_ONE_OUR_OID "6aea5f295304c36144ad6e9247a291b7f8112399" +#define CONFLICTS_ONE_THEIR_OID "516bd85f78061e09ccc714561d7b504672cb52da" + +#define CONFLICTS_TWO_ANCESTOR_OID "84af62840be1b1c47b778a8a249f3ff45155038c" +#define CONFLICTS_TWO_OUR_OID "8b3f43d2402825c200f835ca1762413e386fd0b2" +#define CONFLICTS_TWO_THEIR_OID "220bd62631c8cf7a83ef39c6b94595f00517211e" + +#define TEST_ANCESTOR_OID "f00ff00ff00ff00ff00ff00ff00ff00ff00ff00f" +#define TEST_OUR_OID "b44bb44bb44bb44bb44bb44bb44bb44bb44bb44b" +#define TEST_THEIR_OID "0123456789abcdef0123456789abcdef01234567" + +// Fixture setup and teardown +void test_index_conflicts__initialize(void) +{ + repo = cl_git_sandbox_init("mergedrepo"); + git_repository_index(&repo_index, repo); +} + +void test_index_conflicts__cleanup(void) +{ + git_index_free(repo_index); + cl_git_sandbox_cleanup(); +} + +void test_index_conflicts__add(void) +{ + git_index_entry ancestor_entry, our_entry, their_entry; + + cl_assert(git_index_entrycount(repo_index) == 8); + + memset(&ancestor_entry, 0x0, sizeof(git_index_entry)); + memset(&our_entry, 0x0, sizeof(git_index_entry)); + memset(&their_entry, 0x0, sizeof(git_index_entry)); + + ancestor_entry.path = "test-one.txt"; + ancestor_entry.flags |= (1 << GIT_IDXENTRY_STAGESHIFT); + git_oid_fromstr(&ancestor_entry.oid, TEST_ANCESTOR_OID); + + our_entry.path = "test-one.txt"; + ancestor_entry.flags |= (2 << GIT_IDXENTRY_STAGESHIFT); + git_oid_fromstr(&our_entry.oid, TEST_OUR_OID); + + their_entry.path = "test-one.txt"; + ancestor_entry.flags |= (3 << GIT_IDXENTRY_STAGESHIFT); + git_oid_fromstr(&their_entry.oid, TEST_THEIR_OID); + + cl_git_pass(git_index_conflict_add(repo_index, &ancestor_entry, &our_entry, &their_entry)); + + cl_assert(git_index_entrycount(repo_index) == 11); +} + +void test_index_conflicts__add_fixes_incorrect_stage(void) +{ + git_index_entry ancestor_entry, our_entry, their_entry; + git_index_entry *conflict_entry[3]; + + cl_assert(git_index_entrycount(repo_index) == 8); + + memset(&ancestor_entry, 0x0, sizeof(git_index_entry)); + memset(&our_entry, 0x0, sizeof(git_index_entry)); + memset(&their_entry, 0x0, sizeof(git_index_entry)); + + ancestor_entry.path = "test-one.txt"; + ancestor_entry.flags |= (3 << GIT_IDXENTRY_STAGESHIFT); + git_oid_fromstr(&ancestor_entry.oid, TEST_ANCESTOR_OID); + + our_entry.path = "test-one.txt"; + ancestor_entry.flags |= (1 << GIT_IDXENTRY_STAGESHIFT); + git_oid_fromstr(&our_entry.oid, TEST_OUR_OID); + + their_entry.path = "test-one.txt"; + ancestor_entry.flags |= (2 << GIT_IDXENTRY_STAGESHIFT); + git_oid_fromstr(&their_entry.oid, TEST_THEIR_OID); + + cl_git_pass(git_index_conflict_add(repo_index, &ancestor_entry, &our_entry, &their_entry)); + + cl_assert(git_index_entrycount(repo_index) == 11); + + cl_git_pass(git_index_conflict_get(&conflict_entry[0], &conflict_entry[1], &conflict_entry[2], repo_index, "test-one.txt")); + + cl_assert(git_index_entry_stage(conflict_entry[0]) == 1); + cl_assert(git_index_entry_stage(conflict_entry[1]) == 2); + cl_assert(git_index_entry_stage(conflict_entry[2]) == 3); +} + +void test_index_conflicts__get(void) +{ + git_index_entry *conflict_entry[3]; + git_oid oid; + + cl_git_pass(git_index_conflict_get(&conflict_entry[0], &conflict_entry[1], + &conflict_entry[2], repo_index, "conflicts-one.txt")); + + cl_assert(strcmp(conflict_entry[0]->path, "conflicts-one.txt") == 0); + + git_oid_fromstr(&oid, CONFLICTS_ONE_ANCESTOR_OID); + cl_assert(git_oid_cmp(&conflict_entry[0]->oid, &oid) == 0); + + git_oid_fromstr(&oid, CONFLICTS_ONE_OUR_OID); + cl_assert(git_oid_cmp(&conflict_entry[1]->oid, &oid) == 0); + + git_oid_fromstr(&oid, CONFLICTS_ONE_THEIR_OID); + cl_assert(git_oid_cmp(&conflict_entry[2]->oid, &oid) == 0); + + cl_git_pass(git_index_conflict_get(&conflict_entry[0], &conflict_entry[1], + &conflict_entry[2], repo_index, "conflicts-two.txt")); + + cl_assert(strcmp(conflict_entry[0]->path, "conflicts-two.txt") == 0); + + git_oid_fromstr(&oid, CONFLICTS_TWO_ANCESTOR_OID); + cl_assert(git_oid_cmp(&conflict_entry[0]->oid, &oid) == 0); + + git_oid_fromstr(&oid, CONFLICTS_TWO_OUR_OID); + cl_assert(git_oid_cmp(&conflict_entry[1]->oid, &oid) == 0); + + git_oid_fromstr(&oid, CONFLICTS_TWO_THEIR_OID); + cl_assert(git_oid_cmp(&conflict_entry[2]->oid, &oid) == 0); +} + +void test_index_conflicts__remove(void) +{ + git_index_entry *entry; + size_t i; + + cl_assert(git_index_entrycount(repo_index) == 8); + + cl_git_pass(git_index_conflict_remove(repo_index, "conflicts-one.txt")); + cl_assert(git_index_entrycount(repo_index) == 5); + + for (i = 0; i < git_index_entrycount(repo_index); i++) { + cl_assert(entry = git_index_get_byindex(repo_index, i)); + cl_assert(strcmp(entry->path, "conflicts-one.txt") != 0); + } + + cl_git_pass(git_index_conflict_remove(repo_index, "conflicts-two.txt")); + cl_assert(git_index_entrycount(repo_index) == 2); + + for (i = 0; i < git_index_entrycount(repo_index); i++) { + cl_assert(entry = git_index_get_byindex(repo_index, i)); + cl_assert(strcmp(entry->path, "conflicts-two.txt") != 0); + } +} + +void test_index_conflicts__moved_to_reuc(void) +{ + git_index_entry *entry; + size_t i; + + cl_assert(git_index_entrycount(repo_index) == 8); + + cl_git_mkfile("./mergedrepo/conflicts-one.txt", "new-file\n"); + + cl_git_pass(git_index_add_from_workdir(repo_index, "conflicts-one.txt")); + + cl_assert(git_index_entrycount(repo_index) == 6); + + for (i = 0; i < git_index_entrycount(repo_index); i++) { + cl_assert(entry = git_index_get_byindex(repo_index, i)); + + if (strcmp(entry->path, "conflicts-one.txt") == 0) + cl_assert(git_index_entry_stage(entry) == 0); + } +} + +void test_index_conflicts__remove_all_conflicts(void) +{ + size_t i; + git_index_entry *entry; + + cl_assert(git_index_entrycount(repo_index) == 8); + + git_index_conflict_cleanup(repo_index); + + cl_assert(git_index_entrycount(repo_index) == 2); + + for (i = 0; i < git_index_entrycount(repo_index); i++) { + cl_assert(entry = git_index_get_byindex(repo_index, i)); + cl_assert(git_index_entry_stage(entry) == 0); + } +} + +void test_index_conflicts__partial(void) +{ + git_index_entry ancestor_entry, our_entry, their_entry; + git_index_entry *conflict_entry[3]; + + cl_assert(git_index_entrycount(repo_index) == 8); + + memset(&ancestor_entry, 0x0, sizeof(git_index_entry)); + memset(&our_entry, 0x0, sizeof(git_index_entry)); + memset(&their_entry, 0x0, sizeof(git_index_entry)); + + ancestor_entry.path = "test-one.txt"; + ancestor_entry.flags |= (1 << GIT_IDXENTRY_STAGESHIFT); + git_oid_fromstr(&ancestor_entry.oid, TEST_ANCESTOR_OID); + + cl_git_pass(git_index_conflict_add(repo_index, &ancestor_entry, NULL, NULL)); + cl_assert(git_index_entrycount(repo_index) == 9); + + cl_git_pass(git_index_conflict_get(&conflict_entry[0], &conflict_entry[1], + &conflict_entry[2], repo_index, "test-one.txt")); + + cl_assert(git_oid_cmp(&ancestor_entry.oid, &conflict_entry[0]->oid) == 0); + cl_assert(conflict_entry[1] == NULL); + cl_assert(conflict_entry[2] == NULL); +} diff --git a/tests-clar/index/filemodes.c b/tests-clar/index/filemodes.c index 75c94e8e7..882d41748 100644 --- a/tests-clar/index/filemodes.c +++ b/tests-clar/index/filemodes.c @@ -25,7 +25,7 @@ void test_index_filemodes__read(void) cl_assert_equal_i(6, git_index_entrycount(index)); for (i = 0; i < 6; ++i) { - git_index_entry *entry = git_index_get(index, i); + git_index_entry *entry = git_index_get_byindex(index, i); cl_assert(entry != NULL); cl_assert(((entry->mode & 0100) ? 1 : 0) == expected[i]); } @@ -56,35 +56,15 @@ static void add_and_check_mode( int pos; git_index_entry *entry; - cl_git_pass(git_index_add(index, filename, 0)); + cl_git_pass(git_index_add_from_workdir(index, filename)); pos = git_index_find(index, filename); cl_assert(pos >= 0); - entry = git_index_get(index, pos); + entry = git_index_get_byindex(index, pos); cl_assert(entry->mode == expect_mode); } -static void append_and_check_mode( - git_index *index, const char *filename, unsigned int expect_mode) -{ - unsigned int before, after; - git_index_entry *entry; - - before = git_index_entrycount(index); - - cl_git_pass(git_index_append(index, filename, 0)); - - after = git_index_entrycount(index); - cl_assert_equal_i(before + 1, after); - - /* bypass git_index_get since that resorts the index */ - entry = (git_index_entry *)git_vector_get(&index->entries, after - 1); - - cl_assert_equal_s(entry->path, filename); - cl_assert(expect_mode == entry->mode); -} - void test_index_filemodes__untrusted(void) { git_config *cfg; @@ -114,23 +94,7 @@ void test_index_filemodes__untrusted(void) replace_file_with_mode("exec_on", "filemodes/exec_on.1", 0755); add_and_check_mode(index, "exec_on", GIT_FILEMODE_BLOB_EXECUTABLE); - /* 5 - append 0644 over existing 0644 -> expect 0644 */ - replace_file_with_mode("exec_off", "filemodes/exec_off.2", 0644); - append_and_check_mode(index, "exec_off", GIT_FILEMODE_BLOB); - - /* 6 - append 0644 over existing 0755 -> expect 0755 */ - replace_file_with_mode("exec_on", "filemodes/exec_on.2", 0644); - append_and_check_mode(index, "exec_on", GIT_FILEMODE_BLOB_EXECUTABLE); - - /* 7 - append 0755 over existing 0644 -> expect 0644 */ - replace_file_with_mode("exec_off", "filemodes/exec_off.3", 0755); - append_and_check_mode(index, "exec_off", GIT_FILEMODE_BLOB); - - /* 8 - append 0755 over existing 0755 -> expect 0755 */ - replace_file_with_mode("exec_on", "filemodes/exec_on.3", 0755); - append_and_check_mode(index, "exec_on", GIT_FILEMODE_BLOB_EXECUTABLE); - - /* 9 - add new 0644 -> expect 0644 */ + /* 5 - add new 0644 -> expect 0644 */ cl_git_write2file("filemodes/new_off", "blah", O_WRONLY | O_CREAT | O_TRUNC, 0644); add_and_check_mode(index, "new_off", GIT_FILEMODE_BLOB); @@ -139,7 +103,7 @@ void test_index_filemodes__untrusted(void) * that doesn't support filemodes correctly, so skip it. */ if (can_filemode) { - /* 10 - add 0755 -> expect 0755 */ + /* 6 - add 0755 -> expect 0755 */ cl_git_write2file("filemodes/new_on", "blah", O_WRONLY | O_CREAT | O_TRUNC, 0755); add_and_check_mode(index, "new_on", GIT_FILEMODE_BLOB_EXECUTABLE); @@ -182,28 +146,12 @@ void test_index_filemodes__trusted(void) replace_file_with_mode("exec_on", "filemodes/exec_on.1", 0755); add_and_check_mode(index, "exec_on", GIT_FILEMODE_BLOB_EXECUTABLE); - /* 5 - append 0644 over existing 0644 -> expect 0644 */ - replace_file_with_mode("exec_off", "filemodes/exec_off.2", 0644); - append_and_check_mode(index, "exec_off", GIT_FILEMODE_BLOB); - - /* 6 - append 0644 over existing 0755 -> expect 0644 */ - replace_file_with_mode("exec_on", "filemodes/exec_on.2", 0644); - append_and_check_mode(index, "exec_on", GIT_FILEMODE_BLOB); - - /* 7 - append 0755 over existing 0644 -> expect 0755 */ - replace_file_with_mode("exec_off", "filemodes/exec_off.3", 0755); - append_and_check_mode(index, "exec_off", GIT_FILEMODE_BLOB_EXECUTABLE); - - /* 8 - append 0755 over existing 0755 -> expect 0755 */ - replace_file_with_mode("exec_on", "filemodes/exec_on.3", 0755); - append_and_check_mode(index, "exec_on", GIT_FILEMODE_BLOB_EXECUTABLE); - - /* 9 - add new 0644 -> expect 0644 */ + /* 5 - add new 0644 -> expect 0644 */ cl_git_write2file("filemodes/new_off", "blah", O_WRONLY | O_CREAT | O_TRUNC, 0644); add_and_check_mode(index, "new_off", GIT_FILEMODE_BLOB); - /* 10 - add 0755 -> expect 0755 */ + /* 6 - add 0755 -> expect 0755 */ cl_git_write2file("filemodes/new_on", "blah", O_WRONLY | O_CREAT | O_TRUNC, 0755); add_and_check_mode(index, "new_on", GIT_FILEMODE_BLOB_EXECUTABLE); diff --git a/tests-clar/index/read_tree.c b/tests-clar/index/read_tree.c index c657d4f71..f63a54bf2 100644 --- a/tests-clar/index/read_tree.c +++ b/tests-clar/index/read_tree.c @@ -24,9 +24,9 @@ void test_index_read_tree__read_write_involution(void) cl_git_mkfile("./read_tree/abc/d", NULL); cl_git_mkfile("./read_tree/abc_d", NULL); - cl_git_pass(git_index_add(index, "abc-d", 0)); - cl_git_pass(git_index_add(index, "abc_d", 0)); - cl_git_pass(git_index_add(index, "abc/d", 0)); + cl_git_pass(git_index_add_from_workdir(index, "abc-d")); + cl_git_pass(git_index_add_from_workdir(index, "abc_d")); + cl_git_pass(git_index_add_from_workdir(index, "abc/d")); /* write-tree */ cl_git_pass(git_tree_create_fromindex(&expected, index)); diff --git a/tests-clar/index/rename.c b/tests-clar/index/rename.c index eecd257fd..e16ec00c1 100644 --- a/tests-clar/index/rename.c +++ b/tests-clar/index/rename.c @@ -19,28 +19,28 @@ void test_index_rename__single_file(void) cl_git_mkfile("./rename/lame.name.txt", "new_file\n"); /* This should add a new blob to the object database in 'd4/fa8600b4f37d7516bef4816ae2c64dbf029e3a' */ - cl_git_pass(git_index_add(index, "lame.name.txt", 0)); + cl_git_pass(git_index_add_from_workdir(index, "lame.name.txt")); cl_assert(git_index_entrycount(index) == 1); cl_git_pass(git_oid_fromstr(&expected, "d4fa8600b4f37d7516bef4816ae2c64dbf029e3a")); position = git_index_find(index, "lame.name.txt"); - entry = git_index_get(index, position); + entry = git_index_get_byindex(index, position); cl_assert(git_oid_cmp(&expected, &entry->oid) == 0); /* This removes the entry from the index, but not from the object database */ - cl_git_pass(git_index_remove(index, position)); + cl_git_pass(git_index_remove(index, "lame.name.txt", 0)); cl_assert(git_index_entrycount(index) == 0); p_rename("./rename/lame.name.txt", "./rename/fancy.name.txt"); - cl_git_pass(git_index_add(index, "fancy.name.txt", 0)); + cl_git_pass(git_index_add_from_workdir(index, "fancy.name.txt")); cl_assert(git_index_entrycount(index) == 1); position = git_index_find(index, "fancy.name.txt"); - entry = git_index_get(index, position); + entry = git_index_get_byindex(index, position); cl_assert(git_oid_cmp(&expected, &entry->oid) == 0); git_index_free(index); diff --git a/tests-clar/index/reuc.c b/tests-clar/index/reuc.c new file mode 100644 index 000000000..c7c394444 --- /dev/null +++ b/tests-clar/index/reuc.c @@ -0,0 +1,236 @@ +#include "clar_libgit2.h" +#include "index.h" +#include "git2/repository.h" + +static git_repository *repo; +static git_index *repo_index; + +#define TEST_REPO_PATH "mergedrepo" +#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index" + +#define ONE_ANCESTOR_OID "478871385b9cd03908c5383acfd568bef023c6b3" +#define ONE_OUR_OID "4458b8bc9e72b6c8755ae456f60e9844d0538d8c" +#define ONE_THEIR_OID "8b72416545c7e761b64cecad4f1686eae4078aa8" + +#define TWO_ANCESTOR_OID "9d81f82fccc7dcd7de7a1ffead1815294c2e092c" +#define TWO_OUR_OID "8f3c06cff9a83757cec40c80bc9bf31a2582bde9" +#define TWO_THEIR_OID "887b153b165d32409c70163e0f734c090f12f673" + +// Fixture setup and teardown +void test_index_reuc__initialize(void) +{ + repo = cl_git_sandbox_init("mergedrepo"); + git_repository_index(&repo_index, repo); +} + +void test_index_reuc__cleanup(void) +{ + git_index_free(repo_index); + cl_git_sandbox_cleanup(); +} + +void test_index_reuc__read_bypath(void) +{ + const git_index_reuc_entry *reuc; + git_oid oid; + + cl_assert_equal_i(2, git_index_reuc_entrycount(repo_index)); + + cl_assert(reuc = git_index_reuc_get_bypath(repo_index, "two.txt")); + + cl_assert(strcmp(reuc->path, "two.txt") == 0); + cl_assert(reuc->mode[0] == 0100644); + cl_assert(reuc->mode[1] == 0100644); + cl_assert(reuc->mode[2] == 0100644); + git_oid_fromstr(&oid, TWO_ANCESTOR_OID); + cl_assert(git_oid_cmp(&reuc->oid[0], &oid) == 0); + git_oid_fromstr(&oid, TWO_OUR_OID); + cl_assert(git_oid_cmp(&reuc->oid[1], &oid) == 0); + git_oid_fromstr(&oid, TWO_THEIR_OID); + cl_assert(git_oid_cmp(&reuc->oid[2], &oid) == 0); + + cl_assert(reuc = git_index_reuc_get_bypath(repo_index, "one.txt")); + + cl_assert(strcmp(reuc->path, "one.txt") == 0); + cl_assert(reuc->mode[0] == 0100644); + cl_assert(reuc->mode[1] == 0100644); + cl_assert(reuc->mode[2] == 0100644); + git_oid_fromstr(&oid, ONE_ANCESTOR_OID); + cl_assert(git_oid_cmp(&reuc->oid[0], &oid) == 0); + git_oid_fromstr(&oid, ONE_OUR_OID); + cl_assert(git_oid_cmp(&reuc->oid[1], &oid) == 0); + git_oid_fromstr(&oid, ONE_THEIR_OID); + cl_assert(git_oid_cmp(&reuc->oid[2], &oid) == 0); +} + +void test_index_reuc__ignore_case(void) +{ + const git_index_reuc_entry *reuc; + git_oid oid; + int index_caps; + + index_caps = git_index_caps(repo_index); + + index_caps &= ~GIT_INDEXCAP_IGNORE_CASE; + cl_git_pass(git_index_set_caps(repo_index, index_caps)); + + cl_assert(!git_index_reuc_get_bypath(repo_index, "TWO.txt")); + + index_caps |= GIT_INDEXCAP_IGNORE_CASE; + cl_git_pass(git_index_set_caps(repo_index, index_caps)); + + cl_assert_equal_i(2, git_index_reuc_entrycount(repo_index)); + + cl_assert(reuc = git_index_reuc_get_bypath(repo_index, "TWO.txt")); + + cl_assert(strcmp(reuc->path, "two.txt") == 0); + cl_assert(reuc->mode[0] == 0100644); + cl_assert(reuc->mode[1] == 0100644); + cl_assert(reuc->mode[2] == 0100644); + git_oid_fromstr(&oid, TWO_ANCESTOR_OID); + cl_assert(git_oid_cmp(&reuc->oid[0], &oid) == 0); + git_oid_fromstr(&oid, TWO_OUR_OID); + cl_assert(git_oid_cmp(&reuc->oid[1], &oid) == 0); + git_oid_fromstr(&oid, TWO_THEIR_OID); + cl_assert(git_oid_cmp(&reuc->oid[2], &oid) == 0); +} + +void test_index_reuc__read_byindex(void) +{ + const git_index_reuc_entry *reuc; + git_oid oid; + + cl_assert_equal_i(2, git_index_reuc_entrycount(repo_index)); + + cl_assert(reuc = git_index_reuc_get_byindex(repo_index, 0)); + + cl_assert(strcmp(reuc->path, "one.txt") == 0); + cl_assert(reuc->mode[0] == 0100644); + cl_assert(reuc->mode[1] == 0100644); + cl_assert(reuc->mode[2] == 0100644); + git_oid_fromstr(&oid, ONE_ANCESTOR_OID); + cl_assert(git_oid_cmp(&reuc->oid[0], &oid) == 0); + git_oid_fromstr(&oid, ONE_OUR_OID); + cl_assert(git_oid_cmp(&reuc->oid[1], &oid) == 0); + git_oid_fromstr(&oid, ONE_THEIR_OID); + cl_assert(git_oid_cmp(&reuc->oid[2], &oid) == 0); + + cl_assert(reuc = git_index_reuc_get_byindex(repo_index, 1)); + + cl_assert(strcmp(reuc->path, "two.txt") == 0); + cl_assert(reuc->mode[0] == 0100644); + cl_assert(reuc->mode[1] == 0100644); + cl_assert(reuc->mode[2] == 0100644); + git_oid_fromstr(&oid, TWO_ANCESTOR_OID); + cl_assert(git_oid_cmp(&reuc->oid[0], &oid) == 0); + git_oid_fromstr(&oid, TWO_OUR_OID); + cl_assert(git_oid_cmp(&reuc->oid[1], &oid) == 0); + git_oid_fromstr(&oid, TWO_THEIR_OID); + cl_assert(git_oid_cmp(&reuc->oid[2], &oid) == 0); +} + +void test_index_reuc__updates_existing(void) +{ + const git_index_reuc_entry *reuc; + git_oid ancestor_oid, our_oid, their_oid, oid; + int index_caps; + + git_index_clear(repo_index); + + index_caps = git_index_caps(repo_index); + + index_caps |= GIT_INDEXCAP_IGNORE_CASE; + cl_git_pass(git_index_set_caps(repo_index, index_caps)); + + git_oid_fromstr(&ancestor_oid, TWO_ANCESTOR_OID); + git_oid_fromstr(&our_oid, TWO_OUR_OID); + git_oid_fromstr(&their_oid, TWO_THEIR_OID); + + cl_git_pass(git_index_reuc_add(repo_index, "two.txt", + 0100644, &ancestor_oid, + 0100644, &our_oid, + 0100644, &their_oid)); + + cl_git_pass(git_index_reuc_add(repo_index, "TWO.txt", + 0100644, &our_oid, + 0100644, &their_oid, + 0100644, &ancestor_oid)); + + cl_assert_equal_i(1, git_index_reuc_entrycount(repo_index)); + + cl_assert(reuc = git_index_reuc_get_byindex(repo_index, 0)); + + cl_assert(strcmp(reuc->path, "TWO.txt") == 0); + git_oid_fromstr(&oid, TWO_OUR_OID); + cl_assert(git_oid_cmp(&reuc->oid[0], &oid) == 0); + git_oid_fromstr(&oid, TWO_THEIR_OID); + cl_assert(git_oid_cmp(&reuc->oid[1], &oid) == 0); + git_oid_fromstr(&oid, TWO_ANCESTOR_OID); + cl_assert(git_oid_cmp(&reuc->oid[2], &oid) == 0); +} + +void test_index_reuc__remove(void) +{ + git_oid oid; + const git_index_reuc_entry *reuc; + + cl_assert_equal_i(2, git_index_reuc_entrycount(repo_index)); + + cl_git_pass(git_index_reuc_remove(repo_index, 0)); + cl_git_fail(git_index_reuc_remove(repo_index, 1)); + + cl_assert_equal_i(1, git_index_reuc_entrycount(repo_index)); + + cl_assert(reuc = git_index_reuc_get_byindex(repo_index, 0)); + + cl_assert(strcmp(reuc->path, "two.txt") == 0); + cl_assert(reuc->mode[0] == 0100644); + cl_assert(reuc->mode[1] == 0100644); + cl_assert(reuc->mode[2] == 0100644); + git_oid_fromstr(&oid, TWO_ANCESTOR_OID); + cl_assert(git_oid_cmp(&reuc->oid[0], &oid) == 0); + git_oid_fromstr(&oid, TWO_OUR_OID); + cl_assert(git_oid_cmp(&reuc->oid[1], &oid) == 0); + git_oid_fromstr(&oid, TWO_THEIR_OID); + cl_assert(git_oid_cmp(&reuc->oid[2], &oid) == 0); +} + +void test_index_reuc__write(void) +{ + git_oid ancestor_oid, our_oid, their_oid; + const git_index_reuc_entry *reuc; + + git_index_clear(repo_index); + + /* Write out of order to ensure sorting is correct */ + git_oid_fromstr(&ancestor_oid, TWO_ANCESTOR_OID); + git_oid_fromstr(&our_oid, TWO_OUR_OID); + git_oid_fromstr(&their_oid, TWO_THEIR_OID); + + cl_git_pass(git_index_reuc_add(repo_index, "two.txt", + 0100644, &ancestor_oid, + 0100644, &our_oid, + 0100644, &their_oid)); + + git_oid_fromstr(&ancestor_oid, ONE_ANCESTOR_OID); + git_oid_fromstr(&our_oid, ONE_OUR_OID); + git_oid_fromstr(&their_oid, ONE_THEIR_OID); + + cl_git_pass(git_index_reuc_add(repo_index, "one.txt", + 0100644, &ancestor_oid, + 0100644, &our_oid, + 0100644, &their_oid)); + + cl_git_pass(git_index_write(repo_index)); + + cl_git_pass(git_index_read(repo_index)); + cl_assert_equal_i(2, git_index_reuc_entrycount(repo_index)); + + /* ensure sort order was round-tripped correct */ + cl_assert(reuc = git_index_reuc_get_byindex(repo_index, 0)); + cl_assert(strcmp(reuc->path, "one.txt") == 0); + + cl_assert(reuc = git_index_reuc_get_byindex(repo_index, 1)); + cl_assert(strcmp(reuc->path, "two.txt") == 0); +} + diff --git a/tests-clar/index/stage.c b/tests-clar/index/stage.c new file mode 100644 index 000000000..ba6f1b806 --- /dev/null +++ b/tests-clar/index/stage.c @@ -0,0 +1,60 @@ +#include "clar_libgit2.h" +#include "index.h" +#include "git2/repository.h" + +static git_repository *repo; +static git_index *repo_index; + +#define TEST_REPO_PATH "mergedrepo" +#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index" + +// Fixture setup and teardown +void test_index_stage__initialize(void) +{ + repo = cl_git_sandbox_init("mergedrepo"); + git_repository_index(&repo_index, repo); +} + +void test_index_stage__cleanup(void) +{ + git_index_free(repo_index); + cl_git_sandbox_cleanup(); +} + + +void test_index_stage__add_always_adds_stage_0(void) +{ + int entry_idx; + git_index_entry *entry; + + cl_git_mkfile("./mergedrepo/new-file.txt", "new-file\n"); + + cl_git_pass(git_index_add_from_workdir(repo_index, "new-file.txt")); + + cl_assert((entry_idx = git_index_find(repo_index, "new-file.txt")) >= 0); + cl_assert((entry = git_index_get_byindex(repo_index, entry_idx)) != NULL); + cl_assert(git_index_entry_stage(entry) == 0); +} + +void test_index_stage__find_gets_first_stage(void) +{ + int entry_idx; + git_index_entry *entry; + + cl_assert((entry_idx = git_index_find(repo_index, "one.txt")) >= 0); + cl_assert((entry = git_index_get_byindex(repo_index, entry_idx)) != NULL); + cl_assert(git_index_entry_stage(entry) == 0); + + cl_assert((entry_idx = git_index_find(repo_index, "two.txt")) >= 0); + cl_assert((entry = git_index_get_byindex(repo_index, entry_idx)) != NULL); + cl_assert(git_index_entry_stage(entry) == 0); + + cl_assert((entry_idx = git_index_find(repo_index, "conflicts-one.txt")) >= 0); + cl_assert((entry = git_index_get_byindex(repo_index, entry_idx)) != NULL); + cl_assert(git_index_entry_stage(entry) == 1); + + cl_assert((entry_idx = git_index_find(repo_index, "conflicts-two.txt")) >= 0); + cl_assert((entry = git_index_get_byindex(repo_index, entry_idx)) != NULL); + cl_assert(git_index_entry_stage(entry) == 1); +} + diff --git a/tests-clar/index/tests.c b/tests-clar/index/tests.c index a535d6815..cf971e1dd 100644 --- a/tests-clar/index/tests.c +++ b/tests-clar/index/tests.c @@ -231,15 +231,19 @@ void test_index_tests__add(void) cl_git_pass(git_oid_fromstr(&id1, "a8233120f6ad708f843d861ce2b7228ec4e3dec6")); /* Add the new file to the index */ - cl_git_pass(git_index_add(index, "test.txt", 0)); + cl_git_pass(git_index_add_from_workdir(index, "test.txt")); /* Wow... it worked! */ cl_assert(git_index_entrycount(index) == 1); - entry = git_index_get(index, 0); + entry = git_index_get_byindex(index, 0); /* And the built-in hashing mechanism worked as expected */ cl_assert(git_oid_cmp(&id1, &entry->oid) == 0); + /* Test access by path instead of index */ + cl_assert((entry = git_index_get_bypath(index, "test.txt", 0)) != NULL); + cl_assert(git_oid_cmp(&id1, &entry->oid) == 0); + git_index_free(index); git_repository_free(repo); } diff --git a/tests-clar/object/commit/commitstagedfile.c b/tests-clar/object/commit/commitstagedfile.c index 6b6c573af..ac38acf5b 100644 --- a/tests-clar/object/commit/commitstagedfile.c +++ b/tests-clar/object/commit/commitstagedfile.c @@ -71,9 +71,9 @@ void test_object_commit_commitstagedfile__generate_predictable_object_ids(void) */ cl_git_mkfile("treebuilder/test.txt", "test\n"); cl_git_pass(git_repository_index(&index, repo)); - cl_git_pass(git_index_add(index, "test.txt", 0)); + cl_git_pass(git_index_add_from_workdir(index, "test.txt")); - entry = git_index_get(index, 0); + entry = git_index_get_byindex(index, 0); cl_assert(git_oid_cmp(&expected_blob_oid, &entry->oid) == 0); diff --git a/tests-clar/resources/mergedrepo/.gitted/COMMIT_EDITMSG b/tests-clar/resources/mergedrepo/.gitted/COMMIT_EDITMSG new file mode 100644 index 000000000..1f7391f92 --- /dev/null +++ b/tests-clar/resources/mergedrepo/.gitted/COMMIT_EDITMSG @@ -0,0 +1 @@ +master diff --git a/tests-clar/resources/mergedrepo/.gitted/HEAD b/tests-clar/resources/mergedrepo/.gitted/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests-clar/resources/mergedrepo/.gitted/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests-clar/resources/mergedrepo/.gitted/MERGE_HEAD b/tests-clar/resources/mergedrepo/.gitted/MERGE_HEAD new file mode 100644 index 000000000..a5bdf6e40 --- /dev/null +++ b/tests-clar/resources/mergedrepo/.gitted/MERGE_HEAD @@ -0,0 +1 @@ +e2809157a7766f272e4cfe26e61ef2678a5357ff diff --git a/tests-clar/resources/mergedrepo/.gitted/MERGE_MODE b/tests-clar/resources/mergedrepo/.gitted/MERGE_MODE new file mode 100644 index 000000000..e69de29bb diff --git a/tests-clar/resources/mergedrepo/.gitted/MERGE_MSG b/tests-clar/resources/mergedrepo/.gitted/MERGE_MSG new file mode 100644 index 000000000..7c4d1f5a9 --- /dev/null +++ b/tests-clar/resources/mergedrepo/.gitted/MERGE_MSG @@ -0,0 +1,5 @@ +Merge branch 'branch' + +Conflicts: + conflicts-one.txt + conflicts-two.txt diff --git a/tests-clar/resources/mergedrepo/.gitted/ORIG_HEAD b/tests-clar/resources/mergedrepo/.gitted/ORIG_HEAD new file mode 100644 index 000000000..13d4d6721 --- /dev/null +++ b/tests-clar/resources/mergedrepo/.gitted/ORIG_HEAD @@ -0,0 +1 @@ +3a34580a35add43a4cf361e8e9a30060a905c876 diff --git a/tests-clar/resources/mergedrepo/.gitted/config b/tests-clar/resources/mergedrepo/.gitted/config new file mode 100644 index 000000000..af107929f --- /dev/null +++ b/tests-clar/resources/mergedrepo/.gitted/config @@ -0,0 +1,6 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + ignorecase = true diff --git a/tests-clar/resources/mergedrepo/.gitted/description b/tests-clar/resources/mergedrepo/.gitted/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/tests-clar/resources/mergedrepo/.gitted/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests-clar/resources/mergedrepo/.gitted/index b/tests-clar/resources/mergedrepo/.gitted/index new file mode 100644 index 000000000..3d29f78e7 Binary files /dev/null and b/tests-clar/resources/mergedrepo/.gitted/index differ diff --git a/tests-clar/resources/mergedrepo/.gitted/info/exclude b/tests-clar/resources/mergedrepo/.gitted/info/exclude new file mode 100644 index 000000000..a5196d1be --- /dev/null +++ b/tests-clar/resources/mergedrepo/.gitted/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/tests-clar/resources/mergedrepo/.gitted/logs/HEAD b/tests-clar/resources/mergedrepo/.gitted/logs/HEAD new file mode 100644 index 000000000..a385da67b --- /dev/null +++ b/tests-clar/resources/mergedrepo/.gitted/logs/HEAD @@ -0,0 +1,5 @@ +0000000000000000000000000000000000000000 9a05ccb4e0f948de03128e095f39dae6976751c5 Edward Thomson 1351371828 -0500 commit (initial): initial +9a05ccb4e0f948de03128e095f39dae6976751c5 9a05ccb4e0f948de03128e095f39dae6976751c5 Edward Thomson 1351371835 -0500 checkout: moving from master to branch +9a05ccb4e0f948de03128e095f39dae6976751c5 e2809157a7766f272e4cfe26e61ef2678a5357ff Edward Thomson 1351371872 -0500 commit: branch +e2809157a7766f272e4cfe26e61ef2678a5357ff 9a05ccb4e0f948de03128e095f39dae6976751c5 Edward Thomson 1351371873 -0500 checkout: moving from branch to master +9a05ccb4e0f948de03128e095f39dae6976751c5 3a34580a35add43a4cf361e8e9a30060a905c876 Edward Thomson 1351372106 -0500 commit: master diff --git a/tests-clar/resources/mergedrepo/.gitted/logs/refs/heads/branch b/tests-clar/resources/mergedrepo/.gitted/logs/refs/heads/branch new file mode 100644 index 000000000..26a5e8dc5 --- /dev/null +++ b/tests-clar/resources/mergedrepo/.gitted/logs/refs/heads/branch @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 9a05ccb4e0f948de03128e095f39dae6976751c5 Edward Thomson 1351371835 -0500 branch: Created from HEAD +9a05ccb4e0f948de03128e095f39dae6976751c5 e2809157a7766f272e4cfe26e61ef2678a5357ff Edward Thomson 1351371872 -0500 commit: branch diff --git a/tests-clar/resources/mergedrepo/.gitted/logs/refs/heads/master b/tests-clar/resources/mergedrepo/.gitted/logs/refs/heads/master new file mode 100644 index 000000000..425f7bd89 --- /dev/null +++ b/tests-clar/resources/mergedrepo/.gitted/logs/refs/heads/master @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 9a05ccb4e0f948de03128e095f39dae6976751c5 Edward Thomson 1351371828 -0500 commit (initial): initial +9a05ccb4e0f948de03128e095f39dae6976751c5 3a34580a35add43a4cf361e8e9a30060a905c876 Edward Thomson 1351372106 -0500 commit: master diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/03/db1d37504ca0c4f7c26d7776b0e28bdea08712 b/tests-clar/resources/mergedrepo/.gitted/objects/03/db1d37504ca0c4f7c26d7776b0e28bdea08712 new file mode 100644 index 000000000..9232f79d9 Binary files /dev/null and b/tests-clar/resources/mergedrepo/.gitted/objects/03/db1d37504ca0c4f7c26d7776b0e28bdea08712 differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/17/0efc1023e0ed2390150bb4469c8456b63e8f91 b/tests-clar/resources/mergedrepo/.gitted/objects/17/0efc1023e0ed2390150bb4469c8456b63e8f91 new file mode 100644 index 000000000..3e124d9a4 Binary files /dev/null and b/tests-clar/resources/mergedrepo/.gitted/objects/17/0efc1023e0ed2390150bb4469c8456b63e8f91 differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/1f/85ca51b8e0aac893a621b61a9c2661d6aa6d81 b/tests-clar/resources/mergedrepo/.gitted/objects/1f/85ca51b8e0aac893a621b61a9c2661d6aa6d81 new file mode 100644 index 000000000..7bb19c873 Binary files /dev/null and b/tests-clar/resources/mergedrepo/.gitted/objects/1f/85ca51b8e0aac893a621b61a9c2661d6aa6d81 differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/22/0bd62631c8cf7a83ef39c6b94595f00517211e b/tests-clar/resources/mergedrepo/.gitted/objects/22/0bd62631c8cf7a83ef39c6b94595f00517211e new file mode 100644 index 000000000..487bcffb1 Binary files /dev/null and b/tests-clar/resources/mergedrepo/.gitted/objects/22/0bd62631c8cf7a83ef39c6b94595f00517211e differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/32/d55d59265db86dd690f0a7fc563db43e2bc6a6 b/tests-clar/resources/mergedrepo/.gitted/objects/32/d55d59265db86dd690f0a7fc563db43e2bc6a6 new file mode 100644 index 000000000..2eb3954fc Binary files /dev/null and b/tests-clar/resources/mergedrepo/.gitted/objects/32/d55d59265db86dd690f0a7fc563db43e2bc6a6 differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/38/e2d82b9065a237904af4b780b4d68da6950534 b/tests-clar/resources/mergedrepo/.gitted/objects/38/e2d82b9065a237904af4b780b4d68da6950534 new file mode 100644 index 000000000..ebe83ccb2 Binary files /dev/null and b/tests-clar/resources/mergedrepo/.gitted/objects/38/e2d82b9065a237904af4b780b4d68da6950534 differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/3a/34580a35add43a4cf361e8e9a30060a905c876 b/tests-clar/resources/mergedrepo/.gitted/objects/3a/34580a35add43a4cf361e8e9a30060a905c876 new file mode 100644 index 000000000..0d4095ffc --- /dev/null +++ b/tests-clar/resources/mergedrepo/.gitted/objects/3a/34580a35add43a4cf361e8e9a30060a905c876 @@ -0,0 +1,2 @@ +xK +1D]}Dx/O"F2oo<*ZoљuIhhrl"r YT8'#vm0.¨.:.#+9R^nG~[=VjR"IjD۔7|N` \ No newline at end of file diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/44/58b8bc9e72b6c8755ae456f60e9844d0538d8c b/tests-clar/resources/mergedrepo/.gitted/objects/44/58b8bc9e72b6c8755ae456f60e9844d0538d8c new file mode 100644 index 000000000..33389c302 Binary files /dev/null and b/tests-clar/resources/mergedrepo/.gitted/objects/44/58b8bc9e72b6c8755ae456f60e9844d0538d8c differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/47/8871385b9cd03908c5383acfd568bef023c6b3 b/tests-clar/resources/mergedrepo/.gitted/objects/47/8871385b9cd03908c5383acfd568bef023c6b3 new file mode 100644 index 000000000..5361ea685 Binary files /dev/null and b/tests-clar/resources/mergedrepo/.gitted/objects/47/8871385b9cd03908c5383acfd568bef023c6b3 differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/51/6bd85f78061e09ccc714561d7b504672cb52da b/tests-clar/resources/mergedrepo/.gitted/objects/51/6bd85f78061e09ccc714561d7b504672cb52da new file mode 100644 index 000000000..a60da877c Binary files /dev/null and b/tests-clar/resources/mergedrepo/.gitted/objects/51/6bd85f78061e09ccc714561d7b504672cb52da differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/53/c1d95a01f4514b162066fc98564500c96c46ad b/tests-clar/resources/mergedrepo/.gitted/objects/53/c1d95a01f4514b162066fc98564500c96c46ad new file mode 100644 index 000000000..85e84d71e Binary files /dev/null and b/tests-clar/resources/mergedrepo/.gitted/objects/53/c1d95a01f4514b162066fc98564500c96c46ad differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/6a/ea5f295304c36144ad6e9247a291b7f8112399 b/tests-clar/resources/mergedrepo/.gitted/objects/6a/ea5f295304c36144ad6e9247a291b7f8112399 new file mode 100644 index 000000000..b16b521e6 Binary files /dev/null and b/tests-clar/resources/mergedrepo/.gitted/objects/6a/ea5f295304c36144ad6e9247a291b7f8112399 differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/70/68e30a7f0090ae32db35dfa1e4189d8780fcb8 b/tests-clar/resources/mergedrepo/.gitted/objects/70/68e30a7f0090ae32db35dfa1e4189d8780fcb8 new file mode 100644 index 000000000..7c4e85ffb Binary files /dev/null and b/tests-clar/resources/mergedrepo/.gitted/objects/70/68e30a7f0090ae32db35dfa1e4189d8780fcb8 differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/75/938de1e367098b3e9a7b1ec3c4ac4548afffe4 b/tests-clar/resources/mergedrepo/.gitted/objects/75/938de1e367098b3e9a7b1ec3c4ac4548afffe4 new file mode 100644 index 000000000..65173fc4d Binary files /dev/null and b/tests-clar/resources/mergedrepo/.gitted/objects/75/938de1e367098b3e9a7b1ec3c4ac4548afffe4 differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/7b/26923aaf452b1977eb08617c59475fb3f74b71 b/tests-clar/resources/mergedrepo/.gitted/objects/7b/26923aaf452b1977eb08617c59475fb3f74b71 new file mode 100644 index 000000000..162fa4455 Binary files /dev/null and b/tests-clar/resources/mergedrepo/.gitted/objects/7b/26923aaf452b1977eb08617c59475fb3f74b71 differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/84/af62840be1b1c47b778a8a249f3ff45155038c b/tests-clar/resources/mergedrepo/.gitted/objects/84/af62840be1b1c47b778a8a249f3ff45155038c new file mode 100644 index 000000000..77a519f55 Binary files /dev/null and b/tests-clar/resources/mergedrepo/.gitted/objects/84/af62840be1b1c47b778a8a249f3ff45155038c differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/88/71f7a2ee3addfc4ba39fbd0783c8e738d04cda b/tests-clar/resources/mergedrepo/.gitted/objects/88/71f7a2ee3addfc4ba39fbd0783c8e738d04cda new file mode 100644 index 000000000..f624cd4f1 Binary files /dev/null and b/tests-clar/resources/mergedrepo/.gitted/objects/88/71f7a2ee3addfc4ba39fbd0783c8e738d04cda differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/88/7b153b165d32409c70163e0f734c090f12f673 b/tests-clar/resources/mergedrepo/.gitted/objects/88/7b153b165d32409c70163e0f734c090f12f673 new file mode 100644 index 000000000..096474c03 Binary files /dev/null and b/tests-clar/resources/mergedrepo/.gitted/objects/88/7b153b165d32409c70163e0f734c090f12f673 differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/8a/ad34cc83733590e74b93d0f7cf00375e2a735a b/tests-clar/resources/mergedrepo/.gitted/objects/8a/ad34cc83733590e74b93d0f7cf00375e2a735a new file mode 100644 index 000000000..a413bc6b0 Binary files /dev/null and b/tests-clar/resources/mergedrepo/.gitted/objects/8a/ad34cc83733590e74b93d0f7cf00375e2a735a differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/8b/3f43d2402825c200f835ca1762413e386fd0b2 b/tests-clar/resources/mergedrepo/.gitted/objects/8b/3f43d2402825c200f835ca1762413e386fd0b2 new file mode 100644 index 000000000..3ac8f6018 Binary files /dev/null and b/tests-clar/resources/mergedrepo/.gitted/objects/8b/3f43d2402825c200f835ca1762413e386fd0b2 differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/8b/72416545c7e761b64cecad4f1686eae4078aa8 b/tests-clar/resources/mergedrepo/.gitted/objects/8b/72416545c7e761b64cecad4f1686eae4078aa8 new file mode 100644 index 000000000..589a5ae9b Binary files /dev/null and b/tests-clar/resources/mergedrepo/.gitted/objects/8b/72416545c7e761b64cecad4f1686eae4078aa8 differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/8f/3c06cff9a83757cec40c80bc9bf31a2582bde9 b/tests-clar/resources/mergedrepo/.gitted/objects/8f/3c06cff9a83757cec40c80bc9bf31a2582bde9 new file mode 100644 index 000000000..6503985e3 Binary files /dev/null and b/tests-clar/resources/mergedrepo/.gitted/objects/8f/3c06cff9a83757cec40c80bc9bf31a2582bde9 differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/8f/fcc405925511824a2240a6d3686aa7f8c7ac50 b/tests-clar/resources/mergedrepo/.gitted/objects/8f/fcc405925511824a2240a6d3686aa7f8c7ac50 new file mode 100644 index 000000000..2eaa80838 Binary files /dev/null and b/tests-clar/resources/mergedrepo/.gitted/objects/8f/fcc405925511824a2240a6d3686aa7f8c7ac50 differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/9a/05ccb4e0f948de03128e095f39dae6976751c5 b/tests-clar/resources/mergedrepo/.gitted/objects/9a/05ccb4e0f948de03128e095f39dae6976751c5 new file mode 100644 index 000000000..7373a80d8 --- /dev/null +++ b/tests-clar/resources/mergedrepo/.gitted/objects/9a/05ccb4e0f948de03128e095f39dae6976751c5 @@ -0,0 +1 @@ +x !Dm@ c6q##Ay/ ܁:#$ltH:闄*DXhV} ˷n[-K_;Z@J GԈbq3"go@I \ No newline at end of file diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/9d/81f82fccc7dcd7de7a1ffead1815294c2e092c b/tests-clar/resources/mergedrepo/.gitted/objects/9d/81f82fccc7dcd7de7a1ffead1815294c2e092c new file mode 100644 index 000000000..c5a651f97 Binary files /dev/null and b/tests-clar/resources/mergedrepo/.gitted/objects/9d/81f82fccc7dcd7de7a1ffead1815294c2e092c differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/b7/cedb8ad4cbb22b6363f9578cbd749797f7ef0d b/tests-clar/resources/mergedrepo/.gitted/objects/b7/cedb8ad4cbb22b6363f9578cbd749797f7ef0d new file mode 100644 index 000000000..3e14b5dc8 Binary files /dev/null and b/tests-clar/resources/mergedrepo/.gitted/objects/b7/cedb8ad4cbb22b6363f9578cbd749797f7ef0d differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/d0/1885ea594926eae9ba5b54ad76692af5969f51 b/tests-clar/resources/mergedrepo/.gitted/objects/d0/1885ea594926eae9ba5b54ad76692af5969f51 new file mode 100644 index 000000000..a641adc2e Binary files /dev/null and b/tests-clar/resources/mergedrepo/.gitted/objects/d0/1885ea594926eae9ba5b54ad76692af5969f51 differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/e2/809157a7766f272e4cfe26e61ef2678a5357ff b/tests-clar/resources/mergedrepo/.gitted/objects/e2/809157a7766f272e4cfe26e61ef2678a5357ff new file mode 100644 index 000000000..fa86662e0 --- /dev/null +++ b/tests-clar/resources/mergedrepo/.gitted/objects/e2/809157a7766f272e4cfe26e61ef2678a5357ff @@ -0,0 +1,3 @@ +xK +1D]t> xNq1(]{Pe mٍ.S0[Dcd +ŅbMԝCgd@>glX].$!0*zu})/E_<ڪO:WځrơqѤh@mt;;5uZyVo\M \ No newline at end of file diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/e6/2cac5c88b9928f2695b934c70efa4285324478 b/tests-clar/resources/mergedrepo/.gitted/objects/e6/2cac5c88b9928f2695b934c70efa4285324478 new file mode 100644 index 000000000..c9841c698 Binary files /dev/null and b/tests-clar/resources/mergedrepo/.gitted/objects/e6/2cac5c88b9928f2695b934c70efa4285324478 differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/f7/2784290c151092abf04ce6b875068547f70406 b/tests-clar/resources/mergedrepo/.gitted/objects/f7/2784290c151092abf04ce6b875068547f70406 new file mode 100644 index 000000000..cd587dbec Binary files /dev/null and b/tests-clar/resources/mergedrepo/.gitted/objects/f7/2784290c151092abf04ce6b875068547f70406 differ diff --git a/tests-clar/resources/mergedrepo/.gitted/refs/heads/branch b/tests-clar/resources/mergedrepo/.gitted/refs/heads/branch new file mode 100644 index 000000000..a5bdf6e40 --- /dev/null +++ b/tests-clar/resources/mergedrepo/.gitted/refs/heads/branch @@ -0,0 +1 @@ +e2809157a7766f272e4cfe26e61ef2678a5357ff diff --git a/tests-clar/resources/mergedrepo/.gitted/refs/heads/master b/tests-clar/resources/mergedrepo/.gitted/refs/heads/master new file mode 100644 index 000000000..13d4d6721 --- /dev/null +++ b/tests-clar/resources/mergedrepo/.gitted/refs/heads/master @@ -0,0 +1 @@ +3a34580a35add43a4cf361e8e9a30060a905c876 diff --git a/tests-clar/resources/mergedrepo/conflicts-one.txt b/tests-clar/resources/mergedrepo/conflicts-one.txt new file mode 100644 index 000000000..8aad34cc8 --- /dev/null +++ b/tests-clar/resources/mergedrepo/conflicts-one.txt @@ -0,0 +1,5 @@ +<<<<<<< HEAD +This is most certainly a conflict! +======= +This is a conflict!!! +>>>>>>> branch diff --git a/tests-clar/resources/mergedrepo/conflicts-two.txt b/tests-clar/resources/mergedrepo/conflicts-two.txt new file mode 100644 index 000000000..e62cac5c8 --- /dev/null +++ b/tests-clar/resources/mergedrepo/conflicts-two.txt @@ -0,0 +1,5 @@ +<<<<<<< HEAD +This is without question another conflict! +======= +This is another conflict!!! +>>>>>>> branch diff --git a/tests-clar/resources/mergedrepo/one.txt b/tests-clar/resources/mergedrepo/one.txt new file mode 100644 index 000000000..75938de1e --- /dev/null +++ b/tests-clar/resources/mergedrepo/one.txt @@ -0,0 +1,10 @@ +This is file one! +This is file one. +This is file one. +This is file one. +This is file one. +This is file one. +This is file one. +This is file one. +This is file one. +This is file one! diff --git a/tests-clar/resources/mergedrepo/two.txt b/tests-clar/resources/mergedrepo/two.txt new file mode 100644 index 000000000..7b26923aa --- /dev/null +++ b/tests-clar/resources/mergedrepo/two.txt @@ -0,0 +1,12 @@ +This is file two! +This is file two. +This is file two. +This is file two. +This is file two. +This is file two. +This is file two. +This is file two. +This is file two. +This is file two. +This is file two. +This is file two! diff --git a/tests-clar/stash/drop.c b/tests-clar/stash/drop.c index 136a94242..5bbc7452a 100644 --- a/tests-clar/stash/drop.c +++ b/tests-clar/stash/drop.c @@ -30,7 +30,7 @@ static void push_three_states(void) cl_git_mkfile("stash/zero.txt", "content\n"); cl_git_pass(git_repository_index(&index, repo)); - cl_git_pass(git_index_add(index, "zero.txt", 0)); + cl_git_pass(git_index_add_from_workdir(index, "zero.txt")); commit_staged_files(&oid, index, signature); cl_git_mkfile("stash/one.txt", "content\n"); diff --git a/tests-clar/stash/save.c b/tests-clar/stash/save.c index 71b0b6486..01acf672c 100644 --- a/tests-clar/stash/save.c +++ b/tests-clar/stash/save.c @@ -246,8 +246,8 @@ void test_stash_save__cannot_stash_when_there_are_no_local_change(void) * 'what' and 'who' are being committed. * 'when' remain untracked. */ - git_index_add(index, "what", 0); - git_index_add(index, "who", 0); + git_index_add_from_workdir(index, "what"); + git_index_add_from_workdir(index, "who"); cl_git_pass(git_index_write(index)); commit_staged_files(&commit_oid, index, signature); git_index_free(index); diff --git a/tests-clar/stash/stash_helpers.c b/tests-clar/stash/stash_helpers.c index f646ef28b..925d0372b 100644 --- a/tests-clar/stash/stash_helpers.c +++ b/tests-clar/stash/stash_helpers.c @@ -44,10 +44,10 @@ void setup_stash(git_repository *repo, git_signature *signature) cl_git_mkfile("stash/.gitignore", "*.ignore\n"); - cl_git_pass(git_index_add(index, "what", 0)); - cl_git_pass(git_index_add(index, "how", 0)); - cl_git_pass(git_index_add(index, "who", 0)); - cl_git_pass(git_index_add(index, ".gitignore", 0)); + cl_git_pass(git_index_add_from_workdir(index, "what")); + cl_git_pass(git_index_add_from_workdir(index, "how")); + cl_git_pass(git_index_add_from_workdir(index, "who")); + cl_git_pass(git_index_add_from_workdir(index, ".gitignore")); cl_git_pass(git_index_write(index)); commit_staged_files(&commit_oid, index, signature); @@ -56,8 +56,8 @@ void setup_stash(git_repository *repo, git_signature *signature) cl_git_rewritefile("stash/how", "not so small and\n"); /* e6d64adb2c7f3eb8feb493b556cc8070dca379a3 */ cl_git_rewritefile("stash/who", "funky world\n"); /* a0400d4954659306a976567af43125a0b1aa8595 */ - cl_git_pass(git_index_add(index, "what", 0)); - cl_git_pass(git_index_add(index, "how", 0)); + cl_git_pass(git_index_add_from_workdir(index, "what")); + cl_git_pass(git_index_add_from_workdir(index, "how")); cl_git_pass(git_index_write(index)); cl_git_rewritefile("stash/what", "see you later\n"); /* bc99dc98b3eba0e9157e94769cd4d49cb49de449 */ diff --git a/tests-clar/status/worktree.c b/tests-clar/status/worktree.c index 4ff315f84..116286f67 100644 --- a/tests-clar/status/worktree.c +++ b/tests-clar/status/worktree.c @@ -438,7 +438,7 @@ void test_status_worktree__first_commit_in_progress(void) cl_assert(result.status == GIT_STATUS_WT_NEW); cl_git_pass(git_repository_index(&index, repo)); - cl_git_pass(git_index_add(index, "testfile.txt", 0)); + cl_git_pass(git_index_add_from_workdir(index, "testfile.txt")); cl_git_pass(git_index_write(index)); memset(&result, 0, sizeof(result)); @@ -570,7 +570,7 @@ void test_status_worktree__bracket_in_filename(void) /* add the file to the index */ cl_git_pass(git_repository_index(&index, repo)); - cl_git_pass(git_index_add(index, FILE_WITH_BRACKET, 0)); + cl_git_pass(git_index_add_from_workdir(index, FILE_WITH_BRACKET)); cl_git_pass(git_index_write(index)); memset(&result, 0, sizeof(result)); @@ -648,7 +648,7 @@ void test_status_worktree__space_in_filename(void) /* add the file to the index */ cl_git_pass(git_repository_index(&index, repo)); - cl_git_pass(git_index_add(index, FILE_WITH_SPACE, 0)); + cl_git_pass(git_index_add_from_workdir(index, FILE_WITH_SPACE)); cl_git_pass(git_index_write(index)); memset(&result, 0, sizeof(result)); @@ -816,7 +816,7 @@ void test_status_worktree__new_staged_file_must_handle_crlf(void) cl_git_mkfile("getting_started/testfile.txt", "content\r\n"); // Content with CRLF cl_git_pass(git_repository_index(&index, repo)); - cl_git_pass(git_index_add(index, "testfile.txt", 0)); + cl_git_pass(git_index_add_from_workdir(index, "testfile.txt")); cl_git_pass(git_index_write(index)); cl_git_pass(git_status_file(&status, repo, "testfile.txt")); diff --git a/tests-clar/submodule/status.c b/tests-clar/submodule/status.c index 63073ceca..eec028c40 100644 --- a/tests-clar/submodule/status.c +++ b/tests-clar/submodule/status.c @@ -105,7 +105,7 @@ void test_submodule_status__ignore_none(void) cl_git_pass(git_repository_index(&index, g_repo)); pos = git_index_find(index, "sm_changed_head"); cl_assert(pos >= 0); - cl_git_pass(git_index_remove(index, pos)); + cl_git_pass(git_index_remove(index, "sm_changed_head", 0)); cl_git_pass(git_index_write(index)); git_index_free(index);