summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRussell Belfer <arrbee@arrbee.com>2012-03-22 10:44:36 -0700
committerRussell Belfer <arrbee@arrbee.com>2012-03-22 10:44:36 -0700
commit66142ae03134ef8a45e6bd304c6106a1685c3c99 (patch)
tree2a938d7439f419e4764e54040d787982efcffa71 /src
parent95340398a1821bd19da1bfe459ba1f375ed89404 (diff)
downloadlibgit2-66142ae03134ef8a45e6bd304c6106a1685c3c99.tar.gz
New status fixes
This adds support for roughly-right tracking of submodules (although it does not recurse into submodules to detect internal modifications a la core git), and it adds support for including unmodified files in diff iteration if requested.
Diffstat (limited to 'src')
-rw-r--r--src/diff.c47
-rw-r--r--src/diff_output.c6
-rw-r--r--src/iterator.c5
-rw-r--r--src/status.c12
4 files changed, 52 insertions, 18 deletions
diff --git a/src/diff.c b/src/diff.c
index 469a6c05c..3f8041af2 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -132,7 +132,17 @@ static int diff_delta__from_one(
git_delta_t status,
const git_index_entry *entry)
{
- git_diff_delta *delta = diff_delta__alloc(diff, status, entry->path);
+ git_diff_delta *delta;
+
+ if (status == GIT_DELTA_IGNORED &&
+ (diff->opts.flags & GIT_DIFF_INCLUDE_IGNORED) == 0)
+ return 0;
+
+ if (status == GIT_DELTA_UNTRACKED &&
+ (diff->opts.flags & GIT_DIFF_INCLUDE_UNTRACKED) == 0)
+ return 0;
+
+ delta = diff_delta__alloc(diff, status, entry->path);
GITERR_CHECK_ALLOC(delta);
/* This fn is just for single-sided diffs */
@@ -168,6 +178,10 @@ static int diff_delta__from_two(
{
git_diff_delta *delta;
+ if (status == GIT_DELTA_UNMODIFIED &&
+ (diff->opts.flags & GIT_DIFF_INCLUDE_UNMODIFIED) == 0)
+ return 0;
+
if ((diff->opts.flags & GIT_DIFF_REVERSE) != 0) {
const git_index_entry *temp = old;
old = new;
@@ -320,26 +334,30 @@ static int maybe_modified(
git_diff_list *diff)
{
git_oid noid, *use_noid = NULL;
+ git_delta_t status = GIT_DELTA_MODIFIED;
GIT_UNUSED(old);
/* support "assume unchanged" & "skip worktree" bits */
if ((oitem->flags_extended & GIT_IDXENTRY_INTENT_TO_ADD) != 0 ||
(oitem->flags_extended & GIT_IDXENTRY_SKIP_WORKTREE) != 0)
- return 0;
+ status = GIT_DELTA_UNMODIFIED;
- if (GIT_MODE_TYPE(oitem->mode) != GIT_MODE_TYPE(nitem->mode)) {
+ /* if basic type of file changed, then split into delete and add */
+ else if (GIT_MODE_TYPE(oitem->mode) != GIT_MODE_TYPE(nitem->mode)) {
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 (git_oid_cmp(&oitem->oid, &nitem->oid) == 0 &&
- oitem->mode == nitem->mode)
- return 0;
+ /* if oids and modes match, then file is unmodified */
+ else if (git_oid_cmp(&oitem->oid, &nitem->oid) == 0 &&
+ oitem->mode == nitem->mode)
+ status = GIT_DELTA_UNMODIFIED;
- if (git_oid_iszero(&nitem->oid) && new->type == GIT_ITERATOR_WORKDIR) {
+ /* if we have a workdir item with an unknown oid, check deeper */
+ else if (git_oid_iszero(&nitem->oid) && new->type == GIT_ITERATOR_WORKDIR) {
/* if they files look exactly alike, then we'll assume the same */
if (oitem->file_size == nitem->file_size &&
oitem->ctime.seconds == nitem->ctime.seconds &&
@@ -348,25 +366,28 @@ static int maybe_modified(
oitem->ino == nitem->ino &&
oitem->uid == nitem->uid &&
oitem->gid == nitem->gid)
- return 0;
+ status = GIT_DELTA_UNMODIFIED;
+
+ /* TODO? should we do anything special with submodules? */
+ else if (S_ISGITLINK(nitem->mode))
+ status = GIT_DELTA_UNMODIFIED;
/* TODO: check git attributes so we will not have to read the file
* in if it is marked binary.
*/
- if (oid_for_workdir_item(diff->repo, nitem, &noid) < 0)
+ else if (oid_for_workdir_item(diff->repo, nitem, &noid) < 0)
return -1;
- if (git_oid_cmp(&oitem->oid, &noid) == 0 &&
+ else if (git_oid_cmp(&oitem->oid, &noid) == 0 &&
oitem->mode == nitem->mode)
- return 0;
+ status = GIT_DELTA_UNMODIFIED;
/* store calculated oid so we don't have to recalc later */
use_noid = &noid;
}
- return diff_delta__from_two(
- diff, GIT_DELTA_MODIFIED, oitem, nitem, use_noid);
+ return diff_delta__from_two(diff, status, oitem, nitem, use_noid);
}
static int diff_from_iterators(
diff --git a/src/diff_output.c b/src/diff_output.c
index 638cabca5..f4c214314 100644
--- a/src/diff_output.c
+++ b/src/diff_output.c
@@ -314,7 +314,8 @@ int git_diff_foreach(
git_blob *old_blob = NULL, *new_blob = NULL;
git_map old_data, new_data;
- if (delta->status == GIT_DELTA_UNMODIFIED)
+ if (delta->status == GIT_DELTA_UNMODIFIED &&
+ (diff->opts.flags & GIT_DIFF_INCLUDE_UNMODIFIED) == 0)
continue;
if (delta->status == GIT_DELTA_IGNORED &&
@@ -377,7 +378,8 @@ int git_diff_foreach(
*/
if (git_oid_cmp(&delta->old.oid, &delta->new.oid) == 0) {
delta->status = GIT_DELTA_UNMODIFIED;
- goto cleanup;
+ if ((diff->opts.flags & GIT_DIFF_INCLUDE_UNMODIFIED) == 0)
+ goto cleanup;
}
}
}
diff --git a/src/iterator.c b/src/iterator.c
index cc15b5f67..001bee7b0 100644
--- a/src/iterator.c
+++ b/src/iterator.c
@@ -427,7 +427,12 @@ static int workdir_iterator__update_entry(workdir_iterator *wi)
/* detect submodules */
if (S_ISDIR(wi->entry.mode) &&
git_path_contains(&wi->path, DOT_GIT) == true)
+ {
+ size_t len = strlen(wi->entry.path);
+ assert(wi->entry.path[len - 1] == '/');
+ wi->entry.path[len - 1] = '\0';
wi->entry.mode = S_IFGITLINK;
+ }
return 0;
}
diff --git a/src/status.c b/src/status.c
index eab7c8850..0c7a62254 100644
--- a/src/status.c
+++ b/src/status.c
@@ -137,7 +137,13 @@ int git_status_foreach_ext(
}
memset(&diffopt, 0, sizeof(diffopt));
- diffopt.flags = GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED;
+ 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)
+ diffopt.flags = diffopt.flags | GIT_DIFF_INCLUDE_IGNORED;
+ if ((opts->flags & GIT_STATUS_OPT_INCLUDE_UNMODIFIED) != 0)
+ diffopt.flags = diffopt.flags | GIT_DIFF_INCLUDE_UNMODIFIED;
+ /* TODO: support EXCLUDE_SUBMODULES flag */
if (show != GIT_STATUS_SHOW_WORKDIR_ONLY &&
(err = git_diff_index_to_tree(repo, &diffopt, head, &idx2head)) < 0)
@@ -180,9 +186,9 @@ int git_status_foreach(
{
git_status_options opts;
- opts.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
+ opts.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
opts.flags = GIT_STATUS_OPT_INCLUDE_IGNORED |
- GIT_STATUS_OPT_EXCLUDE_SUBMODULES;
+ GIT_STATUS_OPT_INCLUDE_UNTRACKED;
return git_status_foreach_ext(repo, &opts, callback, payload);
}