Commit e9238687 by Vicent Marti

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/
parent b4d757c0
......@@ -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_index_recursive(git_tree *tree, git_index *index, git_tree_diff_cb cb, void *data);
GIT_END_DECL
#endif
......@@ -930,3 +930,101 @@ int git_tree_diff(git_tree *a, git_tree *b, git_tree_diff_cb cb, void *data)
exit:
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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment