GIT_DIFF_DISABLE_PATHSPEC_MATCH = (1 << 11),
GIT_DIFF_DELTAS_ARE_ICASE = (1 << 12),
GIT_DIFF_INCLUDE_UNTRACKED_CONTENT = (1 << 13),
+ GIT_DIFF_DONT_SPLIT_TYPECHANGE = (1 << 14),
};
/**
GIT_DELTA_RENAMED = 4,
GIT_DELTA_COPIED = 5,
GIT_DELTA_IGNORED = 6,
- GIT_DELTA_UNTRACKED = 7
+ GIT_DELTA_UNTRACKED = 7,
+ GIT_DELTA_TYPECHANGE = 8,
} git_delta_t;
/**
*/
GIT_BEGIN_DECL
-enum {
- GIT_STATUS_CURRENT = 0,
+typedef enum {
+ GIT_STATUS_CURRENT = 0,
- GIT_STATUS_INDEX_NEW = (1 << 0),
- GIT_STATUS_INDEX_MODIFIED = (1 << 1),
- GIT_STATUS_INDEX_DELETED = (1 << 2),
+ GIT_STATUS_INDEX_NEW = (1u << 0),
+ GIT_STATUS_INDEX_MODIFIED = (1u << 1),
+ GIT_STATUS_INDEX_DELETED = (1u << 2),
+ GIT_STATUS_INDEX_RENAMED = (1u << 3),
+ GIT_STATUS_INDEX_TYPECHANGE = (1u << 4),
- GIT_STATUS_WT_NEW = (1 << 3),
- GIT_STATUS_WT_MODIFIED = (1 << 4),
- GIT_STATUS_WT_DELETED = (1 << 5),
+ GIT_STATUS_WT_NEW = (1u << 7),
+ GIT_STATUS_WT_MODIFIED = (1u << 8),
+ GIT_STATUS_WT_DELETED = (1u << 9),
+ GIT_STATUS_WT_TYPECHANGE = (1u << 10),
- GIT_STATUS_IGNORED = (1 << 6),
-};
+ GIT_STATUS_IGNORED = (1u << 14),
+} git_status_t;
/**
* Gather file statuses and run a callback for each one.
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);
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) */
/* 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 */
/* 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 */
/* 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))
switch (index_status) {
case GIT_DELTA_ADDED:
case GIT_DELTA_COPIED:
- case GIT_DELTA_RENAMED:
st = GIT_STATUS_INDEX_NEW;
break;
case GIT_DELTA_DELETED:
case GIT_DELTA_MODIFIED:
st = GIT_STATUS_INDEX_MODIFIED;
break;
+ case GIT_DELTA_RENAMED:
+ st = GIT_STATUS_INDEX_RENAMED;
+ break;
+ case GIT_DELTA_TYPECHANGE:
+ st = GIT_STATUS_INDEX_TYPECHANGE;
+ break;
default:
break;
}
switch (workdir_status) {
case GIT_DELTA_ADDED:
- case GIT_DELTA_COPIED:
case GIT_DELTA_RENAMED:
+ case GIT_DELTA_COPIED:
case GIT_DELTA_UNTRACKED:
st = GIT_STATUS_WT_NEW;
break;
case GIT_DELTA_IGNORED:
st = GIT_STATUS_IGNORED;
break;
+ case GIT_DELTA_TYPECHANGE:
+ st = GIT_STATUS_WT_TYPECHANGE;
+ break;
default:
break;
}
memset(&diffopt, 0, sizeof(diffopt));
memcpy(&diffopt.pathspec, &opts->pathspec, sizeof(diffopt.pathspec));
+ diffopt.flags = GIT_DIFF_DONT_SPLIT_TYPECHANGE;
+
if ((opts->flags & GIT_STATUS_OPT_INCLUDE_UNTRACKED) != 0)
diffopt.flags = diffopt.flags | GIT_DIFF_INCLUDE_UNTRACKED;
if ((opts->flags & GIT_STATUS_OPT_INCLUDE_IGNORED) != 0)