Commit ff8d635a by Carlos Martín Nieto

Merge pull request #3139 from ethomson/diff_conflicts

Include conflicts when diffing
parents fb92b48d 9b3e41f7
...@@ -49,6 +49,13 @@ support for HTTPS connections insead of OpenSSL. ...@@ -49,6 +49,13 @@ support for HTTPS connections insead of OpenSSL.
the error message, which allows you to get the "repository not the error message, which allows you to get the "repository not
found" messages. found" messages.
* `git_index_conflict_add()` will remove staged entries that exist for
conflicted paths.
* The flags for a `git_diff_file` will now have the `GIT_DIFF_FLAG_EXISTS`
bit set when a file exists on that side of the diff. This is useful
for understanding whether a side of the diff exists in the presence of
a conflict.
### API additions ### API additions
...@@ -98,6 +105,18 @@ support for HTTPS connections insead of OpenSSL. ...@@ -98,6 +105,18 @@ support for HTTPS connections insead of OpenSSL.
configuration of the server, and tools can use this to show messages configuration of the server, and tools can use this to show messages
about failing to communicate with the server. about failing to communicate with the server.
* `git_diff_index_to_workdir()` and `git_diff_tree_to_index()` will now
produce deltas of type `GIT_DELTA_CONFLICTED` to indicate that the index
side of the delta is a conflict.
* The `git_status` family of functions will now produce status of type
`GIT_STATUS_CONFLICTED` to indicate that a conflict exists for that file
in the index.
* `git_index_entry_is_conflict()` is a utility function to determine if
a given index entry has a non-zero stage entry, indicating that it is
one side of a conflict.
### API removals ### API removals
* `git_remote_save()` and `git_remote_clear_refspecs()` have been * `git_remote_save()` and `git_remote_clear_refspecs()` have been
......
...@@ -226,6 +226,7 @@ typedef enum { ...@@ -226,6 +226,7 @@ typedef enum {
GIT_DIFF_FLAG_BINARY = (1u << 0), /**< file(s) treated as binary data */ GIT_DIFF_FLAG_BINARY = (1u << 0), /**< file(s) treated as binary data */
GIT_DIFF_FLAG_NOT_BINARY = (1u << 1), /**< file(s) treated as text data */ GIT_DIFF_FLAG_NOT_BINARY = (1u << 1), /**< file(s) treated as text data */
GIT_DIFF_FLAG_VALID_ID = (1u << 2), /**< `id` value is known correct */ GIT_DIFF_FLAG_VALID_ID = (1u << 2), /**< `id` value is known correct */
GIT_DIFF_FLAG_EXISTS = (1u << 3), /**< file exists at this side of the delta */
} git_diff_flag_t; } git_diff_flag_t;
/** /**
...@@ -239,16 +240,17 @@ typedef enum { ...@@ -239,16 +240,17 @@ typedef enum {
* DELETED pairs). * DELETED pairs).
*/ */
typedef enum { typedef enum {
GIT_DELTA_UNMODIFIED = 0, /**< no changes */ GIT_DELTA_UNMODIFIED = 0, /**< no changes */
GIT_DELTA_ADDED = 1, /**< entry does not exist in old version */ GIT_DELTA_ADDED = 1, /**< entry does not exist in old version */
GIT_DELTA_DELETED = 2, /**< entry does not exist in new version */ GIT_DELTA_DELETED = 2, /**< entry does not exist in new version */
GIT_DELTA_MODIFIED = 3, /**< entry content changed between old and new */ GIT_DELTA_MODIFIED = 3, /**< entry content changed between old and new */
GIT_DELTA_RENAMED = 4, /**< entry was renamed between old and new */ GIT_DELTA_RENAMED = 4, /**< entry was renamed between old and new */
GIT_DELTA_COPIED = 5, /**< entry was copied from another old entry */ GIT_DELTA_COPIED = 5, /**< entry was copied from another old entry */
GIT_DELTA_IGNORED = 6, /**< entry is ignored item in workdir */ GIT_DELTA_IGNORED = 6, /**< entry is ignored item in workdir */
GIT_DELTA_UNTRACKED = 7, /**< entry is untracked item in workdir */ GIT_DELTA_UNTRACKED = 7, /**< entry is untracked item in workdir */
GIT_DELTA_TYPECHANGE = 8, /**< type of entry changed between old and new */ GIT_DELTA_TYPECHANGE = 8, /**< type of entry changed between old and new */
GIT_DELTA_UNREADABLE = 9, /**< entry is unreadable */ GIT_DELTA_UNREADABLE = 9, /**< entry is unreadable */
GIT_DELTA_CONFLICTED = 10, /**< entry in the index is conflicted */
} git_delta_t; } git_delta_t;
/** /**
......
...@@ -430,6 +430,15 @@ GIT_EXTERN(int) git_index_add(git_index *index, const git_index_entry *source_en ...@@ -430,6 +430,15 @@ GIT_EXTERN(int) git_index_add(git_index *index, const git_index_entry *source_en
*/ */
GIT_EXTERN(int) git_index_entry_stage(const git_index_entry *entry); GIT_EXTERN(int) git_index_entry_stage(const git_index_entry *entry);
/**
* Return whether the given index entry is a conflict (has a high stage
* entry). This is simply shorthand for `git_index_entry_stage > 0`.
*
* @param entry The entry
* @return 1 if the entry is a conflict entry, 0 otherwise
*/
GIT_EXTERN(int) git_index_entry_is_conflict(const git_index_entry *entry);
/**@}*/ /**@}*/
/** @name Workdir Index Entry Functions /** @name Workdir Index Entry Functions
...@@ -631,7 +640,8 @@ GIT_EXTERN(int) git_index_find(size_t *at_pos, git_index *index, const char *pat ...@@ -631,7 +640,8 @@ GIT_EXTERN(int) git_index_find(size_t *at_pos, git_index *index, const char *pat
/**@{*/ /**@{*/
/** /**
* Add or update index entries to represent a conflict * Add or update index entries to represent a conflict. Any staged
* entries that exist at the given paths will be removed.
* *
* The entries are the entries from the tree included in the merge. Any * 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 * entry may be null to indicate that that file was not present in the
......
...@@ -46,6 +46,7 @@ typedef enum { ...@@ -46,6 +46,7 @@ typedef enum {
GIT_STATUS_WT_UNREADABLE = (1u << 12), GIT_STATUS_WT_UNREADABLE = (1u << 12),
GIT_STATUS_IGNORED = (1u << 14), GIT_STATUS_IGNORED = (1u << 14),
GIT_STATUS_CONFLICTED = (1u << 15),
} git_status_t; } git_status_t;
/** /**
......
...@@ -1173,6 +1173,9 @@ int git_index_remove_bypath(git_index *index, const char *path) ...@@ -1173,6 +1173,9 @@ int git_index_remove_bypath(git_index *index, const char *path)
ret != GIT_ENOTFOUND)) ret != GIT_ENOTFOUND))
return ret; return ret;
if (ret == GIT_ENOTFOUND)
giterr_clear();
return 0; return 0;
} }
...@@ -1314,6 +1317,30 @@ int git_index_conflict_add(git_index *index, ...@@ -1314,6 +1317,30 @@ int git_index_conflict_add(git_index *index,
(ret = index_entry_dup(&entries[2], INDEX_OWNER(index), their_entry)) < 0) (ret = index_entry_dup(&entries[2], INDEX_OWNER(index), their_entry)) < 0)
goto on_error; goto on_error;
/* Validate entries */
for (i = 0; i < 3; i++) {
if (entries[i] && !valid_filemode(entries[i]->mode)) {
giterr_set(GITERR_INDEX, "invalid filemode for stage %d entry",
i);
return -1;
}
}
/* Remove existing index entries for each path */
for (i = 0; i < 3; i++) {
if (entries[i] == NULL)
continue;
if ((ret = git_index_remove(index, entries[i]->path, 0)) != 0) {
if (ret != GIT_ENOTFOUND)
goto on_error;
giterr_clear();
ret = 0;
}
}
/* Add the conflict entries */
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
if (entries[i] == NULL) if (entries[i] == NULL)
continue; continue;
...@@ -1321,7 +1348,7 @@ int git_index_conflict_add(git_index *index, ...@@ -1321,7 +1348,7 @@ int git_index_conflict_add(git_index *index,
/* Make sure stage is correct */ /* Make sure stage is correct */
GIT_IDXENTRY_STAGE_SET(entries[i], i + 1); GIT_IDXENTRY_STAGE_SET(entries[i], i + 1);
if ((ret = index_insert(index, &entries[i], 1, true)) < 0) if ((ret = index_insert(index, &entries[i], 0, true)) < 0)
goto on_error; goto on_error;
entries[i] = NULL; /* don't free if later entry fails */ entries[i] = NULL; /* don't free if later entry fails */
...@@ -1510,7 +1537,7 @@ int git_index_conflict_next( ...@@ -1510,7 +1537,7 @@ int git_index_conflict_next(
while (iterator->cur < iterator->index->entries.length) { while (iterator->cur < iterator->index->entries.length) {
entry = git_index_get_byindex(iterator->index, iterator->cur); entry = git_index_get_byindex(iterator->index, iterator->cur);
if (git_index_entry_stage(entry) > 0) { if (git_index_entry_is_conflict(entry)) {
if ((len = index_conflict__get_byindex( if ((len = index_conflict__get_byindex(
ancestor_out, ancestor_out,
our_out, our_out,
...@@ -2356,6 +2383,11 @@ int git_index_entry_stage(const git_index_entry *entry) ...@@ -2356,6 +2383,11 @@ int git_index_entry_stage(const git_index_entry *entry)
return GIT_IDXENTRY_STAGE(entry); return GIT_IDXENTRY_STAGE(entry);
} }
int git_index_entry_is_conflict(const git_index_entry *entry)
{
return (GIT_IDXENTRY_STAGE(entry) > 0);
}
typedef struct read_tree_data { typedef struct read_tree_data {
git_index *index; git_index *index;
git_vector *old_entries; git_vector *old_entries;
...@@ -2638,7 +2670,8 @@ static int apply_each_file(const git_diff_delta *delta, float progress, void *pa ...@@ -2638,7 +2670,8 @@ static int apply_each_file(const git_diff_delta *delta, float progress, void *pa
if (error < 0) /* actual error */ if (error < 0) /* actual error */
return error; return error;
if (delta->status == GIT_DELTA_DELETED) /* If the workdir item does not exist, remove it from the index. */
if ((delta->new_file.flags & GIT_DIFF_FLAG_EXISTS) == 0)
error = git_index_remove_bypath(data->index, path); error = git_index_remove_bypath(data->index, path);
else else
error = git_index_add_bypath(data->index, delta->new_file.path); error = git_index_add_bypath(data->index, delta->new_file.path);
......
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#define iterator__include_trees(I) iterator__flag(I,INCLUDE_TREES) #define iterator__include_trees(I) iterator__flag(I,INCLUDE_TREES)
#define iterator__dont_autoexpand(I) iterator__flag(I,DONT_AUTOEXPAND) #define iterator__dont_autoexpand(I) iterator__flag(I,DONT_AUTOEXPAND)
#define iterator__do_autoexpand(I) !iterator__flag(I,DONT_AUTOEXPAND) #define iterator__do_autoexpand(I) !iterator__flag(I,DONT_AUTOEXPAND)
#define iterator__include_conflicts(I) iterator__flag(I, INCLUDE_CONFLICTS)
#define GIT_ITERATOR_FIRST_ACCESS (1 << 15) #define GIT_ITERATOR_FIRST_ACCESS (1 << 15)
#define iterator__has_been_accessed(I) iterator__flag(I,FIRST_ACCESS) #define iterator__has_been_accessed(I) iterator__flag(I,FIRST_ACCESS)
...@@ -668,13 +669,16 @@ static const git_index_entry *index_iterator__index_entry(index_iterator *ii) ...@@ -668,13 +669,16 @@ static const git_index_entry *index_iterator__index_entry(index_iterator *ii)
return ie; return ie;
} }
static const git_index_entry *index_iterator__skip_conflicts(index_iterator *ii) static const git_index_entry *index_iterator__advance_over_conflicts(index_iterator *ii)
{ {
const git_index_entry *ie; const git_index_entry *ie = index_iterator__index_entry(ii);
while ((ie = index_iterator__index_entry(ii)) != NULL && if (!iterator__include_conflicts(ii)) {
git_index_entry_stage(ie) != 0) while (ie && git_index_entry_is_conflict(ie)) {
ii->current++; ii->current++;
ie = index_iterator__index_entry(ii);
}
}
return ie; return ie;
} }
...@@ -702,7 +706,7 @@ static void index_iterator__next_prefix_tree(index_iterator *ii) ...@@ -702,7 +706,7 @@ static void index_iterator__next_prefix_tree(index_iterator *ii)
static int index_iterator__first_prefix_tree(index_iterator *ii) static int index_iterator__first_prefix_tree(index_iterator *ii)
{ {
const git_index_entry *ie = index_iterator__skip_conflicts(ii); const git_index_entry *ie = index_iterator__advance_over_conflicts(ii);
const char *scan, *prior, *slash; const char *scan, *prior, *slash;
if (!ie || !iterator__include_trees(ii)) if (!ie || !iterator__include_trees(ii))
...@@ -825,7 +829,7 @@ static int index_iterator__reset( ...@@ -825,7 +829,7 @@ static int index_iterator__reset(
git_index_snapshot_find( git_index_snapshot_find(
&ii->current, &ii->entries, ii->entry_srch, ii->base.start, 0, 0); &ii->current, &ii->entries, ii->entry_srch, ii->base.start, 0, 0);
if ((ie = index_iterator__skip_conflicts(ii)) == NULL) if ((ie = index_iterator__advance_over_conflicts(ii)) == NULL)
return 0; return 0;
if (git_buf_sets(&ii->partial, ie->path) < 0) if (git_buf_sets(&ii->partial, ie->path) < 0)
......
...@@ -33,6 +33,8 @@ typedef enum { ...@@ -33,6 +33,8 @@ typedef enum {
GIT_ITERATOR_DONT_AUTOEXPAND = (1u << 3), GIT_ITERATOR_DONT_AUTOEXPAND = (1u << 3),
/** convert precomposed unicode to decomposed unicode */ /** convert precomposed unicode to decomposed unicode */
GIT_ITERATOR_PRECOMPOSE_UNICODE = (1u << 4), GIT_ITERATOR_PRECOMPOSE_UNICODE = (1u << 4),
/** include conflicts */
GIT_ITERATOR_INCLUDE_CONFLICTS = (1u << 5),
} git_iterator_flag_t; } git_iterator_flag_t;
typedef struct { typedef struct {
......
...@@ -2492,7 +2492,7 @@ int git_merge__check_result(git_repository *repo, git_index *index_new) ...@@ -2492,7 +2492,7 @@ int git_merge__check_result(git_repository *repo, git_index *index_new)
for (i = 0; i < git_index_entrycount(index_new); i++) { for (i = 0; i < git_index_entrycount(index_new); i++) {
e = git_index_get_byindex(index_new, i); e = git_index_get_byindex(index_new, i);
if (git_index_entry_stage(e) != 0 && if (git_index_entry_is_conflict(e) &&
(git_vector_last(&paths) == NULL || (git_vector_last(&paths) == NULL ||
strcmp(git_vector_last(&paths), e->path) != 0)) { strcmp(git_vector_last(&paths), e->path) != 0)) {
...@@ -2544,7 +2544,7 @@ int git_merge__append_conflicts_to_merge_msg( ...@@ -2544,7 +2544,7 @@ int git_merge__append_conflicts_to_merge_msg(
for (i = 0; i < git_index_entrycount(index); i++) { for (i = 0; i < git_index_entrycount(index); i++) {
const git_index_entry *e = git_index_get_byindex(index, i); const git_index_entry *e = git_index_get_byindex(index, i);
if (git_index_entry_stage(e) == 0) if (!git_index_entry_is_conflict(e))
continue; continue;
if (last == NULL || strcmp(e->path, last) != 0) if (last == NULL || strcmp(e->path, last) != 0)
......
...@@ -63,6 +63,7 @@ int git_reset_default( ...@@ -63,6 +63,7 @@ int git_reset_default(
assert(delta->status == GIT_DELTA_ADDED || assert(delta->status == GIT_DELTA_ADDED ||
delta->status == GIT_DELTA_MODIFIED || delta->status == GIT_DELTA_MODIFIED ||
delta->status == GIT_DELTA_CONFLICTED ||
delta->status == GIT_DELTA_DELETED); delta->status == GIT_DELTA_DELETED);
error = git_index_conflict_remove(index, delta->old_file.path); error = git_index_conflict_remove(index, delta->old_file.path);
......
...@@ -44,6 +44,9 @@ static unsigned int index_delta2status(const git_diff_delta *head2idx) ...@@ -44,6 +44,9 @@ static unsigned int index_delta2status(const git_diff_delta *head2idx)
case GIT_DELTA_TYPECHANGE: case GIT_DELTA_TYPECHANGE:
st = GIT_STATUS_INDEX_TYPECHANGE; st = GIT_STATUS_INDEX_TYPECHANGE;
break; break;
case GIT_DELTA_CONFLICTED:
st = GIT_STATUS_CONFLICTED;
break;
default: default:
break; break;
} }
...@@ -102,6 +105,9 @@ static unsigned int workdir_delta2status( ...@@ -102,6 +105,9 @@ static unsigned int workdir_delta2status(
case GIT_DELTA_TYPECHANGE: case GIT_DELTA_TYPECHANGE:
st = GIT_STATUS_WT_TYPECHANGE; st = GIT_STATUS_WT_TYPECHANGE;
break; break;
case GIT_DELTA_CONFLICTED:
st = GIT_STATUS_CONFLICTED;
break;
default: default:
break; break;
} }
......
...@@ -102,7 +102,7 @@ static void create_index(struct checkout_index_entry *entries, size_t entries_le ...@@ -102,7 +102,7 @@ static void create_index(struct checkout_index_entry *entries, size_t entries_le
memset(&entry, 0x0, sizeof(git_index_entry)); memset(&entry, 0x0, sizeof(git_index_entry));
entry.mode = entries[i].mode; entry.mode = entries[i].mode;
entry.flags = entries[i].stage << GIT_IDXENTRY_STAGESHIFT; GIT_IDXENTRY_STAGE_SET(&entry, entries[i].stage);
git_oid_fromstr(&entry.id, entries[i].oid_str); git_oid_fromstr(&entry.id, entries[i].oid_str);
entry.path = entries[i].path; entry.path = entries[i].path;
......
...@@ -685,15 +685,15 @@ static void add_conflict(git_index *index, const char *path) ...@@ -685,15 +685,15 @@ static void add_conflict(git_index *index, const char *path)
entry.path = path; entry.path = path;
git_oid_fromstr(&entry.id, "d427e0b2e138501a3d15cc376077a3631e15bd46"); git_oid_fromstr(&entry.id, "d427e0b2e138501a3d15cc376077a3631e15bd46");
entry.flags = (1 << GIT_IDXENTRY_STAGESHIFT); GIT_IDXENTRY_STAGE_SET(&entry, 1);
cl_git_pass(git_index_add(index, &entry)); cl_git_pass(git_index_add(index, &entry));
git_oid_fromstr(&entry.id, "4e886e602529caa9ab11d71f86634bd1b6e0de10"); git_oid_fromstr(&entry.id, "4e886e602529caa9ab11d71f86634bd1b6e0de10");
entry.flags = (2 << GIT_IDXENTRY_STAGESHIFT); GIT_IDXENTRY_STAGE_SET(&entry, 2);
cl_git_pass(git_index_add(index, &entry)); cl_git_pass(git_index_add(index, &entry));
git_oid_fromstr(&entry.id, "2bd0a343aeef7a2cf0d158478966a6e587ff3863"); git_oid_fromstr(&entry.id, "2bd0a343aeef7a2cf0d158478966a6e587ff3863");
entry.flags = (3 << GIT_IDXENTRY_STAGESHIFT); GIT_IDXENTRY_STAGE_SET(&entry, 3);
cl_git_pass(git_index_add(index, &entry)); cl_git_pass(git_index_add(index, &entry));
} }
......
...@@ -893,16 +893,16 @@ static void create_conflict(const char *path) ...@@ -893,16 +893,16 @@ static void create_conflict(const char *path)
memset(&entry, 0x0, sizeof(git_index_entry)); memset(&entry, 0x0, sizeof(git_index_entry));
entry.mode = 0100644; entry.mode = 0100644;
entry.flags = 1 << GIT_IDXENTRY_STAGESHIFT; GIT_IDXENTRY_STAGE_SET(&entry, 1);
git_oid_fromstr(&entry.id, "d427e0b2e138501a3d15cc376077a3631e15bd46"); git_oid_fromstr(&entry.id, "d427e0b2e138501a3d15cc376077a3631e15bd46");
entry.path = path; entry.path = path;
cl_git_pass(git_index_add(index, &entry)); cl_git_pass(git_index_add(index, &entry));
entry.flags = 2 << GIT_IDXENTRY_STAGESHIFT; GIT_IDXENTRY_STAGE_SET(&entry, 2);
git_oid_fromstr(&entry.id, "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf"); git_oid_fromstr(&entry.id, "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf");
cl_git_pass(git_index_add(index, &entry)); cl_git_pass(git_index_add(index, &entry));
entry.flags = 3 << GIT_IDXENTRY_STAGESHIFT; GIT_IDXENTRY_STAGE_SET(&entry, 3);
git_oid_fromstr(&entry.id, "2bd0a343aeef7a2cf0d158478966a6e587ff3863"); git_oid_fromstr(&entry.id, "2bd0a343aeef7a2cf0d158478966a6e587ff3863");
cl_git_pass(git_index_add(index, &entry)); cl_git_pass(git_index_add(index, &entry));
......
...@@ -197,6 +197,14 @@ git_repository *cl_git_sandbox_init(const char *sandbox) ...@@ -197,6 +197,14 @@ git_repository *cl_git_sandbox_init(const char *sandbox)
return _cl_repo; return _cl_repo;
} }
git_repository *cl_git_sandbox_init_new(const char *sandbox)
{
cl_git_pass(git_repository_init(&_cl_repo, sandbox, false));
_cl_sandbox = sandbox;
return _cl_repo;
}
git_repository *cl_git_sandbox_reopen(void) git_repository *cl_git_sandbox_reopen(void)
{ {
if (_cl_repo) { if (_cl_repo) {
......
...@@ -127,6 +127,7 @@ int cl_rename(const char *source, const char *dest); ...@@ -127,6 +127,7 @@ int cl_rename(const char *source, const char *dest);
/* Git sandbox setup helpers */ /* Git sandbox setup helpers */
git_repository *cl_git_sandbox_init(const char *sandbox); git_repository *cl_git_sandbox_init(const char *sandbox);
git_repository *cl_git_sandbox_init_new(const char *name);
void cl_git_sandbox_cleanup(void); void cl_git_sandbox_cleanup(void);
git_repository *cl_git_sandbox_reopen(void); git_repository *cl_git_sandbox_reopen(void);
......
...@@ -68,7 +68,7 @@ int diff_file_cb( ...@@ -68,7 +68,7 @@ int diff_file_cb(
if ((delta->flags & GIT_DIFF_FLAG_BINARY) != 0) if ((delta->flags & GIT_DIFF_FLAG_BINARY) != 0)
e->files_binary++; e->files_binary++;
cl_assert(delta->status <= GIT_DELTA_TYPECHANGE); cl_assert(delta->status <= GIT_DELTA_CONFLICTED);
e->file_status[delta->status] += 1; e->file_status[delta->status] += 1;
......
...@@ -8,7 +8,7 @@ typedef struct { ...@@ -8,7 +8,7 @@ typedef struct {
int files; int files;
int files_binary; int files_binary;
int file_status[10]; /* indexed by git_delta_t value */ int file_status[11]; /* indexed by git_delta_t value */
int hunks; int hunks;
int hunk_new_lines; int hunk_new_lines;
......
...@@ -163,3 +163,79 @@ void test_diff_index__checks_options_version(void) ...@@ -163,3 +163,79 @@ void test_diff_index__checks_options_version(void)
git_tree_free(a); git_tree_free(a);
} }
static void do_conflicted_diff(diff_expects *exp, unsigned long flags)
{
const char *a_commit = "26a125ee1bf"; /* the current HEAD */
git_tree *a = resolve_commit_oid_to_tree(g_repo, a_commit);
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
git_index_entry ancestor = {0}, ours = {0}, theirs = {0};
git_diff *diff = NULL;
git_index *index;
cl_assert(a);
opts.context_lines = 1;
opts.interhunk_lines = 1;
opts.flags |= flags;
memset(exp, 0, sizeof(diff_expects));
cl_git_pass(git_repository_index(&index, g_repo));
ancestor.path = ours.path = theirs.path = "staged_changes";
ancestor.mode = ours.mode = theirs.mode = 0100644;
git_oid_fromstr(&ancestor.id, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
git_oid_fromstr(&ours.id, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
git_oid_fromstr(&theirs.id, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
cl_git_pass(git_index_conflict_add(index, &ancestor, &ours, &theirs));
cl_git_pass(git_diff_tree_to_index(&diff, g_repo, a, index, &opts));
cl_git_pass(git_diff_foreach(
diff, diff_file_cb, diff_hunk_cb, diff_line_cb, exp));
git_diff_free(diff);
git_tree_free(a);
git_index_free(index);
}
void test_diff_index__reports_conflicts(void)
{
diff_expects exp;
do_conflicted_diff(&exp, 0);
cl_assert_equal_i(8, exp.files);
cl_assert_equal_i(3, exp.file_status[GIT_DELTA_ADDED]);
cl_assert_equal_i(2, exp.file_status[GIT_DELTA_DELETED]);
cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]);
cl_assert_equal_i(1, exp.file_status[GIT_DELTA_CONFLICTED]);
cl_assert_equal_i(7, exp.hunks);
cl_assert_equal_i(9, exp.lines);
cl_assert_equal_i(2, exp.line_ctxt);
cl_assert_equal_i(5, exp.line_adds);
cl_assert_equal_i(2, exp.line_dels);
}
void test_diff_index__reports_conflicts_when_reversed(void)
{
diff_expects exp;
do_conflicted_diff(&exp, GIT_DIFF_REVERSE);
cl_assert_equal_i(8, exp.files);
cl_assert_equal_i(2, exp.file_status[GIT_DELTA_ADDED]);
cl_assert_equal_i(3, exp.file_status[GIT_DELTA_DELETED]);
cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]);
cl_assert_equal_i(1, exp.file_status[GIT_DELTA_CONFLICTED]);
cl_assert_equal_i(7, exp.hunks);
cl_assert_equal_i(9, exp.lines);
cl_assert_equal_i(2, exp.line_ctxt);
cl_assert_equal_i(2, exp.line_adds);
cl_assert_equal_i(5, exp.line_dels);
}
...@@ -68,6 +68,51 @@ void test_diff_workdir__to_index(void) ...@@ -68,6 +68,51 @@ void test_diff_workdir__to_index(void)
git_diff_free(diff); git_diff_free(diff);
} }
void test_diff_workdir__to_index_with_conflicts(void)
{
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
git_diff *diff = NULL;
git_index *index;
git_index_entry our_entry = {0}, their_entry = {0};
diff_expects exp = {0};
g_repo = cl_git_sandbox_init("status");
opts.context_lines = 3;
opts.interhunk_lines = 1;
/* Adding an entry that represents a rename gets two files in conflict */
our_entry.path = "subdir/modified_file";
our_entry.mode = 0100644;
their_entry.path = "subdir/rename_conflict";
their_entry.mode = 0100644;
cl_git_pass(git_repository_index(&index, g_repo));
cl_git_pass(git_index_conflict_add(index, NULL, &our_entry, &their_entry));
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, index, &opts));
cl_git_pass(diff_foreach_via_iterator(
diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
cl_assert_equal_i(9, exp.files);
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]);
cl_assert_equal_i(3, exp.file_status[GIT_DELTA_MODIFIED]);
cl_assert_equal_i(2, exp.file_status[GIT_DELTA_CONFLICTED]);
cl_assert_equal_i(7, exp.hunks);
cl_assert_equal_i(12, exp.lines);
cl_assert_equal_i(4, exp.line_ctxt);
cl_assert_equal_i(3, exp.line_adds);
cl_assert_equal_i(5, exp.line_dels);
git_diff_free(diff);
git_index_free(index);
}
void test_diff_workdir__to_index_with_assume_unchanged(void) void test_diff_workdir__to_index_with_assume_unchanged(void)
{ {
git_diff_options opts = GIT_DIFF_OPTIONS_INIT; git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
......
...@@ -57,7 +57,7 @@ void test_index_collision__add_with_highstage_1(void) ...@@ -57,7 +57,7 @@ void test_index_collision__add_with_highstage_1(void)
git_oid_fromstr(&entry.id, "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"); git_oid_fromstr(&entry.id, "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391");
entry.path = "a/b"; entry.path = "a/b";
entry.flags = (2 << GIT_IDXENTRY_STAGESHIFT); GIT_IDXENTRY_STAGE_SET(&entry, 2);
cl_git_pass(git_index_add(index, &entry)); cl_git_pass(git_index_add(index, &entry));
/* create a blob beneath the previous tree entry */ /* create a blob beneath the previous tree entry */
...@@ -67,7 +67,7 @@ void test_index_collision__add_with_highstage_1(void) ...@@ -67,7 +67,7 @@ void test_index_collision__add_with_highstage_1(void)
/* create another tree entry above the blob */ /* create another tree entry above the blob */
entry.path = "a/b"; entry.path = "a/b";
entry.flags = (1 << GIT_IDXENTRY_STAGESHIFT); GIT_IDXENTRY_STAGE_SET(&entry, 1);
cl_git_pass(git_index_add(index, &entry)); cl_git_pass(git_index_add(index, &entry));
git_index_free(index); git_index_free(index);
...@@ -89,17 +89,17 @@ void test_index_collision__add_with_highstage_2(void) ...@@ -89,17 +89,17 @@ void test_index_collision__add_with_highstage_2(void)
git_oid_fromstr(&entry.id, "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"); git_oid_fromstr(&entry.id, "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391");
entry.path = "a/b/c"; entry.path = "a/b/c";
entry.flags = (1 << GIT_IDXENTRY_STAGESHIFT); GIT_IDXENTRY_STAGE_SET(&entry, 1);
cl_git_pass(git_index_add(index, &entry)); cl_git_pass(git_index_add(index, &entry));
/* create a blob beneath the previous tree entry */ /* create a blob beneath the previous tree entry */
entry.path = "a/b/c"; entry.path = "a/b/c";
entry.flags = (2 << GIT_IDXENTRY_STAGESHIFT); GIT_IDXENTRY_STAGE_SET(&entry, 2);
cl_git_pass(git_index_add(index, &entry)); cl_git_pass(git_index_add(index, &entry));
/* create another tree entry above the blob */ /* create another tree entry above the blob */
entry.path = "a/b"; entry.path = "a/b";
entry.flags = (3 << GIT_IDXENTRY_STAGESHIFT); GIT_IDXENTRY_STAGE_SET(&entry, 3);
cl_git_pass(git_index_add(index, &entry)); cl_git_pass(git_index_add(index, &entry));
git_index_free(index); git_index_free(index);
......
...@@ -16,6 +16,7 @@ static git_index *repo_index; ...@@ -16,6 +16,7 @@ static git_index *repo_index;
#define CONFLICTS_TWO_OUR_OID "8b3f43d2402825c200f835ca1762413e386fd0b2" #define CONFLICTS_TWO_OUR_OID "8b3f43d2402825c200f835ca1762413e386fd0b2"
#define CONFLICTS_TWO_THEIR_OID "220bd62631c8cf7a83ef39c6b94595f00517211e" #define CONFLICTS_TWO_THEIR_OID "220bd62631c8cf7a83ef39c6b94595f00517211e"
#define TEST_STAGED_OID "beefdadafeedabedcafedeedbabedeadbeaddeaf"
#define TEST_ANCESTOR_OID "f00ff00ff00ff00ff00ff00ff00ff00ff00ff00f" #define TEST_ANCESTOR_OID "f00ff00ff00ff00ff00ff00ff00ff00ff00ff00f"
#define TEST_OUR_OID "b44bb44bb44bb44bb44bb44bb44bb44bb44bb44b" #define TEST_OUR_OID "b44bb44bb44bb44bb44bb44bb44bb44bb44bb44b"
#define TEST_THEIR_OID "0123456789abcdef0123456789abcdef01234567" #define TEST_THEIR_OID "0123456789abcdef0123456789abcdef01234567"
...@@ -46,15 +47,18 @@ void test_index_conflicts__add(void) ...@@ -46,15 +47,18 @@ void test_index_conflicts__add(void)
memset(&their_entry, 0x0, sizeof(git_index_entry)); memset(&their_entry, 0x0, sizeof(git_index_entry));
ancestor_entry.path = "test-one.txt"; ancestor_entry.path = "test-one.txt";
ancestor_entry.flags |= (1 << GIT_IDXENTRY_STAGESHIFT); ancestor_entry.mode = 0100644;
GIT_IDXENTRY_STAGE_SET(&ancestor_entry, 1);
git_oid_fromstr(&ancestor_entry.id, TEST_ANCESTOR_OID); git_oid_fromstr(&ancestor_entry.id, TEST_ANCESTOR_OID);
our_entry.path = "test-one.txt"; our_entry.path = "test-one.txt";
ancestor_entry.flags |= (2 << GIT_IDXENTRY_STAGESHIFT); our_entry.mode = 0100644;
GIT_IDXENTRY_STAGE_SET(&our_entry, 2);
git_oid_fromstr(&our_entry.id, TEST_OUR_OID); git_oid_fromstr(&our_entry.id, TEST_OUR_OID);
their_entry.path = "test-one.txt"; their_entry.path = "test-one.txt";
ancestor_entry.flags |= (3 << GIT_IDXENTRY_STAGESHIFT); their_entry.mode = 0100644;
GIT_IDXENTRY_STAGE_SET(&ancestor_entry, 2);
git_oid_fromstr(&their_entry.id, TEST_THEIR_OID); git_oid_fromstr(&their_entry.id, TEST_THEIR_OID);
cl_git_pass(git_index_conflict_add(repo_index, &ancestor_entry, &our_entry, &their_entry)); cl_git_pass(git_index_conflict_add(repo_index, &ancestor_entry, &our_entry, &their_entry));
...@@ -74,15 +78,18 @@ void test_index_conflicts__add_fixes_incorrect_stage(void) ...@@ -74,15 +78,18 @@ void test_index_conflicts__add_fixes_incorrect_stage(void)
memset(&their_entry, 0x0, sizeof(git_index_entry)); memset(&their_entry, 0x0, sizeof(git_index_entry));
ancestor_entry.path = "test-one.txt"; ancestor_entry.path = "test-one.txt";
ancestor_entry.flags |= (3 << GIT_IDXENTRY_STAGESHIFT); ancestor_entry.mode = 0100644;
GIT_IDXENTRY_STAGE_SET(&ancestor_entry, 3);
git_oid_fromstr(&ancestor_entry.id, TEST_ANCESTOR_OID); git_oid_fromstr(&ancestor_entry.id, TEST_ANCESTOR_OID);
our_entry.path = "test-one.txt"; our_entry.path = "test-one.txt";
ancestor_entry.flags |= (1 << GIT_IDXENTRY_STAGESHIFT); our_entry.mode = 0100644;
GIT_IDXENTRY_STAGE_SET(&our_entry, 1);
git_oid_fromstr(&our_entry.id, TEST_OUR_OID); git_oid_fromstr(&our_entry.id, TEST_OUR_OID);
their_entry.path = "test-one.txt"; their_entry.path = "test-one.txt";
ancestor_entry.flags |= (2 << GIT_IDXENTRY_STAGESHIFT); their_entry.mode = 0100644;
GIT_IDXENTRY_STAGE_SET(&their_entry, 2);
git_oid_fromstr(&their_entry.id, TEST_THEIR_OID); git_oid_fromstr(&their_entry.id, TEST_THEIR_OID);
cl_git_pass(git_index_conflict_add(repo_index, &ancestor_entry, &our_entry, &their_entry)); cl_git_pass(git_index_conflict_add(repo_index, &ancestor_entry, &our_entry, &their_entry));
...@@ -96,6 +103,55 @@ void test_index_conflicts__add_fixes_incorrect_stage(void) ...@@ -96,6 +103,55 @@ void test_index_conflicts__add_fixes_incorrect_stage(void)
cl_assert(git_index_entry_stage(conflict_entry[2]) == 3); cl_assert(git_index_entry_stage(conflict_entry[2]) == 3);
} }
void test_index_conflicts__add_removes_stage_zero(void)
{
git_index_entry staged, ancestor_entry, our_entry, their_entry;
const git_index_entry *conflict_entry[3];
cl_assert(git_index_entrycount(repo_index) == 8);
memset(&staged, 0x0, sizeof(git_index_entry));
memset(&ancestor_entry, 0x0, sizeof(git_index_entry));
memset(&our_entry, 0x0, sizeof(git_index_entry));
memset(&their_entry, 0x0, sizeof(git_index_entry));
staged.path = "test-one.txt";
staged.mode = 0100644;
git_oid_fromstr(&staged.id, TEST_STAGED_OID);
cl_git_pass(git_index_add(repo_index, &staged));
cl_assert(git_index_entrycount(repo_index) == 9);
ancestor_entry.path = "test-one.txt";
ancestor_entry.mode = 0100644;
GIT_IDXENTRY_STAGE_SET(&ancestor_entry, 3);
git_oid_fromstr(&ancestor_entry.id, TEST_ANCESTOR_OID);
our_entry.path = "test-one.txt";
our_entry.mode = 0100644;
GIT_IDXENTRY_STAGE_SET(&our_entry, 1);
git_oid_fromstr(&our_entry.id, TEST_OUR_OID);
their_entry.path = "test-one.txt";
their_entry.mode = 0100644;
GIT_IDXENTRY_STAGE_SET(&their_entry, 2);
git_oid_fromstr(&their_entry.id, 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_assert_equal_p(NULL, git_index_get_bypath(repo_index, "test-one.txt", 0));
cl_git_pass(git_index_conflict_get(&conflict_entry[0], &conflict_entry[1], &conflict_entry[2], repo_index, "test-one.txt"));
cl_assert_equal_oid(&ancestor_entry.id, &conflict_entry[0]->id);
cl_assert_equal_i(1, git_index_entry_stage(conflict_entry[0]));
cl_assert_equal_oid(&our_entry.id, &conflict_entry[1]->id);
cl_assert_equal_i(2, git_index_entry_stage(conflict_entry[1]));
cl_assert_equal_oid(&their_entry.id, &conflict_entry[2]->id);
cl_assert_equal_i(3, git_index_entry_stage(conflict_entry[2]));
}
void test_index_conflicts__get(void) void test_index_conflicts__get(void)
{ {
const git_index_entry *conflict_entry[3]; const git_index_entry *conflict_entry[3];
...@@ -216,7 +272,7 @@ void test_index_conflicts__moved_to_reuc_on_add(void) ...@@ -216,7 +272,7 @@ void test_index_conflicts__moved_to_reuc_on_add(void)
cl_assert(entry = git_index_get_byindex(repo_index, i)); cl_assert(entry = git_index_get_byindex(repo_index, i));
if (strcmp(entry->path, "conflicts-one.txt") == 0) if (strcmp(entry->path, "conflicts-one.txt") == 0)
cl_assert(git_index_entry_stage(entry) == 0); cl_assert(!git_index_entry_is_conflict(entry));
} }
} }
...@@ -256,7 +312,7 @@ void test_index_conflicts__remove_all_conflicts(void) ...@@ -256,7 +312,7 @@ void test_index_conflicts__remove_all_conflicts(void)
for (i = 0; i < git_index_entrycount(repo_index); i++) { for (i = 0; i < git_index_entrycount(repo_index); i++) {
cl_assert(entry = git_index_get_byindex(repo_index, i)); cl_assert(entry = git_index_get_byindex(repo_index, i));
cl_assert(git_index_entry_stage(entry) == 0); cl_assert(!git_index_entry_is_conflict(entry));
} }
} }
...@@ -272,7 +328,8 @@ void test_index_conflicts__partial(void) ...@@ -272,7 +328,8 @@ void test_index_conflicts__partial(void)
memset(&their_entry, 0x0, sizeof(git_index_entry)); memset(&their_entry, 0x0, sizeof(git_index_entry));
ancestor_entry.path = "test-one.txt"; ancestor_entry.path = "test-one.txt";
ancestor_entry.flags |= (1 << GIT_IDXENTRY_STAGESHIFT); ancestor_entry.mode = 0100644;
GIT_IDXENTRY_STAGE_SET(&ancestor_entry, 1);
git_oid_fromstr(&ancestor_entry.id, TEST_ANCESTOR_OID); git_oid_fromstr(&ancestor_entry.id, TEST_ANCESTOR_OID);
cl_git_pass(git_index_conflict_add(repo_index, &ancestor_entry, NULL, NULL)); cl_git_pass(git_index_conflict_add(repo_index, &ancestor_entry, NULL, NULL));
......
...@@ -71,7 +71,7 @@ static int merge_trivial_conflict_entrycount(git_index *index) ...@@ -71,7 +71,7 @@ static int merge_trivial_conflict_entrycount(git_index *index)
for (i = 0; i < git_index_entrycount(index); i++) { for (i = 0; i < git_index_entrycount(index); i++) {
cl_assert(entry = git_index_get_byindex(index, i)); cl_assert(entry = git_index_get_byindex(index, i));
if (git_index_entry_stage(entry) > 0) if (git_index_entry_is_conflict(entry))
count++; count++;
} }
......
...@@ -66,7 +66,7 @@ static size_t merge_trivial_conflict_entrycount(void) ...@@ -66,7 +66,7 @@ static size_t merge_trivial_conflict_entrycount(void)
for (i = 0; i < git_index_entrycount(repo_index); i++) { for (i = 0; i < git_index_entrycount(repo_index); i++) {
cl_assert(entry = git_index_get_byindex(repo_index, i)); cl_assert(entry = git_index_get_byindex(repo_index, i));
if (git_index_entry_stage(entry) > 0) if (git_index_entry_is_conflict(entry))
count++; count++;
} }
......
...@@ -126,17 +126,17 @@ static void add_fake_conflicts(git_index *index) ...@@ -126,17 +126,17 @@ static void add_fake_conflicts(git_index *index)
ancestor_entry.path = "duplicate"; ancestor_entry.path = "duplicate";
ancestor_entry.mode = GIT_FILEMODE_BLOB; ancestor_entry.mode = GIT_FILEMODE_BLOB;
ancestor_entry.flags |= (1 << GIT_IDXENTRY_STAGESHIFT); GIT_IDXENTRY_STAGE_SET(&ancestor_entry, 1);
git_oid_fromstr(&ancestor_entry.id, "a8233120f6ad708f843d861ce2b7228ec4e3dec6"); git_oid_fromstr(&ancestor_entry.id, "a8233120f6ad708f843d861ce2b7228ec4e3dec6");
our_entry.path = "duplicate"; our_entry.path = "duplicate";
our_entry.mode = GIT_FILEMODE_BLOB; our_entry.mode = GIT_FILEMODE_BLOB;
ancestor_entry.flags |= (2 << GIT_IDXENTRY_STAGESHIFT); GIT_IDXENTRY_STAGE_SET(&our_entry, 2);
git_oid_fromstr(&our_entry.id, "45b983be36b73c0788dc9cbcb76cbb80fc7bb057"); git_oid_fromstr(&our_entry.id, "45b983be36b73c0788dc9cbcb76cbb80fc7bb057");
their_entry.path = "duplicate"; their_entry.path = "duplicate";
their_entry.mode = GIT_FILEMODE_BLOB; their_entry.mode = GIT_FILEMODE_BLOB;
ancestor_entry.flags |= (3 << GIT_IDXENTRY_STAGESHIFT); GIT_IDXENTRY_STAGE_SET(&their_entry, 3);
git_oid_fromstr(&their_entry.id, "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd"); git_oid_fromstr(&their_entry.id, "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd");
cl_git_pass(git_index_conflict_add(index, &ancestor_entry, &our_entry, &their_entry)); cl_git_pass(git_index_conflict_add(index, &ancestor_entry, &our_entry, &their_entry));
......
...@@ -108,7 +108,7 @@ static void index_entry_init(git_index *index, int side, git_oid *oid) ...@@ -108,7 +108,7 @@ static void index_entry_init(git_index *index, int side, git_oid *oid)
memset(&entry, 0x0, sizeof(git_index_entry)); memset(&entry, 0x0, sizeof(git_index_entry));
entry.path = "conflicting_file"; entry.path = "conflicting_file";
entry.flags = (side << GIT_IDXENTRY_STAGESHIFT); GIT_IDXENTRY_STAGE_SET(&entry, side);
entry.mode = 0100644; entry.mode = 0100644;
git_oid_cpy(&entry.id, oid); git_oid_cpy(&entry.id, oid);
......
...@@ -461,14 +461,17 @@ void test_status_worktree__conflict_with_diff3(void) ...@@ -461,14 +461,17 @@ void test_status_worktree__conflict_with_diff3(void)
memset(&their_entry, 0x0, sizeof(git_index_entry)); memset(&their_entry, 0x0, sizeof(git_index_entry));
ancestor_entry.path = "modified_file"; ancestor_entry.path = "modified_file";
ancestor_entry.mode = 0100644;
git_oid_fromstr(&ancestor_entry.id, git_oid_fromstr(&ancestor_entry.id,
"452e4244b5d083ddf0460acf1ecc74db9dcfa11a"); "452e4244b5d083ddf0460acf1ecc74db9dcfa11a");
our_entry.path = "modified_file"; our_entry.path = "modified_file";
our_entry.mode = 0100644;
git_oid_fromstr(&our_entry.id, git_oid_fromstr(&our_entry.id,
"452e4244b5d083ddf0460acf1ecc74db9dcfa11a"); "452e4244b5d083ddf0460acf1ecc74db9dcfa11a");
their_entry.path = "modified_file"; their_entry.path = "modified_file";
their_entry.mode = 0100644;
git_oid_fromstr(&their_entry.id, git_oid_fromstr(&their_entry.id,
"452e4244b5d083ddf0460acf1ecc74db9dcfa11a"); "452e4244b5d083ddf0460acf1ecc74db9dcfa11a");
...@@ -484,7 +487,7 @@ void test_status_worktree__conflict_with_diff3(void) ...@@ -484,7 +487,7 @@ void test_status_worktree__conflict_with_diff3(void)
cl_git_pass(git_status_file(&status, repo, "modified_file")); cl_git_pass(git_status_file(&status, repo, "modified_file"));
cl_assert_equal_i(GIT_STATUS_INDEX_DELETED | GIT_STATUS_WT_NEW, status); cl_assert_equal_i(GIT_STATUS_CONFLICTED, status);
} }
static const char *filemode_paths[] = { static const char *filemode_paths[] = {
...@@ -614,14 +617,17 @@ void test_status_worktree__conflicted_item(void) ...@@ -614,14 +617,17 @@ void test_status_worktree__conflicted_item(void)
memset(&our_entry, 0x0, sizeof(git_index_entry)); memset(&our_entry, 0x0, sizeof(git_index_entry));
memset(&their_entry, 0x0, sizeof(git_index_entry)); memset(&their_entry, 0x0, sizeof(git_index_entry));
ancestor_entry.mode = 0100644;
ancestor_entry.path = "modified_file"; ancestor_entry.path = "modified_file";
git_oid_fromstr(&ancestor_entry.id, git_oid_fromstr(&ancestor_entry.id,
"452e4244b5d083ddf0460acf1ecc74db9dcfa11a"); "452e4244b5d083ddf0460acf1ecc74db9dcfa11a");
our_entry.mode = 0100644;
our_entry.path = "modified_file"; our_entry.path = "modified_file";
git_oid_fromstr(&our_entry.id, git_oid_fromstr(&our_entry.id,
"452e4244b5d083ddf0460acf1ecc74db9dcfa11a"); "452e4244b5d083ddf0460acf1ecc74db9dcfa11a");
their_entry.mode = 0100644;
their_entry.path = "modified_file"; their_entry.path = "modified_file";
git_oid_fromstr(&their_entry.id, git_oid_fromstr(&their_entry.id,
"452e4244b5d083ddf0460acf1ecc74db9dcfa11a"); "452e4244b5d083ddf0460acf1ecc74db9dcfa11a");
...@@ -634,9 +640,55 @@ void test_status_worktree__conflicted_item(void) ...@@ -634,9 +640,55 @@ void test_status_worktree__conflicted_item(void)
&our_entry, &their_entry)); &our_entry, &their_entry));
cl_git_pass(git_status_file(&status, repo, "modified_file")); cl_git_pass(git_status_file(&status, repo, "modified_file"));
cl_assert_equal_i(GIT_STATUS_WT_MODIFIED, status); cl_assert_equal_i(GIT_STATUS_CONFLICTED, status);
git_index_free(index);
}
void test_status_worktree__conflict_has_no_oid(void)
{
git_repository *repo = cl_git_sandbox_init("status");
git_index *index;
git_index_entry entry = {0};
git_status_list *statuslist;
const git_status_entry *status;
git_oid zero_id = {0};
entry.mode = 0100644;
entry.path = "modified_file";
git_oid_fromstr(&entry.id, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
cl_git_pass(git_repository_index(&index, repo));
cl_git_pass(git_index_conflict_add(index, &entry, &entry, &entry));
git_status_list_new(&statuslist, repo, NULL);
cl_assert_equal_i(16, git_status_list_entrycount(statuslist));
status = git_status_byindex(statuslist, 2);
cl_assert_equal_i(GIT_STATUS_CONFLICTED, status->status);
cl_assert_equal_s("modified_file", status->head_to_index->old_file.path);
cl_assert(!git_oid_equal(&zero_id, &status->head_to_index->old_file.id));
cl_assert(0 != status->head_to_index->old_file.mode);
cl_assert_equal_s("modified_file", status->head_to_index->new_file.path);
cl_assert_equal_oid(&zero_id, &status->head_to_index->new_file.id);
cl_assert_equal_i(0, status->head_to_index->new_file.mode);
cl_assert_equal_i(0, status->head_to_index->new_file.size);
cl_assert_equal_s("modified_file", status->index_to_workdir->old_file.path);
cl_assert_equal_oid(&zero_id, &status->index_to_workdir->old_file.id);
cl_assert_equal_i(0, status->index_to_workdir->old_file.mode);
cl_assert_equal_i(0, status->index_to_workdir->old_file.size);
cl_assert_equal_s("modified_file", status->index_to_workdir->new_file.path);
cl_assert(
!git_oid_equal(&zero_id, &status->index_to_workdir->new_file.id) ||
!(status->index_to_workdir->new_file.flags & GIT_DIFF_FLAG_VALID_ID));
cl_assert(0 != status->index_to_workdir->new_file.mode);
cl_assert(0 != status->index_to_workdir->new_file.size);
git_index_free(index); git_index_free(index);
git_status_list_free(statuslist);
} }
static void stage_and_commit(git_repository *repo, const char *path) static void stage_and_commit(git_repository *repo, const char *path)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment