Beispiel #1
0
/**
 * Determines whether or not the working directory has non-committed changes.
 */
static int sync_local_dirty(int *out,
                            git_repository *repo,
                            git_oid *commit_id)
{
    int e = 0;
    git_tree *tree = NULL;
    git_diff *diff = NULL;

    if (git_repository_is_bare(repo))
    {
        *out = 0;
        goto exit;
    }

    git_oid tree_id;
    git_check(sync_get_tree(&tree_id, repo, commit_id));
    git_check(git_tree_lookup(&tree, repo, &tree_id));

    git_diff_options diff_options = GIT_DIFF_OPTIONS_INIT;
    diff_options.flags |= GIT_DIFF_INCLUDE_UNTRACKED;
    git_check(git_diff_tree_to_workdir(&diff, repo, tree, &diff_options));

    *out = git_diff_num_deltas(diff);

exit:
    if (tree)           git_tree_free(tree);
    if (diff)           git_diff_free(diff);
    return e;
}
Beispiel #2
0
PyObject *
Tree_diff(Tree *self, PyObject *args, PyObject *kwds)
{
    git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
    git_diff_list *diff;
    git_tree* tree = NULL;
    git_index* index;
    git_repository *repo;
    int err, empty_tree = 0;
    char *keywords[] = {"obj", "flags", "empty_tree", NULL};

    Diff *py_diff;
    PyObject *py_obj = NULL;

    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oii", keywords,
                                     &py_obj, &opts.flags, &empty_tree))
        return NULL;

    repo = git_tree_owner(self->tree);
    if (py_obj == NULL) {
        if (empty_tree > 0)
            err = git_diff_tree_to_tree(&diff, repo, self->tree, NULL, &opts);
        else
            err = git_diff_tree_to_workdir(&diff, repo, self->tree, &opts);

    } else if (PyObject_TypeCheck(py_obj, &TreeType)) {
        tree = ((Tree *)py_obj)->tree;
        err = git_diff_tree_to_tree(&diff, repo, self->tree, tree, &opts);

    } else if (PyObject_TypeCheck(py_obj, &IndexType)) {
        index = ((Index *)py_obj)->index;
        err = git_diff_tree_to_index(&diff, repo, self->tree, index, &opts);

    } else {
        PyErr_SetObject(PyExc_TypeError, py_obj);
        return NULL;
    }

    if (err < 0)
        return Error_set(err);

    py_diff = PyObject_New(Diff, &DiffType);
    if (py_diff) {
        Py_INCREF(self->repo);
        py_diff->repo = self->repo;
        py_diff->list = diff;
    }

    return (PyObject*)py_diff;
}
Beispiel #3
0
PyObject *
Tree_diff(Tree *self, PyObject *args)
{
    git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
    git_diff_list *diff;
    int err;

    Diff *py_diff;
    PyObject *py_obj = NULL;

    if (!PyArg_ParseTuple(args, "|Oi", &py_obj, &opts.flags))
        return NULL;

    if (py_obj == NULL) {
        err = git_diff_tree_to_workdir(
                &diff,
                self->repo->repo,
                self->tree,
                &opts);
    } else if (PyObject_TypeCheck(py_obj, &TreeType)) {
        err = git_diff_tree_to_tree(
                &diff,
                self->repo->repo,
                self->tree,
                ((Tree *)py_obj)->tree,
                &opts);
    } else if (PyObject_TypeCheck(py_obj, &IndexType)) {
        err = git_diff_tree_to_index(
                &diff,
                self->repo->repo,
                self->tree,
                ((Index *)py_obj)->index,
                &opts);
    } else {
        PyErr_SetObject(PyExc_TypeError, py_obj);
        return NULL;
    }

    if (err < 0)
        return Error_set(err);

    py_diff = PyObject_New(Diff, &DiffType);
    if (py_diff) {
        Py_INCREF(self->repo);
        py_diff->repo = self->repo;
        py_diff->list = diff;
    }

    return (PyObject*)py_diff;
}
Beispiel #4
0
static int build_untracked_tree(
	git_tree **tree_out,
	git_index *index,
	git_commit *i_commit,
	uint32_t flags)
{
	git_tree *i_tree = NULL;
	git_diff_list *diff = NULL;
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
	struct cb_data data = {0};
	int error;

	git_index_clear(index);

	data.index = index;

	if (flags & GIT_STASH_INCLUDE_UNTRACKED) {
		opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED |
			GIT_DIFF_RECURSE_UNTRACKED_DIRS;
		data.include_untracked = true;
	}

	if (flags & GIT_STASH_INCLUDE_IGNORED) {
		opts.flags |= GIT_DIFF_INCLUDE_IGNORED;
		data.include_ignored = true;
	}

	if ((error = git_commit_tree(&i_tree, i_commit)) < 0)
		goto cleanup;

	if ((error = git_diff_tree_to_workdir(
			&diff, git_index_owner(index), i_tree, &opts)) < 0)
		goto cleanup;

	if ((error = git_diff_foreach(
			diff, update_index_cb, NULL, NULL, &data)) < 0)
	{
		if (error == GIT_EUSER)
			error = data.error;
		goto cleanup;
	}

	error = build_tree_from_index(tree_out, index);

cleanup:
	git_diff_list_free(diff);
	git_tree_free(i_tree);
	return error;
}
Beispiel #5
0
PyObject *
Tree_diff_to_workdir(Tree *self, PyObject *args)
{
    git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
    git_diff *diff;
    Repository *py_repo;
    int err;

    if (!PyArg_ParseTuple(args, "|IHH", &opts.flags, &opts.context_lines,
                                        &opts.interhunk_lines))
        return NULL;

    py_repo = self->repo;
    err = git_diff_tree_to_workdir(&diff, py_repo->repo, self->tree, &opts);
    if (err < 0)
        return Error_set(err);

    return wrap_diff(diff, py_repo);
}
Beispiel #6
0
/*
 *  call-seq:
 *    tree.diff_workdir([options]) -> diff
 *
 *  Returns a diff between a tree and the current workdir.
 *
 *  The +tree+ object will be used as the "old file" side of the diff, while the
 *  content of the current workdir will be used for the "new file" side.
 *
 *  See Rugged::Tree#diff for a list of options that can be passed.
 */
static VALUE rb_git_tree_diff_workdir(int argc, VALUE *argv, VALUE self)
{
	git_tree *tree;
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
	git_repository *repo;
	git_diff *diff;
	VALUE owner, rb_options;
	int error;

	rb_scan_args(argc, argv, "00:", &rb_options);
	rugged_parse_diff_options(&opts, rb_options);

	Data_Get_Struct(self, git_tree, tree);
	owner = rugged_owner(self);
	Data_Get_Struct(owner, git_repository, repo);

	error = git_diff_tree_to_workdir(&diff, repo, tree, &opts);

	xfree(opts.pathspec.strings);
	rugged_exception_check(error);

	return rugged_diff_new(rb_cRuggedDiff, owner, diff);
}
Beispiel #7
0
void test_diff_drivers__patterns(void)
{
	git_config *cfg;
	const char *one_sha = "19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13";
	git_tree *one;
	git_diff_list *diff;
	git_diff_patch *patch;
	char *text;
	const char *expected0 = "diff --git a/untimely.txt b/untimely.txt\nindex 9a69d96..57fd0cf 100644\n--- a/untimely.txt\n+++ b/untimely.txt\n@@ -22,3 +22,5 @@ Comes through the blood of the vanguards who\n   dreamed--too soon--it had sounded.\r\n \r\n                 -- Rudyard Kipling\r\n+\r\n+Some new stuff\r\n";
	const char *expected1 = "diff --git a/untimely.txt b/untimely.txt\nindex 9a69d96..57fd0cf 100644\nBinary files a/untimely.txt and b/untimely.txt differ\n";
	const char *expected2 = "diff --git a/untimely.txt b/untimely.txt\nindex 9a69d96..57fd0cf 100644\n--- a/untimely.txt\n+++ b/untimely.txt\n@@ -22,3 +22,5 @@ Heaven delivers on earth the Hour that cannot be\n   dreamed--too soon--it had sounded.\r\n \r\n                 -- Rudyard Kipling\r\n+\r\n+Some new stuff\r\n";

	g_repo = cl_git_sandbox_init("renames");

	one = resolve_commit_oid_to_tree(g_repo, one_sha);

	/* no diff */

	cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL));
	cl_assert_equal_i(0, (int)git_diff_num_deltas(diff));
	git_diff_list_free(diff);

	/* default diff */

	cl_git_append2file("renames/untimely.txt", "\r\nSome new stuff\r\n");

	cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL));
	cl_assert_equal_i(1, (int)git_diff_num_deltas(diff));

	cl_git_pass(git_diff_get_patch(&patch, NULL, diff, 0));
	cl_git_pass(git_diff_patch_to_str(&text, patch));
	cl_assert_equal_s(expected0, text);

	git__free(text);
	git_diff_patch_free(patch);
	git_diff_list_free(diff);

	/* attribute diff set to false */

	cl_git_rewritefile("renames/.gitattributes", "untimely.txt -diff\n");

	cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL));
	cl_assert_equal_i(1, (int)git_diff_num_deltas(diff));

	cl_git_pass(git_diff_get_patch(&patch, NULL, diff, 0));
	cl_git_pass(git_diff_patch_to_str(&text, patch));
	cl_assert_equal_s(expected1, text);

	git__free(text);
	git_diff_patch_free(patch);
	git_diff_list_free(diff);

	/* attribute diff set to unconfigured value (should use default) */

	cl_git_rewritefile("renames/.gitattributes", "untimely.txt diff=kipling0\n");

	cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL));
	cl_assert_equal_i(1, (int)git_diff_num_deltas(diff));

	cl_git_pass(git_diff_get_patch(&patch, NULL, diff, 0));
	cl_git_pass(git_diff_patch_to_str(&text, patch));
	cl_assert_equal_s(expected0, text);

	git__free(text);
	git_diff_patch_free(patch);
	git_diff_list_free(diff);

	/* let's define that driver */

	cl_git_pass(git_repository_config(&cfg, g_repo));
	cl_git_pass(git_config_set_bool(cfg, "diff.kipling0.binary", 1));
	git_config_free(cfg);

	cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL));
	cl_assert_equal_i(1, (int)git_diff_num_deltas(diff));

	cl_git_pass(git_diff_get_patch(&patch, NULL, diff, 0));
	cl_git_pass(git_diff_patch_to_str(&text, patch));
	cl_assert_equal_s(expected1, text);

	git__free(text);
	git_diff_patch_free(patch);
	git_diff_list_free(diff);

	/* let's use a real driver with some regular expressions */

	git_diff_driver_registry_free(g_repo->diff_drivers);
	g_repo->diff_drivers = NULL;

	cl_git_pass(git_repository_config(&cfg, g_repo));
	cl_git_pass(git_config_set_bool(cfg, "diff.kipling0.binary", 0));
	cl_git_pass(git_config_set_string(cfg, "diff.kipling0.xfuncname", "^H"));
	git_config_free(cfg);

	cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL));
	cl_assert_equal_i(1, (int)git_diff_num_deltas(diff));

	cl_git_pass(git_diff_get_patch(&patch, NULL, diff, 0));
	cl_git_pass(git_diff_patch_to_str(&text, patch));
	cl_assert_equal_s(expected2, text);

	git__free(text);
	git_diff_patch_free(patch);
	git_diff_list_free(diff);

	git_tree_free(one);
}
Beispiel #8
0
int lg2_diff(git_repository *repo, int argc, char *argv[])
{
	git_tree *t1 = NULL, *t2 = NULL;
	git_diff *diff;
	struct opts o = {
		GIT_DIFF_OPTIONS_INIT, GIT_DIFF_FIND_OPTIONS_INIT,
		-1, 0, 0, GIT_DIFF_FORMAT_PATCH, NULL, NULL, "."
	};

	parse_opts(&o, argc, argv);

	/**
	 * Possible argument patterns:
	 *
	 *  * &lt;sha1&gt; &lt;sha2&gt;
	 *  * &lt;sha1&gt; --cached
	 *  * &lt;sha1&gt;
	 *  * --cached
	 *  * --nocache (don't use index data in diff at all)
	 *  * nothing
	 *
	 * Currently ranged arguments like &lt;sha1&gt;..&lt;sha2&gt; and &lt;sha1&gt;...&lt;sha2&gt;
	 * are not supported in this example
	 */

	if (o.treeish1)
		treeish_to_tree(&t1, repo, o.treeish1);
	if (o.treeish2)
		treeish_to_tree(&t2, repo, o.treeish2);

	if (t1 && t2)
		check_lg2(
			git_diff_tree_to_tree(&diff, repo, t1, t2, &o.diffopts),
			"diff trees", NULL);
	else if (o.cache != CACHE_NORMAL) {
		if (!t1)
			treeish_to_tree(&t1, repo, "HEAD");

		if (o.cache == CACHE_NONE)
			check_lg2(
				git_diff_tree_to_workdir(&diff, repo, t1, &o.diffopts),
				"diff tree to working directory", NULL);
		else
			check_lg2(
				git_diff_tree_to_index(&diff, repo, t1, NULL, &o.diffopts),
				"diff tree to index", NULL);
	}
	else if (t1)
		check_lg2(
			git_diff_tree_to_workdir_with_index(&diff, repo, t1, &o.diffopts),
			"diff tree to working directory", NULL);
	else
		check_lg2(
			git_diff_index_to_workdir(&diff, repo, NULL, &o.diffopts),
			"diff index to working directory", NULL);

	/** Apply rename and copy detection if requested. */

	if ((o.findopts.flags & GIT_DIFF_FIND_ALL) != 0)
		check_lg2(
			git_diff_find_similar(diff, &o.findopts),
			"finding renames and copies", NULL);

	/** Generate simple output using libgit2 display helper. */

	if (!o.output)
		o.output = OUTPUT_DIFF;

	if (o.output != OUTPUT_DIFF)
		diff_print_stats(diff, &o);

	if ((o.output & OUTPUT_DIFF) != 0) {
		if (o.color >= 0)
			fputs(colors[0], stdout);

		check_lg2(
			git_diff_print(diff, o.format, color_printer, &o.color),
			"displaying diff", NULL);

		if (o.color >= 0)
			fputs(colors[0], stdout);
	}

	/** Cleanup before exiting. */
	git_diff_free(diff);
	git_tree_free(t1);
	git_tree_free(t2);

	return 0;
}