Пример #1
0
void GitRepository::commit(const QString& message)
{
    git_repository* repo = repository();

    {
        git_auto<git_status_list> changes;
        git_eval(git_status_list_new(&changes, repo, NULL));
        if (git_status_list_entrycount(changes) == 0) { return; }
    }

    git_auto<git_index> index;
    git_eval(git_repository_index(&index, repo));

    git_oid tree_id;
    git_eval(git_index_write_tree(&tree_id, index));

    git_auto<git_tree> tree;
    git_eval(git_tree_lookup(&tree, repo, &tree_id));

    git_oid parent_id;
    git_eval(git_reference_name_to_id(&parent_id, repo, "HEAD"));

    git_auto<git_commit> parent;
    git_eval(git_commit_lookup(&parent, repo, &parent_id));

    git_oid commit_id;
    git_signature* sig = signature();
    git_eval(git_commit_create_v(&commit_id, repo, "HEAD", sig, sig, NULL, message.toLocal8Bit(), tree, 1, parent));
}
Пример #2
0
void test_status_worktree__at_head_parent(void)
{
	git_repository *repo = cl_git_sandbox_init("empty_standard_repo");
	git_status_options opts = GIT_STATUS_OPTIONS_INIT;
	git_status_list *statuslist;
	git_tree *parent_tree;
	const git_status_entry *status;

	cl_git_mkfile("empty_standard_repo/file1", "ping");
	stage_and_commit(repo, "file1");

	cl_git_pass(git_repository_head_tree(&parent_tree, repo));

	cl_git_mkfile("empty_standard_repo/file2", "pong");
	stage_and_commit(repo, "file2");

	cl_git_rewritefile("empty_standard_repo/file2", "pyng");

	opts.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
	opts.baseline = parent_tree;
	cl_git_pass(git_status_list_new(&statuslist, repo, &opts));

	cl_assert_equal_sz(1, git_status_list_entrycount(statuslist));
	status = git_status_byindex(statuslist, 0);
	cl_assert(status != NULL);
	cl_assert_equal_s("file2", status->index_to_workdir->old_file.path);
	cl_assert_equal_i(GIT_STATUS_WT_MODIFIED | GIT_STATUS_INDEX_NEW, status->status);

	git_tree_free(parent_tree);
	git_status_list_free(statuslist);
}
Пример #3
0
int lg2_status(git_repository *repo, int argc, char *argv[])
{
	git_status_list *status;
	struct opts o = { GIT_STATUS_OPTIONS_INIT, "." };

	o.statusopt.show  = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
	o.statusopt.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED |
		GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX |
		GIT_STATUS_OPT_SORT_CASE_SENSITIVELY;

	parse_opts(&o, argc, argv);

	if (git_repository_is_bare(repo))
		fatal("Cannot report status on bare repository",
			git_repository_path(repo));

show_status:
	if (o.repeat)
		printf("\033[H\033[2J");

	/**
	 * Run status on the repository
	 *
	 * We use `git_status_list_new()` to generate a list of status
	 * information which lets us iterate over it at our
	 * convenience and extract the data we want to show out of
	 * each entry.
	 *
	 * You can use `git_status_foreach()` or
	 * `git_status_foreach_ext()` if you'd prefer to execute a
	 * callback for each entry. The latter gives you more control
	 * about what results are presented.
	 */
	check_lg2(git_status_list_new(&status, repo, &o.statusopt),
		"Could not get status", NULL);

	if (o.showbranch)
		show_branch(repo, o.format);

	if (o.showsubmod) {
		int submod_count = 0;
		check_lg2(git_submodule_foreach(repo, print_submod, &submod_count),
			"Cannot iterate submodules", o.repodir);
	}

	if (o.format == FORMAT_LONG)
		print_long(status);
	else
		print_short(repo, status);

	git_status_list_free(status);

	if (o.repeat) {
		sleep(o.repeat);
		goto show_status;
	}

	return 0;
}
Пример #4
0
void test_status_worktree__update_stat_cache_0(void)
{
	git_repository *repo = cl_git_sandbox_init("status");
	git_status_options opts = GIT_STATUS_OPTIONS_INIT;
	git_status_list *status;
	git_diff_perfdata perf = GIT_DIFF_PERFDATA_INIT;
	git_index *index;

	opts.flags = GIT_STATUS_OPT_DEFAULTS;

	cl_git_pass(git_status_list_new(&status, repo, &opts));
	check_status0(status);
	cl_git_pass(git_status_list_get_perfdata(&perf, status));
	cl_assert_equal_sz(13 + 3, perf.stat_calls);
	cl_assert_equal_sz(5, perf.oid_calculations);

	git_status_list_free(status);

	/* tick the index so we avoid recalculating racily-clean entries */
	cl_git_pass(git_repository_index__weakptr(&index, repo));
	tick_index(index);

	opts.flags |= GIT_STATUS_OPT_UPDATE_INDEX;

	cl_git_pass(git_status_list_new(&status, repo, &opts));
	check_status0(status);
	cl_git_pass(git_status_list_get_perfdata(&perf, status));
	cl_assert_equal_sz(13 + 3, perf.stat_calls);
	cl_assert_equal_sz(5, perf.oid_calculations);

	git_status_list_free(status);

	opts.flags &= ~GIT_STATUS_OPT_UPDATE_INDEX;

	/* tick again as the index updating from the previous diff might have reset the timestamp */
	tick_index(index);
	cl_git_pass(git_status_list_new(&status, repo, &opts));
	check_status0(status);
	cl_git_pass(git_status_list_get_perfdata(&perf, status));
	cl_assert_equal_sz(13 + 3, perf.stat_calls);
	cl_assert_equal_sz(0, perf.oid_calculations);

	git_status_list_free(status);
}
Пример #5
0
void test_status_ignore__negative_ignores_without_trailing_slash_inside_ignores(void)
{
	git_status_options status_opts = GIT_STATUS_OPTIONS_INIT;
	git_status_list *list;
	int found_parent_file = 0, found_parent_child1_file = 0, found_parent_child2_file = 0;
	size_t i;
	static const char *test_files[] = {
		"empty_standard_repo/parent/file.txt",
		"empty_standard_repo/parent/force.txt",
		"empty_standard_repo/parent/child1/file.txt",
		"empty_standard_repo/parent/child2/file.txt",
		NULL
	};

	make_test_data("empty_standard_repo", test_files);
	cl_git_mkfile(
		"empty_standard_repo/.gitignore",
		"parent/*\n"
		"!parent/force.txt\n"
		"!parent/child1\n"
		"!parent/child2/\n");

	add_one_to_index("parent/force.txt");

	assert_is_ignored("parent/file.txt");
	refute_is_ignored("parent/force.txt");
	refute_is_ignored("parent/child1/file.txt");
	refute_is_ignored("parent/child2/file.txt");

	status_opts.flags = GIT_STATUS_OPT_DEFAULTS;
	cl_git_pass(git_status_list_new(&list, g_repo, &status_opts));
	for (i = 0; i < git_status_list_entrycount(list); i++) {
		const git_status_entry *entry = git_status_byindex(list, i);

		if (!entry->index_to_workdir)
			continue;

		if (!strcmp("parent/file.txt", entry->index_to_workdir->new_file.path))
			found_parent_file = 1;

		if (!strcmp("parent/force.txt", entry->index_to_workdir->new_file.path))
			found_parent_file = 1;

		if (!strcmp("parent/child1/file.txt", entry->index_to_workdir->new_file.path))
			found_parent_child1_file = 1;

		if (!strcmp("parent/child2/file.txt", entry->index_to_workdir->new_file.path))
			found_parent_child2_file = 1;
	}
	git_status_list_free(list);

	cl_assert(found_parent_file);
	cl_assert(found_parent_child1_file);
	cl_assert(found_parent_child2_file);
}
Пример #6
0
void test_index_nsec__status_doesnt_clear_nsecs(void)
{
	git_status_list *statuslist;

	cl_git_pass(git_status_list_new(&statuslist, repo, NULL));

	git_index_read(repo_index, 1);
	cl_assert_equal_b(true, has_nsecs());

	git_status_list_free(statuslist);
}
Пример #7
0
StagedFiles PmrWorkspace::stagedFiles()
{
    // Retrieve and return all current staged files

    StagedFiles res = StagedFiles();
    git_index *index;

    if (git_repository_index(&index, mGitRepository) == GIT_OK) {
        git_status_options statusOptions;

        git_status_init_options(&statusOptions, GIT_STATUS_OPTIONS_VERSION);

        statusOptions.flags =  GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX
                              |GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY;
        statusOptions.show = GIT_STATUS_SHOW_INDEX_ONLY;

        git_status_list *statusList;

        if (git_status_list_new(&statusList, mGitRepository, &statusOptions) == GIT_OK) {
            for (size_t i = 0, iMax = git_status_list_entrycount(statusList); i < iMax; ++i) {
                const git_status_entry *status = git_status_byindex(statusList, i);
                const char *filePath = (status->head_to_index != nullptr)?
                                           status->head_to_index->old_file.path:
                                           (status->index_to_workdir != nullptr)?
                                               status->index_to_workdir->old_file.path:
                                               nullptr;

                if (filePath != nullptr) {
                    if ((status->status & GIT_STATUS_INDEX_TYPECHANGE) != 0) {
                        res << StagedFile(filePath, GIT_STATUS_INDEX_TYPECHANGE);
                    } else if ((status->status & GIT_STATUS_INDEX_RENAMED) != 0) {
                        res << StagedFile(filePath, GIT_STATUS_INDEX_RENAMED);
                    } else if ((status->status & GIT_STATUS_INDEX_DELETED) != 0) {
                        res << StagedFile(filePath, GIT_STATUS_INDEX_DELETED);
                    } else if ((status->status & GIT_STATUS_INDEX_MODIFIED) != 0) {
                        res << StagedFile(filePath, GIT_STATUS_INDEX_MODIFIED);
                    } else if ((status->status & GIT_STATUS_INDEX_NEW) != 0) {
                        res << StagedFile(filePath, GIT_STATUS_INDEX_NEW);
                    }
                }
            }

            git_status_list_free(statusList);
        }

        git_index_free(index);
    }

    return res;
}
Пример #8
0
void test_status_worktree__simple_delete_indexed(void)
{
	git_repository *repo = cl_git_sandbox_init("renames");
	git_status_options opts = GIT_STATUS_OPTIONS_INIT;
	git_status_list *status;

	opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED |
		GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH |
		GIT_STATUS_OPT_EXCLUDE_SUBMODULES |
		GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS;

	cl_git_pass(git_status_list_new(&status, repo, &opts));
	cl_assert_equal_sz(0, git_status_list_entrycount(status));
	git_status_list_free(status);

	cl_must_pass(p_unlink("renames/untimely.txt"));

	cl_git_pass(git_status_list_new(&status, repo, &opts));
	cl_assert_equal_sz(1, git_status_list_entrycount(status));
	cl_assert_equal_i(
		GIT_STATUS_WT_DELETED, git_status_byindex(status, 0)->status);
	git_status_list_free(status);
}
Пример #9
0
void QGit::status()
{
    git_repository *repo = nullptr;
    git_status_list *list = nullptr;
    QMap<git_status_t, int> items;
    size_t index = 0;
    int res = 0;

    QGitError error;

    try {

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

        res = git_status_list_new(&list, repo, nullptr);
        if (res)
        {
            throw QGitError("git_status_list_new", res);
        }

        while(const git_status_entry *item = git_status_byindex(list, index))
        {
            items[item->status]++;

            index++;
        }

    } catch(const QGitError & ex) {
        error = ex;
    }

    emit statusReply(items, error);

    if (list)
    {
        git_status_list_free(list);
        list = nullptr;
    }

    if (repo)
    {
        git_repository_free(repo);
        repo = nullptr;
    }
}
Пример #10
0
PyObject *
Repository_status(Repository *self)
{
    PyObject *dict;
    int err;
    size_t len, i;
    git_status_list *list;

    dict = PyDict_New();
    if (dict == NULL)
        return NULL;

    err = git_status_list_new(&list, self->repo, NULL);
    if (err < 0)
        return Error_set(err);

    len = git_status_list_entrycount(list);
    for (i = 0; i < len; i++) {
        const git_status_entry *entry;
        const char *path;
        PyObject *status;

        entry = git_status_byindex(list, i);
        if (entry == NULL)
            goto error;

        /* We need to choose one of the strings */
        if (entry->head_to_index)
            path = entry->head_to_index->old_file.path;
        else
            path = entry->index_to_workdir->old_file.path;
        status = PyLong_FromLong((long) entry->status);

        err = PyDict_SetItemString(dict, path, status);
        Py_CLEAR(status);

        if (err < 0)
            goto error;

    }

    git_status_list_free(list);
    return dict;

error:
    git_status_list_free(list);
    Py_CLEAR(dict);
    return NULL;
}
Пример #11
0
void test_rebase_merge__next(void)
{
	git_rebase *rebase;
	git_reference *branch_ref, *upstream_ref;
	git_annotated_commit *branch_head, *upstream_head;
	git_rebase_operation *rebase_operation;
	git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
	git_status_list *status_list;
	const git_status_entry *status_entry;
	git_oid pick_id, file1_id;

	checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;

	cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef"));
	cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master"));

	cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref));
	cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref));

	cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, NULL));

	cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts));

	git_oid_fromstr(&pick_id, "da9c51a23d02d931a486f45ad18cda05cf5d2b94");

	cl_assert_equal_i(GIT_REBASE_OPERATION_PICK, rebase_operation->type);
	cl_assert_equal_oid(&pick_id, &rebase_operation->id);
	cl_assert_equal_file("da9c51a23d02d931a486f45ad18cda05cf5d2b94\n", 41, "rebase/.git/rebase-merge/current");
	cl_assert_equal_file("1\n", 2, "rebase/.git/rebase-merge/msgnum");

	cl_git_pass(git_status_list_new(&status_list, repo, NULL));
	cl_assert_equal_i(1, git_status_list_entrycount(status_list));
	cl_assert(status_entry = git_status_byindex(status_list, 0));

	cl_assert_equal_s("beef.txt", status_entry->head_to_index->new_file.path);

	git_oid_fromstr(&file1_id, "8d95ea62e621f1d38d230d9e7d206e41096d76af");
	cl_assert_equal_oid(&file1_id, &status_entry->head_to_index->new_file.id);

	git_status_list_free(status_list);
	git_annotated_commit_free(branch_head);
	git_annotated_commit_free(upstream_head);
	git_reference_free(branch_ref);
	git_reference_free(upstream_ref);
	git_rebase_free(rebase);
}
Пример #12
0
/**
 * Check for any changes in index
 *
 * @param repository The repository
 * @return 0 if ok, else error code.
 */
static int git2r_any_changes_in_index(git_repository *repository)
{
    int err;
    int changes_in_index = 0;
    size_t i, count;
    git_status_list *status = NULL;
    git_status_options opts = GIT_STATUS_OPTIONS_INIT;
    opts.show  = GIT_STATUS_SHOW_INDEX_ONLY;

    err = git_status_list_new(&status, repository, &opts);
    if (GIT_OK != err)
        goto cleanup;

    count = git_status_list_entrycount(status);
    for (i = 0; i < count; ++i) {
        const git_status_entry *s = git_status_byindex(status, i);

        if (s->status == GIT_STATUS_CURRENT)
            continue;

        if (s->status & GIT_STATUS_INDEX_NEW)
            changes_in_index = 1;
        else if (s->status & GIT_STATUS_INDEX_MODIFIED)
            changes_in_index = 1;
        else if (s->status & GIT_STATUS_INDEX_DELETED)
            changes_in_index = 1;
        else if (s->status & GIT_STATUS_INDEX_RENAMED)
            changes_in_index = 1;
        else if (s->status & GIT_STATUS_INDEX_TYPECHANGE)
            changes_in_index = 1;

        if (changes_in_index)
            break;
    }

    if (!changes_in_index) {
        giterr_set_str(GITERR_NONE, git2r_err_nothing_added_to_commit);
        err = GIT_ERROR;
    }

cleanup:
    if (status)
        git_status_list_free(status);

    return err;
}
Пример #13
0
void test_status_worktree__conflict_has_no_oid(void)
{
	git_repository *repo = cl_git_sandbox_init("status");
	git_index *index;
	git_index_entry entry = {{0}};
	git_status_list *statuslist;
	const git_status_entry *status;
	git_oid zero_id = {{0}};

	entry.mode = 0100644;
	entry.path = "modified_file";
	git_oid_fromstr(&entry.id, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");

	cl_git_pass(git_repository_index(&index, repo));
	cl_git_pass(git_index_conflict_add(index, &entry, &entry, &entry));

	git_status_list_new(&statuslist, repo, NULL);

	cl_assert_equal_i(16, git_status_list_entrycount(statuslist));

	status = git_status_byindex(statuslist, 2);

	cl_assert_equal_i(GIT_STATUS_CONFLICTED, status->status);
	cl_assert_equal_s("modified_file", status->head_to_index->old_file.path);
	cl_assert(!git_oid_equal(&zero_id, &status->head_to_index->old_file.id));
	cl_assert(0 != status->head_to_index->old_file.mode);
	cl_assert_equal_s("modified_file", status->head_to_index->new_file.path);
	cl_assert_equal_oid(&zero_id, &status->head_to_index->new_file.id);
	cl_assert_equal_i(0, status->head_to_index->new_file.mode);
	cl_assert_equal_i(0, status->head_to_index->new_file.size);

	cl_assert_equal_s("modified_file", status->index_to_workdir->old_file.path);
	cl_assert_equal_oid(&zero_id, &status->index_to_workdir->old_file.id);
	cl_assert_equal_i(0, status->index_to_workdir->old_file.mode);
	cl_assert_equal_i(0, status->index_to_workdir->old_file.size);
	cl_assert_equal_s("modified_file", status->index_to_workdir->new_file.path);
	cl_assert(
		!git_oid_equal(&zero_id, &status->index_to_workdir->new_file.id) ||
		!(status->index_to_workdir->new_file.flags & GIT_DIFF_FLAG_VALID_ID));
	cl_assert(0 != status->index_to_workdir->new_file.mode);
	cl_assert(0 != status->index_to_workdir->new_file.size);

	git_index_free(index);
	git_status_list_free(statuslist);
}
Пример #14
0
static void test_abort(git_annotated_commit *branch, git_annotated_commit *onto)
{
	git_rebase *rebase;
	git_reference *head_ref, *branch_ref = NULL;
	git_signature *signature;
	git_status_list *statuslist;
	git_reflog *reflog;
	const git_reflog_entry *reflog_entry;

	cl_git_pass(git_rebase_open(&rebase, repo));
	cl_git_pass(git_signature_new(&signature, "Rebaser", "*****@*****.**", 1404157834, -400));
	cl_git_pass(git_rebase_abort(rebase, signature));

	cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo));

	/* Make sure the refs are updated appropriately */
	cl_git_pass(git_reference_lookup(&head_ref, repo, "HEAD"));

	if (branch->ref_name == NULL)
		cl_assert_equal_oid(git_annotated_commit_id(branch), git_reference_target(head_ref));
	else {
		cl_assert_equal_s("refs/heads/beef", git_reference_symbolic_target(head_ref));
		cl_git_pass(git_reference_lookup(&branch_ref, repo, git_reference_symbolic_target(head_ref)));
		cl_assert_equal_oid(git_annotated_commit_id(branch), git_reference_target(branch_ref));
	}

	git_status_list_new(&statuslist, repo, NULL);
	cl_assert_equal_i(0, git_status_list_entrycount(statuslist));
	git_status_list_free(statuslist);

	/* Make sure the reflogs are updated appropriately */
	cl_git_pass(git_reflog_read(&reflog, repo, "HEAD"));

	cl_assert(reflog_entry = git_reflog_entry_byindex(reflog, 0));
	cl_assert_equal_oid(git_annotated_commit_id(onto), git_reflog_entry_id_old(reflog_entry));
	cl_assert_equal_oid(git_annotated_commit_id(branch), git_reflog_entry_id_new(reflog_entry));
	cl_assert_equal_s("rebase: aborting", git_reflog_entry_message(reflog_entry));

	git_reflog_free(reflog);
	git_reference_free(head_ref);
	git_reference_free(branch_ref);
	git_signature_free(signature);
	git_rebase_free(rebase);
}
Пример #15
0
/* A repo that has a HEAD (even a properly born HEAD that peels to
 * a commit) but no index should be treated as if it's an empty baseline
 */
void test_checkout_tree__baseline_is_empty_when_no_index(void)
{
	git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
	git_reference *head;
	git_object *obj;
	git_status_list *status;
	size_t conflicts = 0;

	assert_on_branch(g_repo, "master");
	cl_git_pass(git_repository_head(&head, g_repo));
	cl_git_pass(git_reference_peel(&obj, head, GIT_OBJ_COMMIT));

	cl_git_pass(git_reset(g_repo, obj, GIT_RESET_HARD, NULL));

	cl_must_pass(p_unlink("testrepo/.git/index"));

	/* for a safe checkout, we should have checkout conflicts with
	 * the existing untracked files.
	 */
	opts.checkout_strategy &= ~GIT_CHECKOUT_FORCE;
	opts.notify_flags = GIT_CHECKOUT_NOTIFY_CONFLICT;
	opts.notify_cb = checkout_conflict_count_cb;
	opts.notify_payload = &conflicts;

	cl_git_fail_with(GIT_ECONFLICT, git_checkout_tree(g_repo, obj, &opts));
	cl_assert_equal_i(4, conflicts);

	/* but force should succeed and update the index */
	opts.checkout_strategy |= GIT_CHECKOUT_FORCE;
	cl_git_pass(git_checkout_tree(g_repo, obj, &opts));

	cl_git_pass(git_status_list_new(&status, g_repo, NULL));
	cl_assert_equal_i(0, git_status_list_entrycount(status));
	git_status_list_free(status);

	git_object_free(obj);
	git_reference_free(head);
}
Пример #16
0
void test_status_ignore__negative_ignores_in_slash_star(void)
{
	git_status_options status_opts = GIT_STATUS_OPTIONS_INIT;
	git_status_list *list;
	int found_look_ma = 0, found_what_about = 0;
	size_t i;
	static const char *test_files[] = {
		"empty_standard_repo/bin/look-ma.txt",
		"empty_standard_repo/bin/what-about-me.txt",
		NULL
	};

	make_test_data("empty_standard_repo", test_files);
	cl_git_mkfile(
		"empty_standard_repo/.gitignore",
		"bin/*\n"
		"!bin/w*\n");

	assert_is_ignored("bin/look-ma.txt");
	refute_is_ignored("bin/what-about-me.txt");

	status_opts.flags = GIT_STATUS_OPT_DEFAULTS;
	cl_git_pass(git_status_list_new(&list, g_repo, &status_opts));
	for (i = 0; i < git_status_list_entrycount(list); i++) {
		const git_status_entry *entry = git_status_byindex(list, i);

		if (!strcmp("bin/look-ma.txt", entry->index_to_workdir->new_file.path))
			found_look_ma = 1;

		if (!strcmp("bin/what-about-me.txt", entry->index_to_workdir->new_file.path))
			found_what_about = 1;
	}
	git_status_list_free(list);

	cl_assert(found_look_ma);
	cl_assert(found_what_about);
}
Пример #17
0
/**
 * Get state of the repository working directory and the staging area.
 *
 * @param repo S4 class git_repository
 * @return VECXSP with status
 */
SEXP git2r_status_list(
    SEXP repo,
    SEXP staged,
    SEXP unstaged,
    SEXP untracked,
    SEXP ignored)
{
    int err;
    size_t i=0, count;
    SEXP list, list_names;
    git_repository *repository;
    git_status_list *status_list = NULL;
    git_status_options opts = GIT_STATUS_OPTIONS_INIT;

    if (git2r_error_check_logical_arg(staged)
        || git2r_error_check_logical_arg(unstaged)
        || git2r_error_check_logical_arg(untracked)
        || git2r_error_check_logical_arg(ignored))
        error("Invalid arguments to git2r_status_list");

    repository = git2r_repository_open(repo);
    if (!repository)
        error(git2r_err_invalid_repository);

    opts.show  = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
    opts.flags = GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX |
        GIT_STATUS_OPT_SORT_CASE_SENSITIVELY;

    if (LOGICAL(untracked)[0])
        opts.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED;
    if (LOGICAL(ignored)[0])
        opts.flags |= GIT_STATUS_OPT_INCLUDE_IGNORED;
    err = git_status_list_new(&status_list, repository, &opts);
    if (err < 0)
        goto cleanup;

    count = LOGICAL(staged)[0] +
        LOGICAL(unstaged)[0] +
        LOGICAL(untracked)[0] +
        LOGICAL(ignored)[0];

    PROTECT(list = allocVector(VECSXP, count));
    PROTECT(list_names = allocVector(STRSXP, count));

    if (LOGICAL(staged)[0]) {
        SET_STRING_ELT(list_names, i, mkChar("staged"));
        git2r_status_list_staged(list, i, status_list);
        i++;
    }

    if (LOGICAL(unstaged)[0]) {
        SET_STRING_ELT(list_names, i, mkChar("unstaged"));
        git2r_status_list_unstaged(list, i, status_list);
        i++;
    }

    if (LOGICAL(untracked)[0]) {
        SET_STRING_ELT(list_names, i, mkChar("untracked"));
        git2r_status_list_untracked(list, i, status_list);
        i++;
    }

    if (LOGICAL(ignored)[0]) {
        SET_STRING_ELT(list_names, i, mkChar("ignored"));
        git2r_status_list_ignored(list, i, status_list);
    }

    setAttrib(list, R_NamesSymbol, list_names);

cleanup:
    if (status_list)
        git_status_list_free(status_list);

    if (repository)
        git_repository_free(repository);

    UNPROTECT(2);

    if (err < 0)
        error("Error: %s\n", giterr_last()->message);

    return list;
}
Пример #18
0
void test_rebase_merge__next_with_conflicts(void)
{
	git_rebase *rebase;
	git_reference *branch_ref, *upstream_ref;
	git_annotated_commit *branch_head, *upstream_head;
	git_rebase_operation *rebase_operation;
	git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
	git_status_list *status_list;
	const git_status_entry *status_entry;
	git_oid pick_id;

	const char *expected_merge =
"ASPARAGUS SOUP.\n"
"\n"
"<<<<<<< master\n"
"TAKE FOUR LARGE BUNCHES of asparagus, scrape it nicely, cut off one inch\n"
"OF THE TOPS, and lay them in water, chop the stalks and put them on the\n"
"FIRE WITH A PIECE OF BACON, a large onion cut up, and pepper and salt;\n"
"ADD TWO QUARTS OF WATER, boil them till the stalks are quite soft, then\n"
"PULP THEM THROUGH A SIEVE, and strain the water to it, which must be put\n"
"=======\n"
"Take four large bunches of asparagus, scrape it nicely, CUT OFF ONE INCH\n"
"of the tops, and lay them in water, chop the stalks and PUT THEM ON THE\n"
"fire with a piece of bacon, a large onion cut up, and pepper and salt;\n"
"add two quarts of water, boil them till the stalks are quite soft, then\n"
"pulp them through a sieve, and strain the water to it, which must be put\n"
">>>>>>> Conflicting modification 1 to asparagus\n"
"back in the pot; put into it a chicken cut up, with the tops of\n"
"asparagus which had been laid by, boil it until these last articles are\n"
"sufficiently done, thicken with flour, butter and milk, and serve it up.\n";

	checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;

	cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/asparagus"));
	cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master"));

	cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref));
	cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref));

	cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, NULL));

	cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts));

	git_oid_fromstr(&pick_id, "33f915f9e4dbd9f4b24430e48731a59b45b15500");

	cl_assert_equal_i(GIT_REBASE_OPERATION_PICK, rebase_operation->type);
	cl_assert_equal_oid(&pick_id, &rebase_operation->id);
	cl_assert_equal_file("33f915f9e4dbd9f4b24430e48731a59b45b15500\n", 41, "rebase/.git/rebase-merge/current");
	cl_assert_equal_file("1\n", 2, "rebase/.git/rebase-merge/msgnum");

	cl_git_pass(git_status_list_new(&status_list, repo, NULL));
	cl_assert_equal_i(1, git_status_list_entrycount(status_list));
	cl_assert(status_entry = git_status_byindex(status_list, 0));

	cl_assert_equal_s("asparagus.txt", status_entry->head_to_index->new_file.path);

	cl_assert_equal_file(expected_merge, strlen(expected_merge), "rebase/asparagus.txt");

	git_status_list_free(status_list);
	git_annotated_commit_free(branch_head);
	git_annotated_commit_free(upstream_head);
	git_reference_free(branch_ref);
	git_reference_free(upstream_ref);
	git_rebase_free(rebase);
}
Пример #19
0
void test_rebase_inmemory__can_resolve_conflicts(void)
{
	git_rebase *rebase;
	git_reference *branch_ref, *upstream_ref;
	git_annotated_commit *branch_head, *upstream_head;
	git_rebase_operation *rebase_operation;
	git_status_list *status_list;
	git_oid pick_id, commit_id, expected_commit_id;
	git_signature *signature;
	git_index *repo_index;
	git_index_entry resolution = {{0}};
	git_rebase_options opts = GIT_REBASE_OPTIONS_INIT;

	cl_git_pass(git_signature_new(&signature,
		"Rebaser", "*****@*****.**", 1405694510, 0));

	opts.inmemory = true;

	cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/asparagus"));
	cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master"));

	cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref));
	cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref));

	cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, &opts));

	cl_git_pass(git_rebase_next(&rebase_operation, rebase));

	git_oid_fromstr(&pick_id, "33f915f9e4dbd9f4b24430e48731a59b45b15500");

	cl_assert_equal_i(GIT_REBASE_OPERATION_PICK, rebase_operation->type);
	cl_assert_equal_oid(&pick_id, &rebase_operation->id);

	/* ensure that we did not do anything stupid to the workdir or repo index */
	cl_git_pass(git_repository_index(&repo_index, repo));
	cl_assert(!git_index_has_conflicts(repo_index));

	cl_git_pass(git_status_list_new(&status_list, repo, NULL));
	cl_assert_equal_i(0, git_status_list_entrycount(status_list));

	/* but that the index returned from rebase does have conflicts */
	cl_assert(git_index_has_conflicts(rebase_operation->index));

	cl_git_fail_with(GIT_EUNMERGED, git_rebase_commit(&commit_id, rebase, NULL, signature, NULL, NULL));

	/* ensure that we can work with the in-memory index to resolve the conflict */
	resolution.path = "asparagus.txt";
	resolution.mode = GIT_FILEMODE_BLOB;
	git_oid_fromstr(&resolution.id, "414dfc71ead79c07acd4ea47fecf91f289afc4b9");
	cl_git_pass(git_index_conflict_remove(rebase_operation->index, "asparagus.txt"));
	cl_git_pass(git_index_add(rebase_operation->index, &resolution));

	/* and finally create a commit for the resolved rebase operation */
	cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature, NULL, NULL));

	cl_git_pass(git_oid_fromstr(&expected_commit_id, "db7af47222181e548810da2ab5fec0e9357c5637"));
	cl_assert_equal_oid(&commit_id, &expected_commit_id);

	git_signature_free(signature);
	git_status_list_free(status_list);
	git_annotated_commit_free(branch_head);
	git_annotated_commit_free(upstream_head);
	git_reference_free(branch_ref);
	git_reference_free(upstream_ref);
	git_index_free(repo_index);
	git_rebase_free(rebase);
}
Пример #20
0
void PmrWorkspace::refreshStatus()
{
    // Keep track of our 'old' file nodes

    PmrWorkspaceFileNodes oldFileNodes = mRepositoryStatusMap.values();

    // Refresh our status

    mStagedCount = 0;
    mUnstagedCount = 0;

    mRepositoryStatusMap.clear();

    if (isOpen()) {
        git_status_options statusOptions;

        git_status_init_options(&statusOptions, GIT_STATUS_OPTIONS_VERSION);

        statusOptions.flags =  GIT_STATUS_OPT_INCLUDE_UNTRACKED
                              |GIT_STATUS_OPT_INCLUDE_UNMODIFIED
                              |GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX
                              |GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY
                              |GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS;
        statusOptions.show  = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;

        git_status_list *statusList;

        if (git_status_list_new(&statusList, mGitRepository, &statusOptions) == GIT_OK) {
            // Go through the different entries and keep track of every single
            // one of them in mRepositoryStatusMap, as well as update
            // mStagedCount and mUnstagedCount, if needed

            for (size_t i = 0, iMax = git_status_list_entrycount(statusList); i < iMax; ++i) {
                const git_status_entry *status = git_status_byindex(statusList, i);
                const char *filePath = (status->head_to_index != nullptr)?
                                           status->head_to_index->old_file.path:
                                           (status->index_to_workdir != nullptr)?
                                               status->index_to_workdir->old_file.path:
                                               nullptr;

                if (filePath != nullptr) {
                    CharPair statusChars = gitStatusChars(status->status);

                    if (statusChars.first != ' ') {
                        ++mStagedCount;
                    }

                    if (statusChars.second != ' ') {
                        ++mUnstagedCount;
                    }

                    mRepositoryStatusMap.insert(filePath, parentFileNode(filePath)->addChild(QFileInfo(filePath).fileName(), statusChars));
                }
            }

            git_status_list_free(statusList);
        }

        // Delete any 'old' file node that is not being used anymore

        PmrWorkspaceFileNodes newFileNodes = mRepositoryStatusMap.values();
        PmrWorkspaceFileNodes oldFileNodesToDelete = PmrWorkspaceFileNodes();

        for (auto oldFileNode : oldFileNodes) {
            if (!newFileNodes.contains(oldFileNode)) {
                oldFileNodesToDelete << oldFileNode;
            }
        }

        if (!oldFileNodesToDelete.isEmpty()) {
            deleteFileNodes(mRootFileNode, oldFileNodesToDelete);
        }
    } else if (mRootFileNode->hasChildren()) {
        // We are not open, so clear our root file node

        for (auto child : mRootFileNode->children()) {
            delete child;
        }
    }
}
Пример #21
0
void QGit::listChangedFiles()
{
    git_repository *repo = nullptr;
    git_status_list *list = nullptr;
    QMap<QString,git_status_t> items;
    int res = 0;
    size_t index = 0;

    QGitError error;

    try {

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

        res = git_status_list_new(&list, repo, nullptr);
        if (res)
        {
            throw QGitError("git_status_list_new", res);
        }

        while(const git_status_entry *item = git_status_byindex(list, index))
        {
            git_status_t status = item->status;
            if ((status != GIT_STATUS_CURRENT)&&(status != GIT_STATUS_IGNORED))
            {
                if (item->index_to_workdir)
                {
                    items.insert(QString::fromUtf8(item->index_to_workdir->new_file.path), status);
                }
                else if (item->head_to_index)
                {
                    items.insert(QString::fromUtf8(item->head_to_index->new_file.path), status);
                }
                else
                {
                    throw QGitError("unknown scenario", res);
                }
            }

            index++;
        }
    } catch(const QGitError &ex) {
        error = ex;
    }

    emit listChangedFilesReply(items, error);

    if (list)
    {
        git_status_list_free(list);
        list = nullptr;
    }

    if (repo)
    {
        git_repository_free(repo);
        repo = nullptr;
    }
}
Пример #22
0
void NotesModel::updateGitStatus() {
    git_repository *repo = NULL;
    git_index *idx = NULL;
    git_signature *me = NULL;

    try {
        e(git_repository_open(&repo, notesFolder().absolutePath().toUtf8().constData()));

        /* Each repository owns an index */
        e(git_repository_index(&idx, repo));

        /* Read index from disk : FIXME Necessary ?*/
        e(git_index_read(idx, true));


        /* Set Option for git status */
        git_status_options opts = { 1, GIT_STATUS_SHOW_INDEX_AND_WORKDIR,
                                    GIT_STATUS_OPT_INCLUDE_UNTRACKED |
                                    //     GIT_STATUS_OPT_INCLUDE_UNMODIFIED |
                                    GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS };
        //status_data d;
        int state = git_repository_state(repo);

        git_status_list *statuses = NULL;
        e(git_status_list_new(&statuses, repo, &opts));


        size_t count = git_status_list_entrycount(statuses);
        if ((count == 0) && (GIT_REPOSITORY_STATE_MERGE != state)) {
            return; // No modified file, exit
        }
        for (size_t i=0; i<count; ++i) {
            const git_status_entry *entry = git_status_byindex(statuses, i);

            /* For each new file add it to the index */
            if ((entry->status & GIT_STATUS_WT_MODIFIED) || (entry->status & GIT_STATUS_WT_RENAMED) || (entry->status & GIT_STATUS_WT_TYPECHANGE) || entry->status == GIT_STATUS_WT_NEW) {
                e(git_index_add_bypath(idx, entry->index_to_workdir->new_file.path));
            }
            else if (entry->status & GIT_STATUS_WT_DELETED) {
                e(git_index_remove_bypath(idx, entry->index_to_workdir->old_file.path));
            }
        }

        e(git_index_write(idx));


        /* Write the index contents to the ODB as a tree */
        git_oid new_tree_id;
        e(git_index_write_tree(&new_tree_id, idx));

        /* Create signature */
        e(git_signature_now(&me, "sparkleNotes", "*****@*****.**"));


        /* Get tree ref */
        git_tree *tree;
        e(git_tree_lookup(&tree, repo, &new_tree_id));

        /* Get parent commit */
        git_oid parentCommitId;
        git_commit *parent;
        int nparents;
        int err;
        err = git_reference_name_to_id( &parentCommitId, repo, "HEAD" );
        if (err == -3) {
            nparents = 0;
        }
        else {
            e(git_commit_lookup( &parent, repo, &parentCommitId ));
            nparents = 1;
        }
        const git_commit *parents [1] = { parent };

        git_oid new_commit_id;
        e(git_commit_create(
              &new_commit_id,
              repo,
              "HEAD",                      /* name of ref to update */
              me,                          /* author */
              me,                          /* committer */
              "UTF-8",                     /* message encoding */
              "Modif on notes",            /* message */
              tree,                        /* root tree */
              nparents,                    /* parent count */
              parents));                    /* parents */


        if(nparents > 0)
            git_commit_free (parent);
        git_checkout_index (repo, idx, NULL);
        git_signature_free(me);
        git_index_free(idx);
        git_repository_free(repo);
    }
    catch (int error) {
        const git_error *err = giterr_last();
        if (err != NULL)
            qDebug() << QString::number(err->klass) + "\t" + QString(err->message);
        giterr_clear();
        git_signature_free(me);
        git_index_free(idx);
        git_repository_free(repo);
    }


}
Пример #23
0
void test_status_worktree__with_directory_in_pathlist(void)
{
	git_repository *repo = cl_git_sandbox_init("testrepo2");
	git_index *index;
	git_status_options opts = GIT_STATUS_OPTIONS_INIT;
	git_status_list *statuslist;
	const git_status_entry *status;
	size_t i, entrycount;
	bool native_ignore_case;
	char *subdir_path = "subdir";

	cl_git_pass(git_repository_index(&index, repo));
	native_ignore_case =
			(git_index_caps(index) & GIT_INDEXCAP_IGNORE_CASE) != 0;
	git_index_free(index);

	opts.pathspec.strings = &subdir_path;
	opts.pathspec.count = 1;
	opts.flags =
			GIT_STATUS_OPT_DEFAULTS |
			GIT_STATUS_OPT_INCLUDE_UNMODIFIED |
			GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH;

	opts.show = GIT_STATUS_SHOW_WORKDIR_ONLY;
	git_status_list_new(&statuslist, repo, &opts);

	entrycount = git_status_list_entrycount(statuslist);
	cl_assert_equal_i(4, entrycount);

	for (i = 0; i < entrycount; i++) {
		status = git_status_byindex(statuslist, i);
		cl_assert_equal_i(0, status->status);
		cl_assert_equal_s(native_ignore_case ?
			testrepo2_subdir_paths_icase[i] :
			testrepo2_subdir_paths[i],
			status->index_to_workdir->old_file.path);
	}

	git_status_list_free(statuslist);

	opts.show = GIT_STATUS_SHOW_INDEX_ONLY;
	git_status_list_new(&statuslist, repo, &opts);

	entrycount = git_status_list_entrycount(statuslist);
	cl_assert_equal_i(4, entrycount);

	for (i = 0; i < entrycount; i++) {
		status = git_status_byindex(statuslist, i);
		cl_assert_equal_i(0, status->status);
		cl_assert_equal_s(native_ignore_case ?
			testrepo2_subdir_paths_icase[i] :
			testrepo2_subdir_paths[i],
			status->head_to_index->old_file.path);
	}

	git_status_list_free(statuslist);

	opts.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
	git_status_list_new(&statuslist, repo, &opts);

	entrycount = git_status_list_entrycount(statuslist);
	cl_assert_equal_i(4, entrycount);

	for (i = 0; i < entrycount; i++) {
		status = git_status_byindex(statuslist, i);
		cl_assert_equal_i(0, status->status);
		cl_assert_equal_s(native_ignore_case ?
			testrepo2_subdir_paths_icase[i] :
			testrepo2_subdir_paths[i],
			status->index_to_workdir->old_file.path);
	}

	git_status_list_free(statuslist);
}