mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-29 13:52:17 +00:00
tree: recursive diff-index
Signed-off-by: Carlos Martín Nieto <carlos@cmartin.tk> Signed-off-by: Vicent Marti <tanoku@gmail.com> # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # Author: Carlos Martín Nieto <carlos@cmartin.tk> # # On branch development # Your branch is ahead of 'origin/development' by 11 commits. # # Changes to be committed: # (use "git reset HEAD^1 <file>..." to unstage) # # modified: include/git2/tree.h # modified: src/tree.c # modified: tests-clay/clay_main.c # modified: tests-clay/object/tree/diff.c # # Untracked files: # (use "git add <file>..." to include in what will be committed) # # 0001-remote-Cleanup-the-remotes-code.patch # 466.patch # 466.patch.1 # 488.patch # Makefile # libgit2.0.15.0.dylib # libgit2.0.dylib # libgit2.dylib # libgit2_clay # libgit2_test # tests-clay/object/tree/
This commit is contained in:
parent
b4d757c0a8
commit
e923868766
@ -347,6 +347,7 @@ typedef int (*git_tree_diff_cb)(const git_tree_diff_data *ptr, void *data);
|
|||||||
*/
|
*/
|
||||||
int git_tree_diff(git_tree *old, git_tree *newer, git_tree_diff_cb cb, void *data);
|
int git_tree_diff(git_tree *old, git_tree *newer, git_tree_diff_cb cb, void *data);
|
||||||
|
|
||||||
|
int git_tree_diff_index_recursive(git_tree *tree, git_index *index, git_tree_diff_cb cb, void *data);
|
||||||
|
|
||||||
GIT_END_DECL
|
GIT_END_DECL
|
||||||
#endif
|
#endif
|
||||||
|
98
src/tree.c
98
src/tree.c
@ -930,3 +930,101 @@ int git_tree_diff(git_tree *a, git_tree *b, git_tree_diff_cb cb, void *data)
|
|||||||
exit:
|
exit:
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct diff_index_cbdata {
|
||||||
|
git_index *index;
|
||||||
|
unsigned int i;
|
||||||
|
git_tree_diff_cb cb;
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int cmp_tentry_ientry(git_tree_entry *tentry, git_index_entry *ientry)
|
||||||
|
{
|
||||||
|
int cmp;
|
||||||
|
|
||||||
|
cmp = tentry->attr - ientry->mode;
|
||||||
|
if (cmp != 0)
|
||||||
|
return cmp;
|
||||||
|
|
||||||
|
return git_oid_cmp(&tentry->oid, &ientry->oid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void make_tentry(git_tree_entry *tentry, git_index_entry *ientry, git_buf *buf)
|
||||||
|
{
|
||||||
|
memset(tentry, 0x0, sizeof(git_tree_entry));
|
||||||
|
tentry->attr = ientry->mode;
|
||||||
|
git_oid_cpy(&tentry->oid, &ientry->oid);
|
||||||
|
if (buf != NULL) {
|
||||||
|
tentry->filename = buf->ptr;
|
||||||
|
tentry->filename_len = buf->size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int diff_index_cb(const char *root, git_tree_entry *tentry, void *data)
|
||||||
|
{
|
||||||
|
struct diff_index_cbdata *cbdata = (struct diff_index_cbdata *) data;
|
||||||
|
git_index_entry *ientry = git_index_get(cbdata->index, cbdata->i);
|
||||||
|
git_tree_entry fake_entry;
|
||||||
|
git_buf fn_buf = GIT_BUF_INIT;
|
||||||
|
int cmp, error = GIT_SUCCESS;
|
||||||
|
|
||||||
|
if (ENTRY_IS_TREE(tentry))
|
||||||
|
return GIT_SUCCESS;
|
||||||
|
|
||||||
|
git_buf_puts(&fn_buf, root);
|
||||||
|
git_buf_puts(&fn_buf, tentry->filename);
|
||||||
|
|
||||||
|
if (!ientry) {
|
||||||
|
error = signal_deletion(tentry, cbdata->cb, cbdata->data);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Like with 'git diff-index', the index is the right side*/
|
||||||
|
cmp = strcmp(git_buf_cstr(&fn_buf), ientry->path);
|
||||||
|
if (cmp == 0) {
|
||||||
|
cbdata->i++;
|
||||||
|
if (!cmp_tentry_ientry(tentry, ientry))
|
||||||
|
goto exit;
|
||||||
|
/* modification */
|
||||||
|
make_tentry(&fake_entry, ientry, &fn_buf);
|
||||||
|
if ((error = signal_modification(tentry, &fake_entry, cbdata->cb, cbdata->data)) < 0)
|
||||||
|
goto exit;
|
||||||
|
} else if (cmp < 0) {
|
||||||
|
/* deletion */
|
||||||
|
memcpy(&fake_entry, tentry, sizeof(git_tree_entry));
|
||||||
|
fake_entry.filename = fn_buf.ptr;
|
||||||
|
fake_entry.filename_len = fn_buf.size;
|
||||||
|
if ((error = signal_deletion(tentry, cbdata->cb, cbdata->data)) < 0)
|
||||||
|
goto exit;
|
||||||
|
} else {
|
||||||
|
/* addition */
|
||||||
|
cbdata->i++;
|
||||||
|
make_tentry(&fake_entry, ientry, &fn_buf);
|
||||||
|
if ((error = signal_addition(&fake_entry, cbdata->cb, cbdata->data)) < 0)
|
||||||
|
goto exit;
|
||||||
|
/*
|
||||||
|
* The index has an addition. This means that we need to use
|
||||||
|
* the next entry in the index without advancing the tree
|
||||||
|
* walker, so call ourselves with the same tree state.
|
||||||
|
*/
|
||||||
|
if ((error = diff_index_cb(root, tentry, data)) < 0)
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
git_buf_free(&fn_buf);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
int git_tree_diff_index_recursive(git_tree *tree, git_index *index, git_tree_diff_cb cb, void *data)
|
||||||
|
{
|
||||||
|
struct diff_index_cbdata cbdata;
|
||||||
|
char dummy_path[GIT_PATH_MAX];
|
||||||
|
|
||||||
|
cbdata.index = index;
|
||||||
|
cbdata.i = 0;
|
||||||
|
cbdata.cb = cb;
|
||||||
|
cbdata.data = data;
|
||||||
|
|
||||||
|
return tree_walk_post(tree, diff_index_cb, dummy_path, 0, &cbdata);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user