mirror of
https://git.proxmox.com/git/libgit2
synced 2025-08-05 14:37:37 +00:00
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.
This commit is contained in:
parent
95340398a1
commit
66142ae031
@ -39,7 +39,8 @@ enum {
|
|||||||
GIT_DIFF_IGNORE_SUBMODULES = (1 << 5),
|
GIT_DIFF_IGNORE_SUBMODULES = (1 << 5),
|
||||||
GIT_DIFF_PATIENCE = (1 << 6),
|
GIT_DIFF_PATIENCE = (1 << 6),
|
||||||
GIT_DIFF_INCLUDE_IGNORED = (1 << 7),
|
GIT_DIFF_INCLUDE_IGNORED = (1 << 7),
|
||||||
GIT_DIFF_INCLUDE_UNTRACKED = (1 << 8)
|
GIT_DIFF_INCLUDE_UNTRACKED = (1 << 8),
|
||||||
|
GIT_DIFF_INCLUDE_UNMODIFIED = (1 << 9)
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -83,14 +83,14 @@ typedef enum {
|
|||||||
* the workdir files are included in the status "show" option.
|
* the workdir files are included in the status "show" option.
|
||||||
* Right now, there is no option to include all files in
|
* Right now, there is no option to include all files in
|
||||||
* directories that are ignored completely.
|
* directories that are ignored completely.
|
||||||
* - GIT_STATUS_OPT_EXCLUDE_UNMODIFIED indicates that callback
|
* - GIT_STATUS_OPT_INCLUDE_UNMODIFIED indicates that callback
|
||||||
* do not need to be made on unmodified files.
|
* should be made even on unmodified files.
|
||||||
* - GIT_STATUS_OPT_EXCLUDE_SUBMODULES indicates that directories
|
* - GIT_STATUS_OPT_EXCLUDE_SUBMODULES indicates that directories
|
||||||
* which appear to be submodules should just be skipped over.
|
* which appear to be submodules should just be skipped over.
|
||||||
*/
|
*/
|
||||||
#define GIT_STATUS_OPT_INCLUDE_UNTRACKED (1 << 0)
|
#define GIT_STATUS_OPT_INCLUDE_UNTRACKED (1 << 0)
|
||||||
#define GIT_STATUS_OPT_INCLUDE_IGNORED (1 << 1)
|
#define GIT_STATUS_OPT_INCLUDE_IGNORED (1 << 1)
|
||||||
#define GIT_STATUS_OPT_EXCLUDE_UNMODIFIED (1 << 2)
|
#define GIT_STATUS_OPT_INCLUDE_UNMODIFIED (1 << 2)
|
||||||
#define GIT_STATUS_OPT_EXCLUDE_SUBMODULES (1 << 3)
|
#define GIT_STATUS_OPT_EXCLUDE_SUBMODULES (1 << 3)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
47
src/diff.c
47
src/diff.c
@ -132,7 +132,17 @@ static int diff_delta__from_one(
|
|||||||
git_delta_t status,
|
git_delta_t status,
|
||||||
const git_index_entry *entry)
|
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);
|
GITERR_CHECK_ALLOC(delta);
|
||||||
|
|
||||||
/* This fn is just for single-sided diffs */
|
/* This fn is just for single-sided diffs */
|
||||||
@ -168,6 +178,10 @@ static int diff_delta__from_two(
|
|||||||
{
|
{
|
||||||
git_diff_delta *delta;
|
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) {
|
if ((diff->opts.flags & GIT_DIFF_REVERSE) != 0) {
|
||||||
const git_index_entry *temp = old;
|
const git_index_entry *temp = old;
|
||||||
old = new;
|
old = new;
|
||||||
@ -320,26 +334,30 @@ static int maybe_modified(
|
|||||||
git_diff_list *diff)
|
git_diff_list *diff)
|
||||||
{
|
{
|
||||||
git_oid noid, *use_noid = NULL;
|
git_oid noid, *use_noid = NULL;
|
||||||
|
git_delta_t status = GIT_DELTA_MODIFIED;
|
||||||
|
|
||||||
GIT_UNUSED(old);
|
GIT_UNUSED(old);
|
||||||
|
|
||||||
/* support "assume unchanged" & "skip worktree" bits */
|
/* support "assume unchanged" & "skip worktree" bits */
|
||||||
if ((oitem->flags_extended & GIT_IDXENTRY_INTENT_TO_ADD) != 0 ||
|
if ((oitem->flags_extended & GIT_IDXENTRY_INTENT_TO_ADD) != 0 ||
|
||||||
(oitem->flags_extended & GIT_IDXENTRY_SKIP_WORKTREE) != 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 ||
|
if (diff_delta__from_one(diff, GIT_DELTA_DELETED, oitem) < 0 ||
|
||||||
diff_delta__from_one(diff, GIT_DELTA_ADDED, nitem) < 0)
|
diff_delta__from_one(diff, GIT_DELTA_ADDED, nitem) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (git_oid_cmp(&oitem->oid, &nitem->oid) == 0 &&
|
/* if oids and modes match, then file is unmodified */
|
||||||
oitem->mode == nitem->mode)
|
else if (git_oid_cmp(&oitem->oid, &nitem->oid) == 0 &&
|
||||||
return 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 they files look exactly alike, then we'll assume the same */
|
||||||
if (oitem->file_size == nitem->file_size &&
|
if (oitem->file_size == nitem->file_size &&
|
||||||
oitem->ctime.seconds == nitem->ctime.seconds &&
|
oitem->ctime.seconds == nitem->ctime.seconds &&
|
||||||
@ -348,25 +366,28 @@ static int maybe_modified(
|
|||||||
oitem->ino == nitem->ino &&
|
oitem->ino == nitem->ino &&
|
||||||
oitem->uid == nitem->uid &&
|
oitem->uid == nitem->uid &&
|
||||||
oitem->gid == nitem->gid)
|
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
|
/* TODO: check git attributes so we will not have to read the file
|
||||||
* in if it is marked binary.
|
* 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;
|
return -1;
|
||||||
|
|
||||||
if (git_oid_cmp(&oitem->oid, &noid) == 0 &&
|
else if (git_oid_cmp(&oitem->oid, &noid) == 0 &&
|
||||||
oitem->mode == nitem->mode)
|
oitem->mode == nitem->mode)
|
||||||
return 0;
|
status = GIT_DELTA_UNMODIFIED;
|
||||||
|
|
||||||
/* store calculated oid so we don't have to recalc later */
|
/* store calculated oid so we don't have to recalc later */
|
||||||
use_noid = &noid;
|
use_noid = &noid;
|
||||||
}
|
}
|
||||||
|
|
||||||
return diff_delta__from_two(
|
return diff_delta__from_two(diff, status, oitem, nitem, use_noid);
|
||||||
diff, GIT_DELTA_MODIFIED, oitem, nitem, use_noid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int diff_from_iterators(
|
static int diff_from_iterators(
|
||||||
|
@ -314,7 +314,8 @@ int git_diff_foreach(
|
|||||||
git_blob *old_blob = NULL, *new_blob = NULL;
|
git_blob *old_blob = NULL, *new_blob = NULL;
|
||||||
git_map old_data, new_data;
|
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;
|
continue;
|
||||||
|
|
||||||
if (delta->status == GIT_DELTA_IGNORED &&
|
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) {
|
if (git_oid_cmp(&delta->old.oid, &delta->new.oid) == 0) {
|
||||||
delta->status = GIT_DELTA_UNMODIFIED;
|
delta->status = GIT_DELTA_UNMODIFIED;
|
||||||
goto cleanup;
|
if ((diff->opts.flags & GIT_DIFF_INCLUDE_UNMODIFIED) == 0)
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -427,7 +427,12 @@ static int workdir_iterator__update_entry(workdir_iterator *wi)
|
|||||||
/* detect submodules */
|
/* detect submodules */
|
||||||
if (S_ISDIR(wi->entry.mode) &&
|
if (S_ISDIR(wi->entry.mode) &&
|
||||||
git_path_contains(&wi->path, DOT_GIT) == true)
|
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;
|
wi->entry.mode = S_IFGITLINK;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
12
src/status.c
12
src/status.c
@ -137,7 +137,13 @@ int git_status_foreach_ext(
|
|||||||
}
|
}
|
||||||
|
|
||||||
memset(&diffopt, 0, sizeof(diffopt));
|
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 &&
|
if (show != GIT_STATUS_SHOW_WORKDIR_ONLY &&
|
||||||
(err = git_diff_index_to_tree(repo, &diffopt, head, &idx2head)) < 0)
|
(err = git_diff_index_to_tree(repo, &diffopt, head, &idx2head)) < 0)
|
||||||
@ -180,9 +186,9 @@ int git_status_foreach(
|
|||||||
{
|
{
|
||||||
git_status_options opts;
|
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 |
|
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);
|
return git_status_foreach_ext(repo, &opts, callback, payload);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user