summaryrefslogtreecommitdiff
path: root/src/diff.c
diff options
context:
space:
mode:
authorRussell Belfer <rb@github.com>2012-09-28 13:40:02 -0700
committerRussell Belfer <rb@github.com>2012-10-09 11:54:01 -0700
commitbc16fd3ebf8727900f2b8c2f44cb14fd03f80bcc (patch)
treea2038177ca25685b108d768e9cabf0ed57d85963 /src/diff.c
parentfade21db0a7a1d535b6352943ecd7b5ae6841e57 (diff)
downloadlibgit2-bc16fd3ebf8727900f2b8c2f44cb14fd03f80bcc.tar.gz
Introduce status/diff TYPECHANGE flags
When I wrote the diff code, I based it on core git's diff output which tends to split a type change into an add and a delete. But core git's status has the notion of a T (typechange) flag for a file. This introduces that into our status APIs and modifies the diff code so it can be forced to not split type changes.
Diffstat (limited to 'src/diff.c')
-rw-r--r--src/diff.c26
1 files changed, 14 insertions, 12 deletions
diff --git a/src/diff.c b/src/diff.c
index 8ab8af3a1..f88bda4aa 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -508,6 +508,7 @@ static int maybe_modified(
git_delta_t status = GIT_DELTA_MODIFIED;
unsigned int omode = oitem->mode;
unsigned int nmode = nitem->mode;
+ bool new_is_workdir = (new_iter->type == GIT_ITERATOR_WORKDIR);
GIT_UNUSED(old_iter);
@@ -515,15 +516,14 @@ static int maybe_modified(
return 0;
/* on platforms with no symlinks, preserve mode of existing symlinks */
- if (S_ISLNK(omode) && S_ISREG(nmode) &&
- !(diff->diffcaps & GIT_DIFFCAPS_HAS_SYMLINKS) &&
- new_iter->type == GIT_ITERATOR_WORKDIR)
+ if (S_ISLNK(omode) && S_ISREG(nmode) && new_is_workdir &&
+ !(diff->diffcaps & GIT_DIFFCAPS_HAS_SYMLINKS))
nmode = omode;
/* on platforms with no execmode, just preserve old mode */
if (!(diff->diffcaps & GIT_DIFFCAPS_TRUST_MODE_BITS) &&
(nmode & MODE_BITS_MASK) != (omode & MODE_BITS_MASK) &&
- new_iter->type == GIT_ITERATOR_WORKDIR)
+ new_is_workdir)
nmode = (nmode & ~MODE_BITS_MASK) | (omode & MODE_BITS_MASK);
/* support "assume unchanged" (poorly, b/c we still stat everything) */
@@ -537,10 +537,14 @@ static int maybe_modified(
/* if basic type of file changed, then split into delete and add */
else if (GIT_MODE_TYPE(omode) != GIT_MODE_TYPE(nmode)) {
- if (diff_delta__from_one(diff, GIT_DELTA_DELETED, oitem) < 0 ||
- diff_delta__from_one(diff, GIT_DELTA_ADDED, nitem) < 0)
- return -1;
- return 0;
+ if ((diff->opts.flags & GIT_DIFF_DONT_SPLIT_TYPECHANGE) != 0)
+ status = GIT_DELTA_TYPECHANGE;
+ else {
+ if (diff_delta__from_one(diff, GIT_DELTA_DELETED, oitem) < 0 ||
+ diff_delta__from_one(diff, GIT_DELTA_ADDED, nitem) < 0)
+ return -1;
+ return 0;
+ }
}
/* if oids and modes match, then file is unmodified */
@@ -551,9 +555,7 @@ static int maybe_modified(
/* if we have an unknown OID and a workdir iterator, then check some
* circumstances that can accelerate things or need special handling
*/
- else if (git_oid_iszero(&nitem->oid) &&
- new_iter->type == GIT_ITERATOR_WORKDIR)
- {
+ else if (git_oid_iszero(&nitem->oid) && new_is_workdir) {
/* TODO: add check against index file st_mtime to avoid racy-git */
/* if the stat data looks exactly alike, then assume the same */
@@ -600,7 +602,7 @@ static int maybe_modified(
/* if we got here and decided that the files are modified, but we
* haven't calculated the OID of the new item, then calculate it now
*/
- if (status == GIT_DELTA_MODIFIED && git_oid_iszero(&nitem->oid)) {
+ if (status != GIT_DELTA_UNMODIFIED && git_oid_iszero(&nitem->oid)) {
if (oid_for_workdir_item(diff->repo, nitem, &noid) < 0)
return -1;
else if (omode == nmode && git_oid_equal(&oitem->oid, &noid))