Example #1
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);
}
Example #2
0
static void assert_head_reflog(git_repository *repo, size_t idx,
                               const char *old_id, const char *new_id, const char *message)
{
    git_reflog *log;
    const git_reflog_entry *entry;
    char id_str[GIT_OID_HEXSZ + 1] = {0};

    cl_git_pass(git_reflog_read(&log, repo, GIT_HEAD_FILE));
    entry = git_reflog_entry_byindex(log, idx);

    git_oid_fmt(id_str, git_reflog_entry_id_old(entry));
    cl_assert_equal_s(old_id, id_str);

    git_oid_fmt(id_str, git_reflog_entry_id_new(entry));
    cl_assert_equal_s(new_id, id_str);

    cl_assert_equal_s(message, git_reflog_entry_message(entry));

    git_reflog_free(log);
}
Example #3
0
void test_refs_branches_create__creation_creates_new_reflog(void)
{
	git_reflog *log;
	const git_reflog_entry *entry;
	git_signature *sig;

	cl_git_pass(git_signature_now(&sig, "me", "*****@*****.**"));

	retrieve_known_commit(&target, repo);
	cl_git_pass(git_branch_create(&branch, repo, NEW_BRANCH_NAME, target, false, sig, "create!"));
	cl_git_pass(git_reflog_read(&log, repo, "refs/heads/" NEW_BRANCH_NAME));

	cl_assert_equal_i(1, git_reflog_entrycount(log));
	entry = git_reflog_entry_byindex(log, 0);
	cl_assert_equal_s("create!", git_reflog_entry_message(entry));
	cl_assert_equal_s("*****@*****.**", git_reflog_entry_committer(entry)->email);

	git_reflog_free(log);
	git_signature_free(sig);
}
Example #4
0
void test_refs_reflog_reflog__show_merge_for_merge_commits(void)
{
	git_oid b1_oid;
	git_oid b2_oid;
	git_oid merge_commit_oid;
	git_commit *b1_commit;
	git_commit *b2_commit;
	git_signature *s;
	git_commit *parent_commits[2];
	git_tree *tree;
	git_reflog *log;
	const git_reflog_entry *entry;

	cl_git_pass(git_signature_now(&s, "alice", "*****@*****.**"));

	cl_git_pass(git_reference_name_to_id(&b1_oid, g_repo, "HEAD"));
	cl_git_pass(git_reference_name_to_id(&b2_oid, g_repo, "refs/heads/test"));

	cl_git_pass(git_commit_lookup(&b1_commit, g_repo, &b1_oid));
	cl_git_pass(git_commit_lookup(&b2_commit, g_repo, &b2_oid));

	parent_commits[0] = b1_commit;
	parent_commits[1] = b2_commit;

	cl_git_pass(git_commit_tree(&tree, b1_commit));

	cl_git_pass(git_commit_create(&merge_commit_oid,
		g_repo, "HEAD", s, s, NULL,
		"Merge commit", tree,
		2, (const struct git_commit **) parent_commits));

	cl_git_pass(git_reflog_read(&log, g_repo, "HEAD"));
	entry = git_reflog_entry_byindex(log, 0);
	cl_assert_equal_s(merge_reflog_message, git_reflog_entry_message(entry));

	git_reflog_free(log);
	git_tree_free(tree);
	git_commit_free(b1_commit);
	git_commit_free(b2_commit);
	git_signature_free(s);
}
Example #5
0
File: stash.c Project: aep/libgit2
int git_stash_foreach(
	git_repository *repo,
	git_stash_cb callback,
	void *payload)
{
	git_reference *stash;
	git_reflog *reflog = NULL;
	int error;
	size_t i, max;
	const git_reflog_entry *entry;

	error = git_reference_lookup(&stash, repo, GIT_REFS_STASH_FILE);
	if (error == GIT_ENOTFOUND) {
		giterr_clear();
		return 0;
	}
	if (error < 0)
		goto cleanup;

	if ((error = git_reflog_read(&reflog, stash)) < 0)
		goto cleanup;

	max = git_reflog_entrycount(reflog);
	for (i = 0; i < max; i++) {
		entry = git_reflog_entry_byindex(reflog, i);

		if (callback(i,
			git_reflog_entry_message(entry),
			git_reflog_entry_id_new(entry),
			payload)) {
				error = GIT_EUSER;
				break;
		}
	}

cleanup:
	git_reference_free(stash);
	git_reflog_free(reflog);
	return error;
}
Example #6
0
PyObject* RefLogIter_iternext(RefLogIter *self)
{
    const git_reflog_entry *entry;
    RefLogEntry *py_entry;

    if (self->i < self->size) {
        entry = git_reflog_entry_byindex(self->reflog, self->i);
        py_entry = PyObject_New(RefLogEntry, &RefLogEntryType);

        py_entry->oid_old = git_oid_allocfmt(git_reflog_entry_id_old(entry));
        py_entry->oid_new = git_oid_allocfmt(git_reflog_entry_id_new(entry));
        py_entry->message = strdup(git_reflog_entry_message(entry));
        py_entry->signature = git_signature_dup(
            git_reflog_entry_committer(entry));

        ++(self->i);

        return (PyObject*) py_entry;
    }

    PyErr_SetNone(PyExc_StopIteration);
    return NULL;
}
Example #7
0
void test_rebase_merge__commit(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_oid commit_id, tree_id, parent_id;
	git_signature *author;
	git_commit *commit;
	git_reflog *reflog;
	const git_reflog_entry *reflog_entry;

	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));
	cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
		NULL, NULL));

	cl_git_pass(git_commit_lookup(&commit, repo, &commit_id));

	git_oid_fromstr(&parent_id, "efad0b11c47cb2f0220cbd6f5b0f93bb99064b00");
	cl_assert_equal_i(1, git_commit_parentcount(commit));
	cl_assert_equal_oid(&parent_id, git_commit_parent_id(commit, 0));

	git_oid_fromstr(&tree_id, "4461379789c777d2a6c1f2ee0e9d6c86731b9992");
	cl_assert_equal_oid(&tree_id, git_commit_tree_id(commit));

	cl_assert_equal_s(NULL, git_commit_message_encoding(commit));
	cl_assert_equal_s("Modification 1 to beef\n", git_commit_message(commit));

	cl_git_pass(git_signature_new(&author,
		"Edward Thomson", "*****@*****.**", 1405621769, 0-(4*60)));
	cl_assert(git_signature__equal(author, git_commit_author(commit)));

	cl_assert(git_signature__equal(signature, git_commit_committer(commit)));

	/* 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(&parent_id, git_reflog_entry_id_old(reflog_entry));
	cl_assert_equal_oid(&commit_id, git_reflog_entry_id_new(reflog_entry));
	cl_assert_equal_s("rebase: Modification 1 to beef", git_reflog_entry_message(reflog_entry));

	git_reflog_free(reflog);
	git_signature_free(author);
	git_commit_free(commit);
	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);
}
Example #8
0
static int retrieve_previously_checked_out_branch_or_revision(git_object **out, git_reference **base_ref, git_repository *repo, const char *identifier, size_t position)
{
	git_reference *ref = NULL;
	git_reflog *reflog = NULL;
	regex_t preg;
	int error = -1;
	size_t i, numentries, cur;
	const git_reflog_entry *entry;
	const char *msg;
	regmatch_t regexmatches[2];
	git_buf buf = GIT_BUF_INIT;

	cur = position;

	if (*identifier != '\0' || *base_ref != NULL)
		return GIT_EINVALIDSPEC;

	if (build_regex(&preg, "checkout: moving from (.*) to .*") < 0)
		return -1;

	if (git_reference_lookup(&ref, repo, GIT_HEAD_FILE) < 0)
		goto cleanup;

	if (git_reflog_read(&reflog, repo, GIT_HEAD_FILE) < 0)
		goto cleanup;

	numentries  = git_reflog_entrycount(reflog);

	for (i = 0; i < numentries; i++) {
		entry = git_reflog_entry_byindex(reflog, i);
		msg = git_reflog_entry_message(entry);
		if (!msg)
			continue;

		if (regexec(&preg, msg, 2, regexmatches, 0))
			continue;

		cur--;

		if (cur > 0)
			continue;

		git_buf_put(&buf, msg+regexmatches[1].rm_so, regexmatches[1].rm_eo - regexmatches[1].rm_so);

		if ((error = git_reference_dwim(base_ref, repo, git_buf_cstr(&buf))) == 0)
			goto cleanup;

		if (error < 0 && error != GIT_ENOTFOUND)
			goto cleanup;

		error = maybe_abbrev(out, repo, git_buf_cstr(&buf));

		goto cleanup;
	}

	error = GIT_ENOTFOUND;

cleanup:
	git_reference_free(ref);
	git_buf_free(&buf);
	regfree(&preg);
	git_reflog_free(reflog);
	return error;
}
Example #9
0
int lgit_current::discover( git_repository *repo )
{
    int error, retval = 0;
    const git_oid *oidp;
    git_oid oid;
    const char *sym;
    std::string symbolic_name;

    cur_repo_ = repo;

    clear();

    // Mark one branch as the checked out one
    git_reference *ref;
    if ( ( error = git_repository_head( &ref, repo ) ) < 0 ) {
        state_ = CURRENT_INVALID_MAIN;
        MessagesI.AppendMessageT( "Could not determine which branch is currently checked out" );
    } else {
        switch ( git_reference_type( ref ) ) {

        /* GIT_REF_OID */
        case GIT_REF_OID:
            // Prepare data for .tip_sha
            oidp = git_reference_target( ref );
            if ( !oidp ) {
                state_ = CURRENT_INVALID_OID;
                break;
            }
            state_ = CURRENT_OID;
            oid = *oidp;
            break;

        /* GIT_REF_SYMBOLIC */
        case GIT_REF_SYMBOLIC:
            sym = git_reference_symbolic_target( ref );
            if ( !sym ) {
                state_ = CURRENT_INVALID_SYM;
                break;
            }
            state_ = CURRENT_SYM;
            symbolic_name = std::string( sym );

            // Also establish OID
            if ( ( error = git_reference_name_to_id( &oid, repo, symbolic_name.c_str() ) ) < 0 ) {
                state_ = CURRENT_INVALID_OID2;
                break;
            }

            break;

        /* DEFAULT */
        /* GIT_REF_INVALID */
        /* GIT_REF_LISTALL */
        default:
            state_ = CURRENT_INVALID_OTHER;
            break;

        }

        /*
         * AFTER SWITCH()
         */

        if ( state_ == CURRENT_OID || state_ == CURRENT_SYM ) {
            char sha[ GIT_OID_HEXSZ + 1 ];
            git_oid_fmt( sha, &oid );
            sha[ GIT_OID_HEXSZ ] = '\0';
            current_oid_ = std::string( sha );
            type_ = CURRENT_TYPE_OID;
        }

        if ( state_ == CURRENT_OID ) {
            // Does the reference have any name?
            const char* refname_cstring = git_reference_name( ref );
            if( !refname_cstring ) {
                refname_cstring = "";
            }
            QString refname = QString::fromUtf8( refname_cstring ).trimmed();

            if( refname.isEmpty() || refname == "HEAD" ) {
                git_reflog *reflog;
                const git_reflog_entry *reflog_entry;

                if ( ( error = git_reflog_read( &reflog, repo, "HEAD" ) ) < 0 ) {
                    MessagesI.AppendMessageT( QString( "Could not read reflog, current HEAD will be established as SHA-only" ) +
                                              QString( " (no tag name resolution, error code: %1)" ) . arg( error ) );
                } else {
                    int count = git_reflog_entrycount( reflog );
                    int limit_count = 0;

                    for ( int i = 0; i < count; i ++ ) {
                        reflog_entry = git_reflog_entry_byindex( reflog, i );
                        if( !reflog_entry ) {
                            MessagesI.AppendMessageT( "Problems when reading reflog" );
                            continue;
                        }

                        oidp = git_reflog_entry_id_new( reflog_entry );
                        if( 0 == git_oid_cmp( oidp, &oid ) ) {
                            const char* message_cstring = git_reflog_entry_message( reflog_entry );
                            if( !message_cstring ) {
                                MessagesI.AppendMessageT( "Problems when reading reflog (2)" );
                                continue;
                            }

                            QString message = QString( message_cstring );
                            QRegExp rx("checkout: moving from.*to (.*)$");
                            if( rx.indexIn( message ) != -1 ) {
                                // The target of the catched move message must not be current HEAD's OID prefix
                                if( ! QString::fromStdString( current_oid_ ).startsWith( rx.cap( 1 ) ) ) {
                                    current_tag_ = rx.cap( 1 ).toStdString();
                                    type_ = CURRENT_TYPE_TAG;
                                }
                                break;
                            }

                            // Search only 5 OID-matching entries
                            if( ++ limit_count >= 5 ) {
                                break;
                            }
                        }
                    }

                    git_reflog_free( reflog );
                }
            } else {
                QStringList parts = refname.split( "/", QString::SkipEmptyParts );
                current_branch_ = parts.last().toStdString();
                type_ = CURRENT_TYPE_BRANCH;
            }
        } else if ( state_ == CURRENT_SYM ) {
            current_branch_ = symbolic_name;
        } else {
            MessagesI.AppendMessageT( QString( "Could not determine which branch is currently checked out (error code: %1)" ).arg( state_ ) );
        }

        git_reference_free( ref );
    }

    return retval;
}
Example #10
0
// create a root commit
void test_commit_write__root(void)
{
	git_oid tree_id, commit_id;
	const git_oid *branch_oid;
	git_signature *author, *committer;
	const char *branch_name = "refs/heads/root-commit-branch";
	git_tree *tree;
	git_reflog *log;
	const git_reflog_entry *entry;

	git_oid_fromstr(&tree_id, tree_oid);
	cl_git_pass(git_tree_lookup(&tree, g_repo, &tree_id));

	/* create signatures */
	cl_git_pass(git_signature_new(&committer, committer_name, committer_email, 123456789, 60));
	cl_git_pass(git_signature_new(&author, committer_name, committer_email, 987654321, 90));

	/* First we need to update HEAD so it points to our non-existant branch */
	cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD"));
	cl_assert(git_reference_type(head) == GIT_REF_SYMBOLIC);
	head_old = git__strdup(git_reference_symbolic_target(head));
	cl_assert(head_old != NULL);
	git_reference_free(head);

	cl_git_pass(git_reference_symbolic_create(&head, g_repo, "HEAD", branch_name, 1, NULL, NULL));

	cl_git_pass(git_commit_create_v(
		&commit_id, /* out id */
		g_repo,
		"HEAD",
		author,
		committer,
		NULL,
		root_commit_message,
		tree,
		0));

	git_object_free((git_object *)tree);
	git_signature_free(author);

	/*
	 * The fact that creating a commit works has already been
	 * tested. Here we just make sure it's our commit and that it was
	 * written as a root commit.
	 */
	cl_git_pass(git_commit_lookup(&commit, g_repo, &commit_id));
	cl_assert(git_commit_parentcount(commit) == 0);
	cl_git_pass(git_reference_lookup(&branch, g_repo, branch_name));
	branch_oid = git_reference_target(branch);
	cl_git_pass(git_oid_cmp(branch_oid, &commit_id));
	cl_assert_equal_s(root_commit_message, git_commit_message(commit));

	cl_git_pass(git_reflog_read(&log, g_repo, branch_name));
	cl_assert_equal_i(1, git_reflog_entrycount(log));
	entry = git_reflog_entry_byindex(log, 0);
	cl_assert_equal_s(committer->email, git_reflog_entry_committer(entry)->email);
	cl_assert_equal_s(committer->name, git_reflog_entry_committer(entry)->name);
	cl_assert_equal_s(root_reflog_message, git_reflog_entry_message(entry));

	git_signature_free(committer);
	git_reflog_free(log);
}
Example #11
0
int ParserFromRefLog(CString ref, std::vector<GitRev> &refloglist)
{
	refloglist.clear();
	if (g_Git.m_IsUseLibGit2)
	{
		CAutoRepository repo(g_Git.GetGitRepository());
		if (!repo)
		{
			MessageBox(nullptr, CGit::GetLibGit2LastErr(_T("Could not open repository.")), _T("TortoiseGit"), MB_ICONERROR);
			return -1;
		}

		CAutoReflog reflog;
		if (git_reflog_read(reflog.GetPointer(), repo, CUnicodeUtils::GetUTF8(ref)) < 0)
		{
			MessageBox(nullptr, CGit::GetLibGit2LastErr(_T("Could not read reflog.")), _T("TortoiseGit"), MB_ICONERROR);
			return -1;
		}

		for (size_t i = 0; i < git_reflog_entrycount(reflog); ++i)
		{
			const git_reflog_entry *entry = git_reflog_entry_byindex(reflog, i);
			if (!entry)
				continue;

			GitRev rev;
			rev.m_CommitHash = (char *)git_reflog_entry_id_new(entry)->id;
			rev.m_Ref.Format(_T("%s@{%d}"), ref, i);
			rev.GetCommitterDate() = CTime(git_reflog_entry_committer(entry)->when.time);
			if (git_reflog_entry_message(entry) != nullptr)
			{
				CString one;
				g_Git.StringAppend(&one, (BYTE *)git_reflog_entry_message(entry));
				int message = one.Find(_T(":"), 0);
				if (message > 0)
				{
					rev.m_RefAction = one.Left(message);
					rev.GetSubject() = one.Mid(message + 1);
				}
			}
			refloglist.push_back(rev); 
		}
	}
	else if (g_Git.m_IsUseGitDLL)
	{
		git_for_each_reflog_ent(CUnicodeUtils::GetUTF8(ref), AddToRefLoglist, &refloglist);
		for (size_t i = 0; i < refloglist.size(); ++i)
			refloglist[i].m_Ref.Format(_T("%s@{%d}"), ref, i);
	}
	else
	{
		CString cmd, out;
		GitRev rev;
		cmd.Format(_T("git.exe reflog show --pretty=\"%%H %%gD: %%gs\" --date=raw %s"), ref);
		if (g_Git.Run(cmd, &out, NULL, CP_UTF8))
			return -1;

		int i = 0;
		CString prefix = ref + _T("@{");
		int pos = 0;
		while (pos >= 0)
		{
			CString one = out.Tokenize(_T("\n"), pos);
			int refPos = one.Find(_T(' '), 0);
			if (refPos < 0)
				continue;

			rev.Clear();

			CString hashStr = one.Left(refPos);
			rev.m_CommitHash = hashStr;
			rev.m_Ref.Format(_T("%s@{%d}"), ref, i++);
			int prefixPos = one.Find(prefix, refPos + 1);
			if (prefixPos != refPos + 1)
				continue;

			int spacePos = one.Find(_T(' '), prefixPos + prefix.GetLength() + 1);
			if (spacePos < 0)
				continue;

			CString timeStr = one.Mid(prefixPos + prefix.GetLength(), spacePos - prefixPos - prefix.GetLength());
			rev.GetCommitterDate() = CTime(_ttoi(timeStr));
			int action = one.Find(_T("}: "), spacePos + 1);
			if (action > 0)
			{
				action += 2;
				int message = one.Find(_T(":"), action);
				if (message > 0)
				{
					rev.m_RefAction = one.Mid(action + 1, message - action - 1);
					rev.GetSubject() = one.Right(one.GetLength() - message - 1);
				}
			}

			refloglist.push_back(rev);
		}
	}
	return 0;
}