예제 #1
0
void test_diff_index__not_in_head_conflicted(void)
{
	const char *a_commit = "26a125ee1bf"; /* the current HEAD */
	git_index_entry theirs = {{0}};
	git_index *index;
	git_diff *diff;
	const git_diff_delta *delta;

	git_tree *a = resolve_commit_oid_to_tree(g_repo, a_commit);

	cl_git_pass(git_repository_index(&index, g_repo));
	cl_git_pass(git_index_read_tree(index, a));

	theirs.path = "file_not_in_head";
	theirs.mode = GIT_FILEMODE_BLOB;
	git_oid_fromstr(&theirs.id, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
	cl_git_pass(git_index_conflict_add(index, NULL, NULL, &theirs));

	cl_git_pass(git_diff_tree_to_index(&diff, g_repo, a, index, NULL));

	cl_assert_equal_i(git_diff_num_deltas(diff), 1);
	delta = git_diff_get_delta(diff, 0);
	cl_assert_equal_i(delta->status, GIT_DELTA_CONFLICTED);

	git_diff_free(diff);
	git_index_free(index);
	git_tree_free(a);
}
예제 #2
0
파일: diff.c 프로젝트: jwes/luagi
int luagi_diff_get_delta( lua_State *L )
{
   git_diff **diff = checkdiff_at( L, 1 );
   int idx = luaL_checkinteger( L, 2 );
   int num = git_diff_num_deltas( *diff );
   if( idx <= 0 || idx > num )
   {
        return ltk_push_error_msg( L, "index out of bounds" );
   }
   idx--;

   const git_diff_delta *delta = git_diff_get_delta( *diff, idx );

   diff_delta_to_table( L, delta );
   return 1; 
}
예제 #3
0
int git_reset_default(
	git_repository *repo,
	const git_object *target,
	const git_strarray* pathspecs)
{
	git_object *commit = NULL;
	git_tree *tree = NULL;
	git_diff *diff = NULL;
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
	size_t i, max_i;
	git_index_entry entry;
	int error;
	git_index *index = NULL;

	assert(pathspecs != NULL && pathspecs->count > 0);

	memset(&entry, 0, sizeof(git_index_entry));

	if ((error = git_repository_index(&index, repo)) < 0)
		goto cleanup;

	if (target) {
		if (git_object_owner(target) != repo) {
			giterr_set(GITERR_OBJECT,
				"%s_default - The given target does not belong to this repository.", ERROR_MSG);
			return -1;
		}

		if ((error = git_object_peel(&commit, target, GIT_OBJECT_COMMIT)) < 0 ||
			(error = git_commit_tree(&tree, (git_commit *)commit)) < 0)
			goto cleanup;
	}

	opts.pathspec = *pathspecs;
	opts.flags = GIT_DIFF_REVERSE;

	if ((error = git_diff_tree_to_index(
		&diff, repo, tree, index, &opts)) < 0)
			goto cleanup;

	for (i = 0, max_i = git_diff_num_deltas(diff); i < max_i; ++i) {
		const git_diff_delta *delta = git_diff_get_delta(diff, i);

		assert(delta->status == GIT_DELTA_ADDED ||
			delta->status == GIT_DELTA_MODIFIED ||
			delta->status == GIT_DELTA_CONFLICTED ||
			delta->status == GIT_DELTA_DELETED);

		error = git_index_conflict_remove(index, delta->old_file.path);
		if (error < 0) {
			if (delta->status == GIT_DELTA_ADDED && error == GIT_ENOTFOUND)
				giterr_clear();
			else
				goto cleanup;
		}

		if (delta->status == GIT_DELTA_DELETED) {
			if ((error = git_index_remove(index, delta->old_file.path, 0)) < 0)
				goto cleanup;
		} else {
			entry.mode = delta->new_file.mode;
			git_oid_cpy(&entry.id, &delta->new_file.id);
			entry.path = (char *)delta->new_file.path;

			if ((error = git_index_add(index, &entry)) < 0)
				goto cleanup;
		}
	}

	error = git_index_write(index);

cleanup:
	git_object_free(commit);
	git_tree_free(tree);
	git_index_free(index);
	git_diff_free(diff);

	return error;
}
예제 #4
0
파일: diff_stats.c 프로젝트: Arhzi/libgit2
int git_diff_stats_to_buf(
	git_buf *out,
	const git_diff_stats *stats,
	git_diff_stats_format_t format,
	size_t width)
{
	int error = 0;
	size_t i;
	const git_diff_delta *delta;

	assert(out && stats);

	if (format & GIT_DIFF_STATS_NUMBER) {
		for (i = 0; i < stats->files_changed; ++i) {
			if ((delta = git_diff_get_delta(stats->diff, i)) == NULL)
				continue;

			error = git_diff_file_stats__number_to_buf(
				out, delta, &stats->filestats[i]);
			if (error < 0)
				return error;
		}
	}

	if (format & GIT_DIFF_STATS_FULL) {
		if (width > 0) {
			if (width > stats->max_name + stats->max_digits + 5)
				width -= (stats->max_name + stats->max_digits + 5);
			if (width < STATS_FULL_MIN_SCALE)
				width = STATS_FULL_MIN_SCALE;
		}
		if (width > stats->max_filestat)
			width = 0;

		for (i = 0; i < stats->files_changed; ++i) {
			if ((delta = git_diff_get_delta(stats->diff, i)) == NULL)
				continue;

			error = git_diff_file_stats__full_to_buf(
				out, delta, &stats->filestats[i], stats, width);
			if (error < 0)
				return error;
		}
	}

	if (format & GIT_DIFF_STATS_FULL || format & GIT_DIFF_STATS_SHORT) {
		git_buf_printf(
			out, " %" PRIuZ " file%s changed",
			stats->files_changed, stats->files_changed != 1 ? "s" : "");

		if (stats->insertions || stats->deletions == 0)
			git_buf_printf(
				out, ", %" PRIuZ " insertion%s(+)",
				stats->insertions, stats->insertions != 1 ? "s" : "");

		if (stats->deletions || stats->insertions == 0)
			git_buf_printf(
				out, ", %" PRIuZ " deletion%s(-)",
				stats->deletions, stats->deletions != 1 ? "s" : "");

		git_buf_putc(out, '\n');

		if (git_buf_oom(out))
			return -1;
	}

	if (format & GIT_DIFF_STATS_INCLUDE_SUMMARY) {
		for (i = 0; i < stats->files_changed; ++i) {
			if ((delta = git_diff_get_delta(stats->diff, i)) == NULL)
				continue;

			error = git_diff_file_stats__summary_to_buf(out, delta);
			if (error < 0)
				return error;
		}
	}

	return error;
}
예제 #5
0
파일: qgit.cpp 프로젝트: bokic/gitmaster
void QGit::commitDiffContent(QString first, QString second, QList<QString> files)
{
    git_commit *first_commit = nullptr, *second_commit = nullptr;
    git_object *first_obj = nullptr, *second_obj = nullptr;
    git_tree *first_tree = nullptr, *second_tree = nullptr;
    const git_diff_delta *delta = nullptr;
    git_repository *repo = nullptr;
    git_patch *patch = nullptr;
    QList<QGitDiffFile> items;
    git_diff *diff = nullptr;
    QGitError error;
    int res = 0;

    try {
        res = git_repository_open(&repo, m_path.absolutePath().toUtf8().constData());
        if (res)
        {
            throw QGitError("git_repository_open", res);
        }

        if (!first.isEmpty())
        {
            res = git_revparse_single(&first_obj, repo, first.toLatin1());
            if (res)
            {
                throw QGitError("git_revparse_single(first)", res);
            }

            res = git_commit_lookup(&first_commit, repo, git_object_id(first_obj));
            if (res)
            {
                throw QGitError("git_commit_lookup(first)", res);
            }

            res = git_commit_tree(&first_tree, first_commit);
            if (res)
            {
                throw QGitError("git_commit_tree(first)", res);
            }
        }

        if (second == "staged")
        {
            git_diff_options options;

            res = git_revparse_single(&first_obj, repo, "HEAD^{tree}");
            if (res)
            {
                throw QGitError("git_revparse_single(staged)", res);
            }

            res = git_tree_lookup(&first_tree, repo, git_object_id(first_obj));
            if (res)
            {
                throw QGitError("git_tree_lookup(staged)", res);
            }

            memset(&options, 0, sizeof(options));
            options.version = GIT_DIFF_OPTIONS_VERSION;
            options.flags = GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_SHOW_UNTRACKED_CONTENT;
            options.context_lines = 3;

            res = git_diff_tree_to_index(&diff, repo, first_tree, nullptr, &options);
            if (res)
            {
                throw QGitError("git_diff_tree_to_index(staged)", res);
            }
        }
        else if (second == "unstaged")
        {
            git_diff_options options;

            memset(&options, 0, sizeof(options));
            options.version = GIT_DIFF_OPTIONS_VERSION;
            options.flags = GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_SHOW_UNTRACKED_CONTENT;
            options.context_lines = 3;

            res = git_diff_index_to_workdir(&diff, repo, nullptr, &options);
            if (res)
            {
                throw QGitError("git_diff_index_to_workdir", res);
            }
        }
        else
        {
            res = git_revparse_single(&second_obj, repo, second.toLatin1());
            if (res)
            {
                throw QGitError("git_revparse_single(second)", res);
            }

            res = git_commit_lookup(&second_commit, repo, git_object_id(second_obj));
            if (res)
            {
                throw QGitError("git_commit_lookup(second)", res);
            }

            res = git_commit_tree(&second_tree, second_commit);
            if (res)
            {
                throw QGitError("git_commit_tree(second)", res);
            }

            res = git_diff_tree_to_tree(&diff, repo, first_tree, second_tree, nullptr);
            if (res)
            {
                throw QGitError("git_diff_tree_to_tree", res);
            }
        }

        size_t _count = git_diff_num_deltas(diff);
        for(size_t c = 0; c < _count; c++)
        {
            delta = git_diff_get_delta(diff, c);

            QGitDiffFile item(delta);

            if (files.contains(item.new_file().path()))
            {
                res = git_patch_from_diff(&patch, diff, c);
                if (res)
                {
                    throw QGitError("git_patch_from_diff", res);
                }

                size_t hunks = git_patch_num_hunks(patch);
                for(size_t  hunk_cnt = 0; hunk_cnt < hunks; hunk_cnt++) {
                    const git_diff_hunk *hunk = nullptr;
                    res = git_patch_get_hunk(&hunk, nullptr, patch, hunk_cnt);
                    if (res)
                    {
                        throw QGitError("git_patch_get_hunk", res);
                    }

                    QGitDiffHunk hunkObj(hunk);

                    const git_diff_line *line = nullptr;

                    int lines = git_patch_num_lines_in_hunk(patch, hunk_cnt);
                    if (lines > 0)
                    {
                        for(int  line_cnt = 0; line_cnt < lines; line_cnt++) {
                            res = git_patch_get_line_in_hunk(&line, patch, hunk_cnt, static_cast<size_t>(line_cnt));
                            if (res)
                            {
                                throw QGitError("git_patch_get_line_in_hunk", res);
                            }

                            hunkObj.addLine(line);
                        }
                    }

                    item.addHunk(hunkObj);
                }

                items.append(item);
            }
        }
    } catch(const QGitError &ex) {
        error = ex;
    }

    emit commitDiffContentReply(first, second, items, error);
}
예제 #6
0
파일: qgit.cpp 프로젝트: bokic/gitmaster
void QGit::commitDiff(QString commitId)
{
    const git_diff_delta *delta = nullptr;
    git_tree *commit_tree = nullptr;
    git_tree *parent_tree = nullptr;
    git_repository *repo = nullptr;
    git_commit *parent = nullptr;
    git_commit *commit = nullptr;
    git_object *obj = nullptr;
    git_diff *diff = nullptr;
    QList<QGitCommitDiffParent> parents;
    QGitSignature commitAuthor, commitCommiter;
    QDateTime commitTime;
    QString commitMessage;
    QGitCommit commitDiff;
    unsigned int parentCount;
    int res = 0;

    QGitError error;

    try {

        res = git_repository_open(&repo, m_path.absolutePath().toUtf8().constData());
        if (res)
        {
            throw QGitError("git_repository_open", res);
        }

        if (commitId.isEmpty())
        {
            commitId = QStringLiteral("HEAD");
        }

        res = git_revparse_single(&obj, repo, commitId.toLatin1());
        if (res)
        {
            throw QGitError("git_revparse_single", res);
        }

        res = git_commit_lookup(&commit, repo, git_object_id(obj));
        if (res)
        {
            throw QGitError("git_commit_lookup", res);
        }

        res = git_commit_tree(&commit_tree, commit);
        if (res)
        {
            throw QGitError("git_commit_tree", res);
        }

        commitAuthor = QGitSignature(QString::fromUtf8(git_commit_author(commit)->name), QString::fromUtf8(git_commit_author(commit)->email), QDateTime::fromMSecsSinceEpoch(git_commit_author(commit)->when.time * 1000));
        commitCommiter = QGitSignature(QString::fromUtf8(git_commit_committer(commit)->name), QString::fromUtf8(git_commit_committer(commit)->email), QDateTime::fromMSecsSinceEpoch(git_commit_committer(commit)->when.time * 1000));

        auto time = git_commit_time(commit);
        auto timeOffset = git_commit_time_offset(commit);
        commitTime = QDateTime::fromMSecsSinceEpoch(time * 1000);
        commitTime.setOffsetFromUtc(timeOffset * 60);

        commitMessage = QString::fromUtf8(git_commit_message(commit));

        parentCount = git_commit_parentcount(commit);

        if (parentCount == 0)
        {
            QGitCommitDiffParent item;

            res = git_diff_tree_to_tree(&diff, repo, nullptr, commit_tree, nullptr);
            if (res)
            {
                throw QGitError("git_diff_tree_to_tree", res);
            }

            size_t _count = git_diff_num_deltas(diff);
            for(size_t c = 0; c < _count; c++)
            {
                delta = git_diff_get_delta(diff, c);

                item.addFile(delta);
            }

            git_diff_free(diff);
            diff = nullptr;

            parents.append(item);
        }
        else
        {
            for(unsigned int c = 0; c < parentCount; c++)
            {
                res = git_commit_parent(&parent, commit, c);
                if (res)
                {
                    throw QGitError("git_commit_parent", res);
                }

                char commit_id[41] = {0, };
                const git_oid *oid = git_commit_id(parent);
                git_oid_tostr(commit_id, 41, oid);
                QGitCommitDiffParent item(commit_id);

                res = git_commit_tree(&parent_tree, parent);
                if (res)
                {
                    throw QGitError("git_commit_tree", res);
                }

                res = git_diff_tree_to_tree(&diff, repo, parent_tree, commit_tree, nullptr);
                if (res)
                {
                    throw QGitError("git_diff_tree_to_tree", res);
                }

                size_t _count = git_diff_num_deltas(diff);
                for(size_t c = 0; c < _count; c++)
                {
                    delta = git_diff_get_delta(diff, c);

                    item.addFile(delta);
                }

                git_diff_free(diff);
                diff = nullptr;

                git_tree_free(parent_tree);
                parent_tree = nullptr;

                git_commit_free(parent);
                parent = nullptr;

                parents.append(item);
            }
        }
    } catch(const QGitError &ex) {
        error = ex;
    }

    commitDiff = QGitCommit(commitId, parents, commitTime, commitAuthor, commitCommiter, commitMessage);

    emit commitDiffReply(commitId, commitDiff, error);

    if (diff)
    {
        git_diff_free(diff);
        diff = nullptr;
    }

    if (parent_tree)
    {
        git_tree_free(parent_tree);
        parent_tree = nullptr;
    }

    if (parent)
    {
        git_commit_free(parent);
        parent = nullptr;
    }

    if (commit_tree)
    {
        git_tree_free(commit_tree);
        commit_tree = nullptr;
    }

    if(commit)
    {
        git_commit_free(commit);
        commit = nullptr;
    }

    if(obj)
    {
        git_object_free(obj);
        obj = nullptr;
    }

    if (repo)
    {
        git_repository_free(repo);
        repo = nullptr;
    }
}
예제 #7
0
static git_blame__origin* find_origin(
		git_blame *blame,
		git_commit *parent,
		git_blame__origin *origin)
{
	git_blame__origin *porigin = NULL;
	git_diff *difflist = NULL;
	git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT;
	git_tree *otree=NULL, *ptree=NULL;

	/* Get the trees from this commit and its parent */
	if (0 != git_commit_tree(&otree, origin->commit) ||
	    0 != git_commit_tree(&ptree, parent))
		goto cleanup;

	/* Configure the diff */
	diffopts.context_lines = 0;
	diffopts.flags = GIT_DIFF_SKIP_BINARY_CHECK;

	/* Check to see if files we're interested have changed */
	diffopts.pathspec.count = blame->paths.length;
	diffopts.pathspec.strings = (char**)blame->paths.contents;
	if (0 != git_diff_tree_to_tree(&difflist, blame->repository, ptree, otree, &diffopts))
			goto cleanup;

	if (!git_diff_num_deltas(difflist)) {
		/* No changes; copy data */
		git_blame__get_origin(&porigin, blame, parent, origin->path);
	} else {
		git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT;
		int i;

		/* Generate a full diff between the two trees */
		git_diff_free(difflist);
		diffopts.pathspec.count = 0;
		if (0 != git_diff_tree_to_tree(&difflist, blame->repository, ptree, otree, &diffopts))
			goto cleanup;

		/* Let diff find renames */
		findopts.flags = GIT_DIFF_FIND_RENAMES;
		if (0 != git_diff_find_similar(difflist, &findopts))
			goto cleanup;

		/* Find one that matches */
		for (i=0; i<(int)git_diff_num_deltas(difflist); i++) {
			const git_diff_delta *delta = git_diff_get_delta(difflist, i);

			if (!git_vector_bsearch(NULL, &blame->paths, delta->new_file.path))
			{
				git_vector_insert_sorted(&blame->paths, (void*)git__strdup(delta->old_file.path),
						paths_on_dup);
				make_origin(&porigin, parent, delta->old_file.path);
			}
		}
	}

cleanup:
	git_diff_free(difflist);
	git_tree_free(otree);
	git_tree_free(ptree);
	return porigin;
}
예제 #8
0
파일: diff.c 프로젝트: ethomson/libgit2
static void *run_index_diffs(void *arg)
{
	int thread = *(int *)arg;
	git_repository *repo;
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
	git_diff *diff = NULL;
	size_t i;
	int exp[4] = { 0, 0, 0, 0 };

	cl_git_pass(git_repository_open(&repo, git_repository_path(_repo)));

	switch (thread & 0x03) {
	case 0: /* diff index to workdir */;
		cl_git_pass(git_diff_index_to_workdir(&diff, repo, NULL, &opts));
		break;
	case 1: /* diff tree 'a' to index */;
		cl_git_pass(git_diff_tree_to_index(&diff, repo, _a, NULL, &opts));
		break;
	case 2: /* diff tree 'b' to index */;
		cl_git_pass(git_diff_tree_to_index(&diff, repo, _b, NULL, &opts));
		break;
	case 3: /* diff index to workdir (explicit index) */;
		{
			git_index *idx;
			cl_git_pass(git_repository_index(&idx, repo));
			cl_git_pass(git_diff_index_to_workdir(&diff, repo, idx, &opts));
			git_index_free(idx);
			break;
		}
	}

	/* keep some diff stats to make sure results are as expected */

	i = git_diff_num_deltas(diff);
	git_atomic_add(&_counts[0], (int32_t)i);
	exp[0] = (int)i;

	while (i > 0) {
		switch (git_diff_get_delta(diff, --i)->status) {
		case GIT_DELTA_MODIFIED: exp[1]++; git_atomic_inc(&_counts[1]); break;
		case GIT_DELTA_ADDED:    exp[2]++; git_atomic_inc(&_counts[2]); break;
		case GIT_DELTA_DELETED:  exp[3]++; git_atomic_inc(&_counts[3]); break;
		default: break;
		}
	}

	switch (thread & 0x03) {
	case 0: case 3:
		cl_assert_equal_i(8, exp[0]); cl_assert_equal_i(4, exp[1]);
		cl_assert_equal_i(0, exp[2]); cl_assert_equal_i(4, exp[3]);
		break;
	case 1:
		cl_assert_equal_i(12, exp[0]); cl_assert_equal_i(3, exp[1]);
		cl_assert_equal_i(7, exp[2]); cl_assert_equal_i(2, exp[3]);
		break;
	case 2:
		cl_assert_equal_i(8, exp[0]); cl_assert_equal_i(3, exp[1]);
		cl_assert_equal_i(3, exp[2]); cl_assert_equal_i(2, exp[3]);
		break;
	}

	git_diff_free(diff);
	git_repository_free(repo);
	git_error_clear();

	return arg;
}