summaryrefslogtreecommitdiff
path: root/src/status.c
diff options
context:
space:
mode:
authorRussell Belfer <rb@github.com>2013-06-14 16:18:04 -0700
committerRussell Belfer <rb@github.com>2013-06-17 10:03:49 -0700
commita1683f28ce2709e615490939e4e244046654d0e5 (patch)
tree8eae4e60603cac390a5da9a3cbb745ea0e4b2644 /src/status.c
parentfb03a223189f418d0767d7d04ff7509dfcfe8394 (diff)
downloadlibgit2-a1683f28ce2709e615490939e4e244046654d0e5.tar.gz
More tests and bug fixes for status with rename
This changes the behavior of the status RENAMED flags so that they will be combined with the MODIFIED flags if appropriate. If a file is modified in the index and also renamed, then the status code will have both the GIT_STATUS_INDEX_MODIFIED and INDEX_RENAMED bits set. If it is renamed but the OID has not changed, then just the GIT_STATUS_INDEX_RENAMED bit will be set. Similarly, the flags GIT_STATUS_WT_MODIFIED and GIT_STATUS_WT_RENAMED can both be set independently of one another. This fixes a serious bug where the check for unmodified files that was done at data load time could end up erasing the RENAMED state of a file that was renamed with no changes. Lastly, this contains a bunch of new tests for status with renames, including tests where the only rename changes are case changes. The expected results of these tests have to vary by whether the platform uses a case sensitive filesystem or not, so the expected data covers those platform differences separately.
Diffstat (limited to 'src/status.c')
-rw-r--r--src/status.c49
1 files changed, 38 insertions, 11 deletions
diff --git a/src/status.c b/src/status.c
index 9c4aead74..375100a89 100644
--- a/src/status.c
+++ b/src/status.c
@@ -20,11 +20,11 @@
#include "git2/diff.h"
#include "diff.h"
-static unsigned int index_delta2status(git_delta_t index_status)
+static unsigned int index_delta2status(const git_diff_delta *head2idx)
{
- unsigned int st = GIT_STATUS_CURRENT;
+ git_status_t st = GIT_STATUS_CURRENT;
- switch (index_status) {
+ switch (head2idx->status) {
case GIT_DELTA_ADDED:
case GIT_DELTA_COPIED:
st = GIT_STATUS_INDEX_NEW;
@@ -37,6 +37,9 @@ static unsigned int index_delta2status(git_delta_t index_status)
break;
case GIT_DELTA_RENAMED:
st = GIT_STATUS_INDEX_RENAMED;
+
+ if (!git_oid_equal(&head2idx->old_file.oid, &head2idx->new_file.oid))
+ st |= GIT_STATUS_INDEX_MODIFIED;
break;
case GIT_DELTA_TYPECHANGE:
st = GIT_STATUS_INDEX_TYPECHANGE;
@@ -48,11 +51,12 @@ static unsigned int index_delta2status(git_delta_t index_status)
return st;
}
-static unsigned int workdir_delta2status(git_delta_t workdir_status)
+static unsigned int workdir_delta2status(
+ git_diff_list *diff, git_diff_delta *idx2wd)
{
- unsigned int st = GIT_STATUS_CURRENT;
+ git_status_t st = GIT_STATUS_CURRENT;
- switch (workdir_status) {
+ switch (idx2wd->status) {
case GIT_DELTA_ADDED:
case GIT_DELTA_COPIED:
case GIT_DELTA_UNTRACKED:
@@ -69,6 +73,28 @@ static unsigned int workdir_delta2status(git_delta_t workdir_status)
break;
case GIT_DELTA_RENAMED:
st = GIT_STATUS_WT_RENAMED;
+
+ if (!git_oid_equal(&idx2wd->old_file.oid, &idx2wd->new_file.oid)) {
+ /* if OIDs don't match, we might need to calculate them now to
+ * discern between RENAMED vs RENAMED+MODIFED
+ */
+ if (git_oid_iszero(&idx2wd->old_file.oid) &&
+ diff->old_src == GIT_ITERATOR_TYPE_WORKDIR &&
+ !git_diff__oid_for_file(
+ diff->repo, idx2wd->old_file.path, idx2wd->old_file.mode,
+ idx2wd->old_file.size, &idx2wd->old_file.oid))
+ idx2wd->old_file.flags |= GIT_DIFF_FLAG_VALID_OID;
+
+ if (git_oid_iszero(&idx2wd->new_file.oid) &&
+ diff->new_src == GIT_ITERATOR_TYPE_WORKDIR &&
+ !git_diff__oid_for_file(
+ diff->repo, idx2wd->new_file.path, idx2wd->new_file.mode,
+ idx2wd->new_file.size, &idx2wd->new_file.oid))
+ idx2wd->new_file.flags |= GIT_DIFF_FLAG_VALID_OID;
+
+ if (!git_oid_equal(&idx2wd->old_file.oid, &idx2wd->new_file.oid))
+ st |= GIT_STATUS_WT_MODIFIED;
+ }
break;
case GIT_DELTA_TYPECHANGE:
st = GIT_STATUS_WT_TYPECHANGE;
@@ -111,18 +137,19 @@ static bool status_is_included(
}
static git_status_t status_compute(
+ git_status_list *status,
git_diff_delta *head2idx,
git_diff_delta *idx2wd)
{
- git_status_t status = 0;
+ git_status_t st = GIT_STATUS_CURRENT;
if (head2idx)
- status |= index_delta2status(head2idx->status);
+ st |= index_delta2status(head2idx);
if (idx2wd)
- status |= workdir_delta2status(idx2wd->status);
+ st |= workdir_delta2status(status->idx2wd, idx2wd);
- return status;
+ return st;
}
static int status_collect(
@@ -139,7 +166,7 @@ static int status_collect(
status_entry = git__malloc(sizeof(git_status_entry));
GITERR_CHECK_ALLOC(status_entry);
- status_entry->status = status_compute(head2idx, idx2wd);
+ status_entry->status = status_compute(status, head2idx, idx2wd);
status_entry->head_to_index = head2idx;
status_entry->index_to_workdir = idx2wd;