Пример #1
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);
}
Пример #2
0
/**
 * Count number of changes in index
 *
 * @param status
 * @return The number of changes
 */
static size_t git2r_status_count_staged(git_status_list *status_list)
{
    size_t i = 0;
    size_t changes = 0;
    size_t count = git_status_list_entrycount(status_list);

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

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

        if (s->status & GIT_STATUS_INDEX_NEW)
            changes++;
        else if (s->status & GIT_STATUS_INDEX_MODIFIED)
            changes++;
        else if (s->status & GIT_STATUS_INDEX_DELETED)
            changes++;
        else if (s->status & GIT_STATUS_INDEX_RENAMED)
            changes++;
        else if (s->status & GIT_STATUS_INDEX_TYPECHANGE)
            changes++;
    }

    return changes;
}
Пример #3
0
/**
 * Add untracked files
 *
 * @param list
 * @param list_index
 * @param status_list
 * @return void
 */
static void git2r_status_list_untracked(
    SEXP list,
    size_t list_index,
    git_status_list *status_list)
{
    size_t i = 0, j = 0, count;
    SEXP sub_list, sub_list_names, item;

    /* Create list with the correct number of entries */
    count = git2r_status_count_untracked(status_list);
    PROTECT(sub_list = allocVector(VECSXP, count));
    PROTECT(sub_list_names = allocVector(STRSXP, count));

    /* i index the entrycount. j index the added change in list */
    count = git_status_list_entrycount(status_list);
    for (; i < count; i++) {
        const git_status_entry *s = git_status_byindex(status_list, i);

        if (s->status == GIT_STATUS_WT_NEW) {
            SET_STRING_ELT(sub_list_names, j, mkChar("untracked"));
            PROTECT(item = allocVector(STRSXP, 1));
            SET_STRING_ELT(item, 0, mkChar(s->index_to_workdir->old_file.path));
            SET_VECTOR_ELT(sub_list, j, item);
            UNPROTECT(1);
            j++;
        }
    }

    setAttrib(sub_list, R_NamesSymbol, sub_list_names);
    SET_VECTOR_ELT(list, list_index, sub_list);
    UNPROTECT(2);
}
Пример #4
0
/**
 * Add changes in index
 *
 * @param list
 * @param list_index
 * @param status_list
 * @return void
 */
static void git2r_status_list_staged(
    SEXP list,
    size_t list_index,
    git_status_list *status_list)
{
    size_t i = 0, j = 0, count;
    SEXP sub_list, sub_list_names, item;

    /* Create list with the correct number of entries */
    count = git2r_status_count_staged(status_list);
    PROTECT(sub_list = allocVector(VECSXP, count));
    PROTECT(sub_list_names = allocVector(STRSXP, count));

    /* i index the entrycount. j index the added change in list */
    count = git_status_list_entrycount(status_list);
    for (; i < count; i++) {
        char *istatus = NULL;
        const char *old_path, *new_path;
        const git_status_entry *s = git_status_byindex(status_list, i);

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

        if (s->status & GIT_STATUS_INDEX_NEW)
            istatus = "new";
        else if (s->status & GIT_STATUS_INDEX_MODIFIED)
            istatus = "modified";
        else if (s->status & GIT_STATUS_INDEX_DELETED)
            istatus = "deleted";
        else if (s->status & GIT_STATUS_INDEX_RENAMED)
            istatus = "renamed";
        else if (s->status & GIT_STATUS_INDEX_TYPECHANGE)
            istatus = "typechange";

        if (!istatus)
            continue;
        SET_STRING_ELT(sub_list_names, j, mkChar(istatus));

        old_path = s->head_to_index->old_file.path;
        new_path = s->head_to_index->new_file.path;

        if (old_path && new_path && strcmp(old_path, new_path)) {
            PROTECT(item = allocVector(STRSXP, 2));
            SET_STRING_ELT(item, 0, mkChar(old_path));
            SET_STRING_ELT(item, 1, mkChar(new_path));
        } else {
            PROTECT(item = allocVector(STRSXP, 1));
            SET_STRING_ELT(item, 0, mkChar(old_path ? old_path : new_path));
        }

        SET_VECTOR_ELT(sub_list, j, item);
        UNPROTECT(1);
        j++;
    }

    setAttrib(sub_list, R_NamesSymbol, sub_list_names);
    SET_VECTOR_ELT(list, list_index, sub_list);
    UNPROTECT(2);
}
Пример #5
0
static void check_status0(git_status_list *status)
{
	size_t i, max_i = git_status_list_entrycount(status);
	cl_assert_equal_sz(entry_count0, max_i);
	for (i = 0; i < max_i; ++i) {
		const git_status_entry *entry = git_status_byindex(status, i);
		cl_assert_equal_i(entry_statuses0[i], entry->status);
	}
}
Пример #6
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);
}
Пример #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
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;
}
Пример #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
/**
 * Count number of ignored files
 *
 * @param status
 * @return The number of files
 */
static size_t git2r_status_count_ignored(git_status_list *status_list)
{
    size_t i = 0;
    size_t ignored = 0;
    size_t count = git_status_list_entrycount(status_list);

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

        if (s->status == GIT_STATUS_IGNORED)
            ignored++;
    }

    return ignored;
}
Пример #11
0
/**
 * Count number of untracked files
 *
 * @param status
 * @return The number of files
 */
static size_t git2r_status_count_untracked(git_status_list *status_list)
{
    size_t i = 0;
    size_t untracked = 0;
    size_t count = git_status_list_entrycount(status_list);

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

        if (s->status == GIT_STATUS_WT_NEW)
            untracked++;
    }

    return untracked;
}
Пример #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_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);
}
Пример #14
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);
}
Пример #15
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);
}
Пример #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
/**
 * Count number of changes in workdir relative to index
 *
 * @param status
 * @return The number of changes
 */
static size_t git2r_status_count_unstaged(git_status_list *status_list)
{
    size_t i = 0;
    size_t changes = 0;
    size_t count = git_status_list_entrycount(status_list);

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

        if (s->status == GIT_STATUS_CURRENT || s->index_to_workdir == NULL)
            continue;

        if (s->status & GIT_STATUS_WT_MODIFIED)
            changes++;
        else if (s->status & GIT_STATUS_WT_DELETED)
            changes++;
        else if (s->status & GIT_STATUS_WT_RENAMED)
            changes++;
        else if (s->status & GIT_STATUS_WT_TYPECHANGE)
            changes++;
    }

    return changes;
}
Пример #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 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);
    }


}
Пример #20
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);
}
Пример #21
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;
        }
    }
}
Пример #22
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;
    }
}
Пример #23
0
/**
 * This function print out an output similar to git's status command
 * in long form, including the command-line hints.
 */
static void print_long(git_status_list *status)
{
	size_t i, maxi = git_status_list_entrycount(status);
	const git_status_entry *s;
	int header = 0, changes_in_index = 0;
	int changed_in_workdir = 0, rm_in_workdir = 0;
	const char *old_path, *new_path;

	/** Print index changes. */

	for (i = 0; i < maxi; ++i) {
		char *istatus = NULL;

		s = git_status_byindex(status, i);

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

		if (s->status & GIT_STATUS_WT_DELETED)
			rm_in_workdir = 1;

		if (s->status & GIT_STATUS_INDEX_NEW)
			istatus = "new file: ";
		if (s->status & GIT_STATUS_INDEX_MODIFIED)
			istatus = "modified: ";
		if (s->status & GIT_STATUS_INDEX_DELETED)
			istatus = "deleted:  ";
		if (s->status & GIT_STATUS_INDEX_RENAMED)
			istatus = "renamed:  ";
		if (s->status & GIT_STATUS_INDEX_TYPECHANGE)
			istatus = "typechange:";

		if (istatus == NULL)
			continue;

		if (!header) {
			printf("# Changes to be committed:\n");
			printf("#   (use \"git reset HEAD <file>...\" to unstage)\n");
			printf("#\n");
			header = 1;
		}

		old_path = s->head_to_index->old_file.path;
		new_path = s->head_to_index->new_file.path;

		if (old_path && new_path && strcmp(old_path, new_path))
			printf("#\t%s  %s -> %s\n", istatus, old_path, new_path);
		else
			printf("#\t%s  %s\n", istatus, old_path ? old_path : new_path);
	}

	if (header) {
		changes_in_index = 1;
		printf("#\n");
	}
	header = 0;

	/** Print workdir changes to tracked files. */

	for (i = 0; i < maxi; ++i) {
		char *wstatus = NULL;

		s = git_status_byindex(status, i);

		/**
		 * With `GIT_STATUS_OPT_INCLUDE_UNMODIFIED` (not used in this example)
		 * `index_to_workdir` may not be `NULL` even if there are
		 * no differences, in which case it will be a `GIT_DELTA_UNMODIFIED`.
		 */
		if (s->status == GIT_STATUS_CURRENT || s->index_to_workdir == NULL)
			continue;

		/** Print out the output since we know the file has some changes */
		if (s->status & GIT_STATUS_WT_MODIFIED)
			wstatus = "modified: ";
		if (s->status & GIT_STATUS_WT_DELETED)
			wstatus = "deleted:  ";
		if (s->status & GIT_STATUS_WT_RENAMED)
			wstatus = "renamed:  ";
		if (s->status & GIT_STATUS_WT_TYPECHANGE)
			wstatus = "typechange:";

		if (wstatus == NULL)
			continue;

		if (!header) {
			printf("# Changes not staged for commit:\n");
			printf("#   (use \"git add%s <file>...\" to update what will be committed)\n", rm_in_workdir ? "/rm" : "");
			printf("#   (use \"git checkout -- <file>...\" to discard changes in working directory)\n");
			printf("#\n");
			header = 1;
		}

		old_path = s->index_to_workdir->old_file.path;
		new_path = s->index_to_workdir->new_file.path;

		if (old_path && new_path && strcmp(old_path, new_path))
			printf("#\t%s  %s -> %s\n", wstatus, old_path, new_path);
		else
			printf("#\t%s  %s\n", wstatus, old_path ? old_path : new_path);
	}

	if (header) {
		changed_in_workdir = 1;
		printf("#\n");
	}

	/** Print untracked files. */

	header = 0;

	for (i = 0; i < maxi; ++i) {
		s = git_status_byindex(status, i);

		if (s->status == GIT_STATUS_WT_NEW) {

			if (!header) {
				printf("# Untracked files:\n");
				printf("#   (use \"git add <file>...\" to include in what will be committed)\n");
				printf("#\n");
				header = 1;
			}

			printf("#\t%s\n", s->index_to_workdir->old_file.path);
		}
	}

	header = 0;

	/** Print ignored files. */

	for (i = 0; i < maxi; ++i) {
		s = git_status_byindex(status, i);

		if (s->status == GIT_STATUS_IGNORED) {

			if (!header) {
				printf("# Ignored files:\n");
				printf("#   (use \"git add -f <file>...\" to include in what will be committed)\n");
				printf("#\n");
				header = 1;
			}

			printf("#\t%s\n", s->index_to_workdir->old_file.path);
		}
	}

	if (!changes_in_index && changed_in_workdir)
		printf("no changes added to commit (use \"git add\" and/or \"git commit -a\")\n");
}
Пример #24
0
/**
 * This version of the output prefixes each path with two status
 * columns and shows submodule status information.
 */
static void print_short(git_repository *repo, git_status_list *status)
{
	size_t i, maxi = git_status_list_entrycount(status);
	const git_status_entry *s;
	char istatus, wstatus;
	const char *extra, *a, *b, *c;

	for (i = 0; i < maxi; ++i) {
		s = git_status_byindex(status, i);

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

		a = b = c = NULL;
		istatus = wstatus = ' ';
		extra = "";

		if (s->status & GIT_STATUS_INDEX_NEW)
			istatus = 'A';
		if (s->status & GIT_STATUS_INDEX_MODIFIED)
			istatus = 'M';
		if (s->status & GIT_STATUS_INDEX_DELETED)
			istatus = 'D';
		if (s->status & GIT_STATUS_INDEX_RENAMED)
			istatus = 'R';
		if (s->status & GIT_STATUS_INDEX_TYPECHANGE)
			istatus = 'T';

		if (s->status & GIT_STATUS_WT_NEW) {
			if (istatus == ' ')
				istatus = '?';
			wstatus = '?';
		}
		if (s->status & GIT_STATUS_WT_MODIFIED)
			wstatus = 'M';
		if (s->status & GIT_STATUS_WT_DELETED)
			wstatus = 'D';
		if (s->status & GIT_STATUS_WT_RENAMED)
			wstatus = 'R';
		if (s->status & GIT_STATUS_WT_TYPECHANGE)
			wstatus = 'T';

		if (s->status & GIT_STATUS_IGNORED) {
			istatus = '!';
			wstatus = '!';
		}

		if (istatus == '?' && wstatus == '?')
			continue;

		/**
		 * A commit in a tree is how submodules are stored, so
		 * let's go take a look at its status.
		 */
		if (s->index_to_workdir &&
			s->index_to_workdir->new_file.mode == GIT_FILEMODE_COMMIT)
		{
			unsigned int smstatus = 0;

			if (!git_submodule_status(&smstatus, repo, s->index_to_workdir->new_file.path,
						  GIT_SUBMODULE_IGNORE_UNSPECIFIED)) {
				if (smstatus & GIT_SUBMODULE_STATUS_WD_MODIFIED)
					extra = " (new commits)";
				else if (smstatus & GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED)
					extra = " (modified content)";
				else if (smstatus & GIT_SUBMODULE_STATUS_WD_WD_MODIFIED)
					extra = " (modified content)";
				else if (smstatus & GIT_SUBMODULE_STATUS_WD_UNTRACKED)
					extra = " (untracked content)";
			}
		}

		/**
		 * Now that we have all the information, format the output.
		 */

		if (s->head_to_index) {
			a = s->head_to_index->old_file.path;
			b = s->head_to_index->new_file.path;
		}
		if (s->index_to_workdir) {
			if (!a)
				a = s->index_to_workdir->old_file.path;
			if (!b)
				b = s->index_to_workdir->old_file.path;
			c = s->index_to_workdir->new_file.path;
		}

		if (istatus == 'R') {
			if (wstatus == 'R')
				printf("%c%c %s %s %s%s\n", istatus, wstatus, a, b, c, extra);
			else
				printf("%c%c %s %s%s\n", istatus, wstatus, a, b, extra);
		} else {
			if (wstatus == 'R')
				printf("%c%c %s %s%s\n", istatus, wstatus, a, c, extra);
			else
				printf("%c%c %s%s\n", istatus, wstatus, a, extra);
		}
	}

	for (i = 0; i < maxi; ++i) {
		s = git_status_byindex(status, i);

		if (s->status == GIT_STATUS_WT_NEW)
			printf("?? %s\n", s->index_to_workdir->old_file.path);
	}
}