summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/general.c2
-rw-r--r--examples/showindex.c3
-rw-r--r--include/git2/index.h296
-rw-r--r--src/attr.c2
-rw-r--r--src/index.c610
-rw-r--r--src/index.h5
-rw-r--r--src/iterator.c2
-rw-r--r--src/stash.c8
-rw-r--r--src/submodule.c6
-rw-r--r--src/tree.c4
-rw-r--r--src/vector.c14
-rw-r--r--src/vector.h1
-rw-r--r--tests-clar/attr/repo.c4
-rw-r--r--tests-clar/core/vector.c84
-rw-r--r--tests-clar/index/conflicts.c217
-rw-r--r--tests-clar/index/filemodes.c66
-rw-r--r--tests-clar/index/read_tree.c6
-rw-r--r--tests-clar/index/rename.c10
-rw-r--r--tests-clar/index/reuc.c236
-rw-r--r--tests-clar/index/stage.c60
-rw-r--r--tests-clar/index/tests.c8
-rw-r--r--tests-clar/object/commit/commitstagedfile.c4
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/COMMIT_EDITMSG1
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/HEAD1
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/MERGE_HEAD1
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/MERGE_MODE0
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/MERGE_MSG5
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/ORIG_HEAD1
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/config6
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/description1
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/indexbin0 -> 842 bytes
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/info/exclude6
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/logs/HEAD5
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/logs/refs/heads/branch2
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/logs/refs/heads/master2
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/objects/03/db1d37504ca0c4f7c26d7776b0e28bdea08712bin0 -> 141 bytes
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/objects/17/0efc1023e0ed2390150bb4469c8456b63e8f91bin0 -> 141 bytes
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/objects/1f/85ca51b8e0aac893a621b61a9c2661d6aa6d81bin0 -> 34 bytes
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/objects/22/0bd62631c8cf7a83ef39c6b94595f00517211ebin0 -> 42 bytes
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/objects/32/d55d59265db86dd690f0a7fc563db43e2bc6a6bin0 -> 159 bytes
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/objects/38/e2d82b9065a237904af4b780b4d68da6950534bin0 -> 74 bytes
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/objects/3a/34580a35add43a4cf361e8e9a30060a905c8762
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/objects/44/58b8bc9e72b6c8755ae456f60e9844d0538d8cbin0 -> 39 bytes
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/objects/47/8871385b9cd03908c5383acfd568bef023c6b3bin0 -> 36 bytes
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/objects/51/6bd85f78061e09ccc714561d7b504672cb52dabin0 -> 36 bytes
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/objects/53/c1d95a01f4514b162066fc98564500c96c46adbin0 -> 45 bytes
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/objects/6a/ea5f295304c36144ad6e9247a291b7f8112399bin0 -> 49 bytes
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/objects/70/68e30a7f0090ae32db35dfa1e4189d8780fcb8bin0 -> 85 bytes
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/objects/75/938de1e367098b3e9a7b1ec3c4ac4548afffe4bin0 -> 41 bytes
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/objects/7b/26923aaf452b1977eb08617c59475fb3f74b71bin0 -> 41 bytes
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/objects/84/af62840be1b1c47b778a8a249f3ff45155038cbin0 -> 40 bytes
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/objects/88/71f7a2ee3addfc4ba39fbd0783c8e738d04cdabin0 -> 66 bytes
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/objects/88/7b153b165d32409c70163e0f734c090f12f673bin0 -> 38 bytes
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/objects/8a/ad34cc83733590e74b93d0f7cf00375e2a735abin0 -> 78 bytes
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/objects/8b/3f43d2402825c200f835ca1762413e386fd0b2bin0 -> 57 bytes
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/objects/8b/72416545c7e761b64cecad4f1686eae4078aa8bin0 -> 38 bytes
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/objects/8f/3c06cff9a83757cec40c80bc9bf31a2582bde9bin0 -> 39 bytes
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/objects/8f/fcc405925511824a2240a6d3686aa7f8c7ac50bin0 -> 140 bytes
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/objects/9a/05ccb4e0f948de03128e095f39dae6976751c51
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/objects/9d/81f82fccc7dcd7de7a1ffead1815294c2e092cbin0 -> 36 bytes
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/objects/b7/cedb8ad4cbb22b6363f9578cbd749797f7ef0dbin0 -> 66 bytes
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/objects/d0/1885ea594926eae9ba5b54ad76692af5969f51bin0 -> 55 bytes
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/objects/e2/809157a7766f272e4cfe26e61ef2678a5357ff3
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/objects/e6/2cac5c88b9928f2695b934c70efa4285324478bin0 -> 87 bytes
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/objects/f7/2784290c151092abf04ce6b875068547f70406bin0 -> 141 bytes
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/refs/heads/branch1
-rw-r--r--tests-clar/resources/mergedrepo/.gitted/refs/heads/master1
-rw-r--r--tests-clar/resources/mergedrepo/conflicts-one.txt5
-rw-r--r--tests-clar/resources/mergedrepo/conflicts-two.txt5
-rw-r--r--tests-clar/resources/mergedrepo/one.txt10
-rw-r--r--tests-clar/resources/mergedrepo/two.txt12
-rw-r--r--tests-clar/stash/drop.c2
-rw-r--r--tests-clar/stash/save.c4
-rw-r--r--tests-clar/stash/stash_helpers.c12
-rw-r--r--tests-clar/status/worktree.c8
-rw-r--r--tests-clar/submodule/status.c2
76 files changed, 1480 insertions, 267 deletions
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
@@ -120,20 +126,19 @@ 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.
+ * Free an existing index object.
*
* @param index an existing index object
*/
-GIT_EXTERN(void) git_index_clear(git_index *index);
+GIT_EXTERN(void) git_index_free(git_index *index);
/**
- * Free an existing index object.
+ * Get the repository this index relates to
*
- * @param index an existing index object
+ * @param index The index
+ * @return A pointer to the repository
*/
-GIT_EXTERN(void) git_index_free(git_index *index);
+GIT_EXTERN(git_repository *) git_index_owner(const git_index *index);
/**
* Read index capabilities flags.
@@ -175,44 +180,92 @@ 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
+ * @param tree tree to read
+ * @return 0 or an error code
*/
-GIT_EXTERN(int) git_index_find(git_index *index, const char *path);
+GIT_EXTERN(int) git_index_read_tree(git_index *index, git_tree *tree);
+
+/**@}*/
+
+/** @name Raw Index Entry Functions
+ *
+ * These functions work on index entries, and allow for raw manipulation
+ * of the entries.
+ */
+/**@{*/
+
+/* Index entry manipulation */
/**
- * Remove all entries with equal path except last added
+ * Get the count of entries currently in the index
*
* @param index an existing index object
+ * @return integer of count of current entries
*/
-GIT_EXTERN(void) git_index_uniq(git_index *index);
+GIT_EXTERN(unsigned int) git_index_entrycount(git_index *index);
/**
- * Add or update an index entry from a file in disk
+ * 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.
*
- * The file `path` must be relative to the repository's
- * working folder and must be readable.
+ * @param index an existing index object
+ */
+GIT_EXTERN(void) git_index_clear(git_index *index);
+
+/**
+ * Get a pointer to one of the entries in the index
*
- * This method will fail in bare index instances.
+ * 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.
*
- * 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.
+ * The entry should not be freed by the caller.
*
* @param index an existing index object
- * @param path filename to add
- * @param stage stage for the entry
+ * @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_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_add(git_index *index, const char *path, int stage);
+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.
*
@@ -220,140 +273,207 @@ GIT_EXTERN(int) git_index_add(git_index *index, const char *path, int stage);
* @param source_entry new entry object
* @return 0 or an error code
*/
-GIT_EXTERN(int) git_index_add2(git_index *index, const git_index_entry *source_entry);
+GIT_EXTERN(int) git_index_add(git_index *index, const git_index_entry *source_entry);
/**
- * Add (append) an index entry from a file in disk
+ * Return the stage number from a git index entry
+ *
+ * This entry is calculated from the entry's flag
+ * attribute like this:
+ *
+ * (entry->flags & GIT_IDXENTRY_STAGEMASK) >> GIT_IDXENTRY_STAGESHIFT
*
- * 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.
+ * @param entry The entry
+ * @returns the stage number
+ */
+GIT_EXTERN(int) git_index_entry_stage(const git_index_entry *entry);
+
+/**@}*/
+
+/** @name Workdir Index Entry Functions
+ *
+ * These functions work on index entries specifically in the working
+ * directory (ie, stage 0).
+ */
+/**@{*/
+
+/**
+ * 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.
+ *
+ * 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
- * @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);
+GIT_EXTERN(int) git_index_add_from_workdir(git_index *index, const char *path);
/**
- * Add (append) an index entry from an in-memory struct
+ * Find the first index of any entries which point to given
+ * path in the Git index.
*
- * 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.
+ * @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
*
- * A full copy (including the 'path' string) of the given
- * 'source_entry' will be inserted on the index.
+ * 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 source_entry new entry 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_append2(git_index *index, const git_index_entry *source_entry);
+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);
/**
- * Remove an entry from the index
+ * 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 position position of the entry to remove
- * @return 0 or an error code
+ * @param path path to search
*/
-GIT_EXTERN(int) git_index_remove(git_index *index, int position);
-
+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);
/**
- * 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.
+ * Removes the index entries that represent a conflict of a single file.
*
- * The entry should not be freed by the caller.
+ * @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
- * @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);
+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 entries currently in the index
+ * Get the count of resolve undo entries currently in the index.
*
* @param index an existing index object
- * @return integer of count of current entries
+ * @return integer of count of current resolve undo entries
*/
-GIT_EXTERN(unsigned int) git_index_entrycount(git_index *index);
+GIT_EXTERN(unsigned int) git_index_reuc_entrycount(git_index *index);
/**
- * Get the count of unmerged entries currently in the index
+ * Finds the resolve undo entry that points to the given path in the Git
+ * index.
*
* @param index an existing index object
- * @return integer of count of current unmerged entries
+ * @param path path to search
+ * @return an index >= 0 if found, -1 otherwise
*/
-GIT_EXTERN(unsigned int) git_index_entrycount_unmerged(git_index *index);
+GIT_EXTERN(int) git_index_reuc_find(git_index *index, const char *path);
/**
- * Get an unmerged entry from the index.
+ * 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 unmerged entry; NULL if not found
+ * @return the resolve undo entry; NULL if not found
*/
-GIT_EXTERN(const git_index_entry_unmerged *) git_index_get_unmerged_bypath(git_index *index, const char *path);
+GIT_EXTERN(const git_index_reuc_entry *) git_index_reuc_get_bypath(git_index *index, const char *path);
/**
- * Get an unmerged entry from the index.
+ * 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 unmerged entry; NULL if out of bounds
+ * @return a pointer to the resolve undo 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(const git_index_reuc_entry *) git_index_reuc_get_byindex(git_index *index, size_t n);
/**
- * Return the stage number from a git index entry
+ * Adds an resolve undo entry for a file based on the given parameters.
*
- * This entry is calculated from the entry's flag
- * attribute like this:
+ * 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.
*
- * (entry->flags & GIT_IDXENTRY_STAGEMASK) >> GIT_IDXENTRY_STAGESHIFT
+ * If there exists a resolve undo entry for the given path in the index,
+ * it will be removed.
*
- * @param entry The entry
- * @returns the stage number
- */
-GIT_EXTERN(int) git_index_entry_stage(const git_index_entry *entry);
-
-/**
- * Read a tree into the index file with stats
- *
- * The current index contents will be replaced by the specified tree. The total
- * node count is collected in stats.
+ * This method will fail in bare index instances.
*
* @param index an existing index object
- * @param tree tree to read
+ * @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_read_tree(git_index *index, git_tree *tree);
+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);
/**
- * Get the repository this index relates to
+ * Remove an resolve undo entry from the index
*
- * @param index The index
- * @return A pointer to the repository
+ * @param index an existing index object
+ * @param position position of the resolve undo entry to remove
+ * @return 0 or an error code
*/
-GIT_EXTERN(git_repository *) git_index_owner(const git_index *index);
+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 reuc_srch(const void *key, const void *array_member)
+{
+ const git_index_reuc_entry *reuc = array_member;
+
+ return strcmp(key, reuc->path);
}
-static int unmerged_srch(const void *key, const void *array_member)
+static int reuc_isrch(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 strcasecmp(key, reuc->path);
}
-static int unmerged_cmp(const void *a, const void *b)
+static int reuc_cmp(const void *a, const void *b)
{
- const git_index_entry_unmerged *info_a = a;
- const git_index_entry_unmerged *info_b = 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,16 +457,25 @@ 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_vector_sort(&index->entries);
+ return git_vector_get(&index->entries, n);
}
-git_index_entry *git_index_get(git_index *index, size_t 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);
- return git_vector_get(&index->entries, n);
+
+ 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)
@@ -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 *entry = NULL;
+ 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 = index_entry_init(&entry, index, path, stage)) < 0 ||
- (ret = index_insert(index, entry, replace)) < 0)
- {
- index_entry_free(entry);
+ if ((ret = git_index_conflict_get(&conflict_entries[0],
+ &conflict_entries[1], &conflict_entries[2], index, path)) < 0)
return ret;
- }
- git_tree_cache_invalidate_path(index->tree, entry->path);
- return 0;
-}
+ 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;
-int git_index_add(git_index *index, const char *path, int stage)
-{
- return index_add(index, path, stage, 1);
+ 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_append(git_index *index, const char *path, int stage)
+int git_index_add_from_workdir(git_index *index, const char *path)
{
- return index_add(index, path, stage, 0);
+ git_index_entry *entry = NULL;
+ int 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;
}
-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;
}
+static int index_find(git_index *index, const char *path, int stage)
+{
+ 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);
+}
+
int git_index_find(git_index *index, const char *path)
{
- return git_vector_bsearch2(&index->entries, index->entries_search, path);
+ int pos;
+
+ 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;
}
unsigned int git_index__prefix_position(git_index *index, const char *path)
{
+ struct entry_srch_key srch_key;
unsigned int pos;
- git_vector_bsearch3(&pos, &index->entries, index->entries_search, path);
+ srch_key.path = path;
+ srch_key.stage = 0;
+
+ git_vector_bsearch3(&pos, &index->entries, index->entries_search, &srch_key);
return pos;
}
-void git_index_uniq(git_index *index)
+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)
{
- git_vector_uniq(&index->entries);
+ return git_vector_bsearch2(&index->reuc, index->reuc_search, path);
}
-const git_index_entry_unmerged *git_index_get_unmerged_bypath(
+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
--- /dev/null
+++ b/tests-clar/resources/mergedrepo/.gitted/MERGE_MODE
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
--- /dev/null
+++ b/tests-clar/resources/mergedrepo/.gitted/index
Binary files 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 <ethomson@edwardthomson.com> 1351371828 -0500 commit (initial): initial
+9a05ccb4e0f948de03128e095f39dae6976751c5 9a05ccb4e0f948de03128e095f39dae6976751c5 Edward Thomson <ethomson@edwardthomson.com> 1351371835 -0500 checkout: moving from master to branch
+9a05ccb4e0f948de03128e095f39dae6976751c5 e2809157a7766f272e4cfe26e61ef2678a5357ff Edward Thomson <ethomson@edwardthomson.com> 1351371872 -0500 commit: branch
+e2809157a7766f272e4cfe26e61ef2678a5357ff 9a05ccb4e0f948de03128e095f39dae6976751c5 Edward Thomson <ethomson@edwardthomson.com> 1351371873 -0500 checkout: moving from branch to master
+9a05ccb4e0f948de03128e095f39dae6976751c5 3a34580a35add43a4cf361e8e9a30060a905c876 Edward Thomson <ethomson@edwardthomson.com> 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 <ethomson@edwardthomson.com> 1351371835 -0500 branch: Created from HEAD
+9a05ccb4e0f948de03128e095f39dae6976751c5 e2809157a7766f272e4cfe26e61ef2678a5357ff Edward Thomson <ethomson@edwardthomson.com> 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 <ethomson@edwardthomson.com> 1351371828 -0500 commit (initial): initial
+9a05ccb4e0f948de03128e095f39dae6976751c5 3a34580a35add43a4cf361e8e9a30060a905c876 Edward Thomson <ethomson@edwardthomson.com> 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
--- /dev/null
+++ b/tests-clar/resources/mergedrepo/.gitted/objects/03/db1d37504ca0c4f7c26d7776b0e28bdea08712
Binary files 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
--- /dev/null
+++ b/tests-clar/resources/mergedrepo/.gitted/objects/17/0efc1023e0ed2390150bb4469c8456b63e8f91
Binary files 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
--- /dev/null
+++ b/tests-clar/resources/mergedrepo/.gitted/objects/1f/85ca51b8e0aac893a621b61a9c2661d6aa6d81
Binary files 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
--- /dev/null
+++ b/tests-clar/resources/mergedrepo/.gitted/objects/22/0bd62631c8cf7a83ef39c6b94595f00517211e
Binary files 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
--- /dev/null
+++ b/tests-clar/resources/mergedrepo/.gitted/objects/32/d55d59265db86dd690f0a7fc563db43e2bc6a6
Binary files 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
--- /dev/null
+++ b/tests-clar/resources/mergedrepo/.gitted/objects/38/e2d82b9065a237904af4b780b4d68da6950534
Binary files 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
--- /dev/null
+++ b/tests-clar/resources/mergedrepo/.gitted/objects/44/58b8bc9e72b6c8755ae456f60e9844d0538d8c
Binary files 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
--- /dev/null
+++ b/tests-clar/resources/mergedrepo/.gitted/objects/47/8871385b9cd03908c5383acfd568bef023c6b3
Binary files 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
--- /dev/null
+++ b/tests-clar/resources/mergedrepo/.gitted/objects/51/6bd85f78061e09ccc714561d7b504672cb52da
Binary files 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
--- /dev/null
+++ b/tests-clar/resources/mergedrepo/.gitted/objects/53/c1d95a01f4514b162066fc98564500c96c46ad
Binary files 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
--- /dev/null
+++ b/tests-clar/resources/mergedrepo/.gitted/objects/6a/ea5f295304c36144ad6e9247a291b7f8112399
Binary files 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
--- /dev/null
+++ b/tests-clar/resources/mergedrepo/.gitted/objects/70/68e30a7f0090ae32db35dfa1e4189d8780fcb8
Binary files 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
--- /dev/null
+++ b/tests-clar/resources/mergedrepo/.gitted/objects/75/938de1e367098b3e9a7b1ec3c4ac4548afffe4
Binary files 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
--- /dev/null
+++ b/tests-clar/resources/mergedrepo/.gitted/objects/7b/26923aaf452b1977eb08617c59475fb3f74b71
Binary files 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
--- /dev/null
+++ b/tests-clar/resources/mergedrepo/.gitted/objects/84/af62840be1b1c47b778a8a249f3ff45155038c
Binary files 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
--- /dev/null
+++ b/tests-clar/resources/mergedrepo/.gitted/objects/88/71f7a2ee3addfc4ba39fbd0783c8e738d04cda
Binary files 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
--- /dev/null
+++ b/tests-clar/resources/mergedrepo/.gitted/objects/88/7b153b165d32409c70163e0f734c090f12f673
Binary files 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
--- /dev/null
+++ b/tests-clar/resources/mergedrepo/.gitted/objects/8a/ad34cc83733590e74b93d0f7cf00375e2a735a
Binary files 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
--- /dev/null
+++ b/tests-clar/resources/mergedrepo/.gitted/objects/8b/3f43d2402825c200f835ca1762413e386fd0b2
Binary files 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
--- /dev/null
+++ b/tests-clar/resources/mergedrepo/.gitted/objects/8b/72416545c7e761b64cecad4f1686eae4078aa8
Binary files 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
--- /dev/null
+++ b/tests-clar/resources/mergedrepo/.gitted/objects/8f/3c06cff9a83757cec40c80bc9bf31a2582bde9
Binary files 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
--- /dev/null
+++ b/tests-clar/resources/mergedrepo/.gitted/objects/8f/fcc405925511824a2240a6d3686aa7f8c7ac50
Binary files 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
--- /dev/null
+++ b/tests-clar/resources/mergedrepo/.gitted/objects/9d/81f82fccc7dcd7de7a1ffead1815294c2e092c
Binary files 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
--- /dev/null
+++ b/tests-clar/resources/mergedrepo/.gitted/objects/b7/cedb8ad4cbb22b6363f9578cbd749797f7ef0d
Binary files 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
--- /dev/null
+++ b/tests-clar/resources/mergedrepo/.gitted/objects/d0/1885ea594926eae9ba5b54ad76692af5969f51
Binary files 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
--- /dev/null
+++ b/tests-clar/resources/mergedrepo/.gitted/objects/e6/2cac5c88b9928f2695b934c70efa4285324478
Binary files 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
--- /dev/null
+++ b/tests-clar/resources/mergedrepo/.gitted/objects/f7/2784290c151092abf04ce6b875068547f70406
Binary files 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);