diff options
author | Russell Belfer <rb@github.com> | 2013-06-14 16:18:04 -0700 |
---|---|---|
committer | Russell Belfer <rb@github.com> | 2013-06-17 10:03:49 -0700 |
commit | a1683f28ce2709e615490939e4e244046654d0e5 (patch) | |
tree | 8eae4e60603cac390a5da9a3cbb745ea0e4b2644 /src/status.c | |
parent | fb03a223189f418d0767d7d04ff7509dfcfe8394 (diff) | |
download | libgit2-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.c | 49 |
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; |