Пример #1
0
bool PmrWorkspace::commitMerge()
{
    // Get the number of merge heads so we can allocate an array for parents

    MergeheadForeachCallbackData data = { 0, nullptr, nullptr };

    git_repository_mergehead_foreach(mGitRepository, mergeheadForeachCallback, &data);

    size_t parentsCount = data.size+1;
    auto parents = new git_commit*[parentsCount]();

    // HEAD is always a parent

    bool res = false;
    git_oid parentId;

    if (   (git_reference_name_to_id(&parentId, mGitRepository, "HEAD") == GIT_OK)
        && (git_commit_lookup(parents, mGitRepository, &parentId) == GIT_OK)) {
        res = true;

        // Populate the list of commit parents

        if (parentsCount > 1) {
            data.size = 0;
            data.repository = mGitRepository;
            data.parents = &(parents[1]);

            if (git_repository_mergehead_foreach(mGitRepository, mergeheadForeachCallback, &data) != GIT_OK) {
                res = false;
            }
        }

        if (res) {
            std::string message = std::string("Merge branch 'master' of ");

            if (commit(message.c_str(), parentsCount, const_cast<const git_commit **>(parents))) {
                git_repository_state_cleanup(mGitRepository);
            } else {
                res = false;
            }
        }
    }

    for (size_t n = 0; n < parentsCount; ++n) {
        git_commit_free(parents[n]);
    }

    delete[] parents;

    if (!res) {
        emitGitError(tr("An error occurred while trying to commit the merge."));
    }

    return res;
}
Пример #2
0
/**
 * Create a commit
 *
 * @param out The oid of the newly created commit
 * @param repository The repository
 * @param index The index
 * @param message The commit message
 * @param author Who is the author of the commit
 * @param committer Who is the committer
 * @return 0 on success, or error code
 */
int git2r_commit_create(
    git_oid *out,
    git_repository *repository,
    git_index *index,
    const char *message,
    git_signature *author,
    git_signature *committer)
{
    int err;
    git_oid oid;
    git_tree *tree = NULL;
    git_commit **parents = NULL;
    size_t n_parents = 0;

    err = git_index_write_tree(&oid, index);
    if (GIT_OK != err)
        goto cleanup;

    err = git_tree_lookup(&tree, repository, &oid);
    if (GIT_OK != err)
        goto cleanup;

    err = git2r_retrieve_parents(&parents, &n_parents, repository);
    if (GIT_OK != err)
        goto cleanup;

    err = git_commit_create(
        out,
        repository,
        "HEAD",
        author,
        committer,
        NULL,
        message,
        tree,
        n_parents,
        (const git_commit**)parents);
    if (GIT_OK != err)
        goto cleanup;

    err = git_repository_state_cleanup(repository);

cleanup:
    if (parents)
        git2r_parents_free(parents, n_parents);

    if (tree)
        git_tree_free(tree);

    return err;
}
Пример #3
0
static int reset(
	git_repository *repo,
	const git_object *target,
	const char *to,
	git_reset_t reset_type,
	const git_checkout_options *checkout_opts)
{
	git_object *commit = NULL;
	git_index *index = NULL;
	git_tree *tree = NULL;
	int error = 0;
	git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
	git_buf log_message = GIT_BUF_INIT;

	assert(repo && target);

	if (checkout_opts)
		opts = *checkout_opts;

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

	if (reset_type != GIT_RESET_SOFT &&
		(error = git_repository__ensure_not_bare(repo,
			reset_type == GIT_RESET_MIXED ? "reset mixed" : "reset hard")) < 0)
		return error;

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

	if (reset_type == GIT_RESET_SOFT &&
		(git_repository_state(repo) == GIT_REPOSITORY_STATE_MERGE ||
		 git_index_has_conflicts(index)))
	{
		giterr_set(GITERR_OBJECT, "%s (soft) in the middle of a merge", ERROR_MSG);
		error = GIT_EUNMERGED;
		goto cleanup;
	}

	if ((error = git_buf_printf(&log_message, "reset: moving to %s", to)) < 0)
		return error;

	if (reset_type == GIT_RESET_HARD) {
		/* overwrite working directory with the new tree */
		opts.checkout_strategy = GIT_CHECKOUT_FORCE;

		if ((error = git_checkout_tree(repo, (git_object *)tree, &opts)) < 0)
			goto cleanup;
	}

	/* move HEAD to the new target */
	if ((error = git_reference__update_terminal(repo, GIT_HEAD_FILE,
		git_object_id(commit), NULL, git_buf_cstr(&log_message))) < 0)
		goto cleanup;

	if (reset_type > GIT_RESET_SOFT) {
		/* reset index to the target content */

		if ((error = git_index_read_tree(index, tree)) < 0 ||
			(error = git_index_write(index)) < 0)
			goto cleanup;

		if ((error = git_repository_state_cleanup(repo)) < 0) {
			giterr_set(GITERR_INDEX, "%s - failed to clean up merge data", ERROR_MSG);
			goto cleanup;
		}
	}

cleanup:
	git_object_free(commit);
	git_index_free(index);
	git_tree_free(tree);
	git_buf_dispose(&log_message);

	return error;
}
Пример #4
0
void SyncState::sync()
{
	m_timer.restart();

	// Set up directory structure, if necessary
	std::string tmpPath = cpp3ds::FileSystem::getFilePath("sdmc:/3ds/BrewMan/tmp");
	std::string cachePath = cpp3ds::FileSystem::getFilePath("sdmc:/3ds/BrewMan/cache");
	std::string installedPath = cpp3ds::FileSystem::getFilePath("sdmc:/3ds/BrewMan/installed");
	if (pathExists(tmpPath.c_str(), false))
		removeDirectory(tmpPath.c_str());
	mkdir(tmpPath.c_str(), 0777);
	if (!pathExists(cachePath.c_str(), false))
		mkdir(cachePath.c_str(), 0777);
	if (!pathExists(installedPath.c_str(), false))
		mkdir(installedPath.c_str(), 0777);

	// If auto-dated, boot into newest BrewMan
	if (autoUpdate())
	{
		char buf[256];
		size_t len;
		FILE *src = fopen("sdmc:/3ds/BrewMan/tmp/update.3dsx", "rb");
		FILE *dst = fopen("sdmc:/3ds/BrewMan/tmp/update-copy.3dsx", "wb");
		while ((len = fread(buf, 1, sizeof(buf), src)) > 0)
			fwrite(buf, 1, sizeof(buf), dst);
		fclose(src);
		fclose(dst);

		bootApp("/3ds/BrewMan/tmp/update.3dsx", "");
		requestStackClear();
		return;
	}

	git_repository *repo = NULL;
	const char *repoUrl = "git://github.com/Repo3DS/ideal-enigma.git";
	const std::string path = cpp3ds::FileSystem::getFilePath(REPO_DIR);

	git_clone_options opts = GIT_CLONE_OPTIONS_INIT;

	setStatus("Fetching git repo...");

	int error = git_clone(&repo, repoUrl, path.c_str(), NULL);

	if (error < 0)
	{
		if (error == GIT_EEXISTS) {
			error = git_repository_open(&repo, path.c_str());
			if (error == 0) {
				git_remote *remote;
				error = git_remote_lookup(&remote, repo, "origin");
				if (error == 0) {
					error = git_remote_fetch(remote, NULL, NULL, "pull");
					if (error == 0)
					{
						git_annotated_commit *our_head, *their_heads[1];
						if (git_repository_fetchhead_foreach(repo, find_master, NULL) == 0)
						{
							git_annotated_commit_from_fetchhead(&their_heads[0], repo, "master", repoUrl, &m_git_oid);

							git_merge_analysis_t analysis;
							git_merge_preference_t prefs;
							git_merge_analysis(&analysis, &prefs, repo, (const git_annotated_commit**)their_heads, 1);

							if (analysis & GIT_MERGE_ANALYSIS_UP_TO_DATE)
								printf("up to date\n");
							else if (analysis & GIT_MERGE_ANALYSIS_FASTFORWARD)
							{
								printf("fast-forwarding\n");
//								if (git_merge(repo, (const git_annotated_commit **)their_heads, 1, NULL, NULL) == 0) {

								git_reference *ref;
								git_reference *newref;
								if (git_reference_lookup(&ref, repo, "refs/heads/master") == 0)
									git_reference_set_target(&newref, ref, &m_git_oid, "BrewMan pull: Fast-forward");

								git_reset_from_annotated(repo, their_heads[0], GIT_RESET_HARD, NULL);

								git_reference_free(ref);
								git_repository_state_cleanup(repo);
							}

							git_annotated_commit_free(their_heads[0]);
						}
					}
				}
			}
			git_repository_free(repo);
			const git_error *e = giterr_last();
			if (e) {
				setStatus(_("Error %d/%d\n%s\nCloning repo again...", error, e->klass, e->message));
				if (!removeDirectory(path.c_str())) {
					cpp3ds::sleep(cpp3ds::seconds(2.f));
					sync();
				} else {
					setStatus("Repo failure. Please report this error.\nAnd delete /3ds/BrewMan/repo/ and try again.");
				}
				return;
			}
		}
		const git_error *e = giterr_last();
		if (e) {
			setStatus(_("Error %d/%d: %s", error, e->klass, e->message));
			return;
		}
	}

	setStatus("Everything up-to-date!");

	// Give the Title animation time to finish if necessary
	while (m_timer.getElapsedTime() < cpp3ds::seconds(5.f))
		cpp3ds::sleep(cpp3ds::milliseconds(50));

	requestStackClear();
	requestStackPush(States::Browse);
}
Пример #5
0
int NotesModel::pull() {

    git_repository *repo = NULL;
    git_remote *remote = NULL;
    git_merge_head *merge_head = NULL;

    if (!QSettings().value("gitRemoteUrl").isValid()) {
        qDebug() << "gitRemoteUrl setting invalid";
        return false; }

    if (QSettings().value("gitRemoteUrl") == "")
        return false;

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

        //List repository and add one from Settings if none exists or doesn t have same URI than settings
        git_strarray   remotes = {0};
        git_remote_list(&remotes, repo);
        if (remotes.count >= 1) {
            for (size_t i = 0; i < remotes.count; i++) {
                e(git_remote_load(&remote, repo, remotes.strings[i]));
                qDebug() << git_remote_url(remote);
                if (QSettings().value("gitRemoteUrl").isValid() && git_remote_url(remote)) {
                    if (strcmp(git_remote_url(remote),QSettings().value("gitRemoteUrl").toString().toUtf8().constData()) != 0) {
                        e(git_remote_delete(remote));
                        e(git_remote_create(&remote, repo, "upstream",
                                            QSettings().value("gitRemoteUrl").toString().toUtf8().constData()));
                        e(git_remote_save(remote));
                    }

                }
            }
        } else if (remotes.count == 0) {
            e(git_remote_create(&remote, repo, "upstream",
                                QSettings().value("gitRemoteUrl").toString().toUtf8().constData()));
            e(git_remote_save(remote));
        }

        e(git_remote_load(&remote, repo, "upstream"));

        git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
        callbacks.credentials = cred_acquire_cb;
        e(git_remote_set_callbacks(remote, &callbacks));

        e(git_remote_connect(remote, GIT_DIRECTION_FETCH));
        int connected = git_remote_connected(remote);
        if (connected)
            e(git_remote_fetch(remote, NULL, NULL));


        git_checkout_options checkout_opt = GIT_CHECKOUT_OPTIONS_INIT;
        checkout_opt.checkout_strategy = GIT_CHECKOUT_FORCE;
        checkout_opt.file_mode = 0644;
        git_merge_options merge_opt = GIT_MERGE_OPTIONS_INIT;
        merge_opt.file_favor = GIT_MERGE_FILE_FAVOR_UNION;

        const git_remote_head **head = NULL;
        size_t size = 0;
        e(git_remote_ls(&head, &size, remote));
        if (size <= 0)
            e(-1);

        git_oid oid = head[0]->oid;

        e(git_merge_head_from_fetchhead(&merge_head, repo, "master", git_remote_url(remote), &oid));
        e(git_merge(repo, (const git_merge_head **)(&merge_head), 1, &merge_opt, &checkout_opt));

        //TRY TO COMMIT
        /* Create signature */
        git_signature *me = NULL;
        e(git_signature_now(&me, "sparkleNotes", "*****@*****.**"));

        //Tree Lookup
        git_object *tree_obj;
        e(git_revparse_single(&tree_obj, repo, "HEAD^{tree}"));

        // Get parent commit
        git_oid parentCommitId;
        git_commit *parent;
        git_oid remoteParentCommitId;
        git_commit *remoteParent;
        e(git_reference_name_to_id( &parentCommitId, repo, "ORIG_HEAD" ));
        e(git_commit_lookup( &parent, repo, &parentCommitId ));
        e(git_reference_name_to_id( &remoteParentCommitId, repo, "MERGE_HEAD" ));
        e(git_commit_lookup( &remoteParent, repo, &remoteParentCommitId ));

        if (remoteParent == parent) {
            //Same commit ... nothing to merge
            e(git_repository_state_cleanup(repo));
            git_merge_head_free(merge_head);
            git_remote_free(remote);
            git_repository_free(repo);
            return false;
        }
        const git_commit *parents [2] = { parent, remoteParent };

        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 */
              "Merge remote upstream/master",   /* message */
              (git_tree *) tree_obj,            /* root tree */
              2,                                /* parent count */
              parents));                        /* parents */


        git_merge_head_free(merge_head);
        git_remote_free(remote);

        e(git_repository_state_cleanup(repo));

        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);
        emit this->error(QString(err->message));
        giterr_clear();
        git_merge_head_free(merge_head);
        git_remote_free(remote);
        git_repository_free(repo);
    }
    return true;
}
Пример #6
0
int main()
{
    git_libgit2_init();

    git_repository* rep = nullptr;

    const git_annotated_commit* their_head[10];
    git_merge_options merge_opt = GIT_MERGE_OPTIONS_INIT;
    git_checkout_options checkout_opt = GIT_CHECKOUT_OPTIONS_INIT;

    git_reference* branch = nullptr;
    git_index* index = nullptr;
    git_index_conflict_iterator* conflict_iterator = nullptr;
    git_oid new_tree_id;

    git_tree* new_tree = nullptr;
    git_signature* me = nullptr;
    git_reference* head = nullptr;
    git_commit* parent_our = nullptr;
    git_commit* parent_their = nullptr;
    git_oid commit_id;

    int error = 0;

    // git open
    error = git_repository_open(&rep, path);
    if (error < 0)
    {
        const git_error *e = giterr_last();
        std::cout << "Error: " << error << " / " << e->klass << " : " << e->message << std::endl;

        goto SHUTDOWN;
    }

    // git merge <branch>
    git_reference_dwim(&branch, rep, "new");
    git_annotated_commit_from_ref((git_annotated_commit **)&their_head[0], rep, branch);
    error = git_merge(rep, their_head, 1, &merge_opt, &checkout_opt);
    if (error < 0)
    {
        const git_error *e = giterr_last();
        std::cout << "Error: " << error << " / " << e->klass << " : " << e->message << std::endl;

        goto SHUTDOWN;
    }

    git_repository_index(&index, rep);

    // reslove conflicts
    if (git_index_has_conflicts(index))
    {
        const git_index_entry* ancestor_out = nullptr;
        const git_index_entry* our_out = nullptr;
        const git_index_entry* their_out = nullptr;

        git_index_conflict_iterator_new(&conflict_iterator, index);

        while (git_index_conflict_next(&ancestor_out, &our_out, &their_out, conflict_iterator) != GIT_ITEROVER)
        {
            if (ancestor_out) std::cout<< "ancestor: " << ancestor_out->path <<std::endl;
            if (our_out) std::cout<< "our: " << our_out->path <<std::endl;
            if (their_out) std::cout<< "their: " << their_out->path <<std::endl;

            // do sth. or rewrite file by code. ...
            // and remove the conflict
//            git_index_conflict_remove(index, "...");
        }

        // git checkout --theirs <file>
        git_checkout_options opt = GIT_CHECKOUT_OPTIONS_INIT;
        opt.checkout_strategy |= GIT_CHECKOUT_USE_THEIRS;
//        const char* p = "file";
//        opt.paths.strings = (char**)&p;
//        opt.paths.count = 1;
        git_checkout_index(rep, index, &opt);

        git_index_conflict_iterator_free(conflict_iterator);
    }

    // add and commit
    git_index_update_all(index, nullptr, nullptr, nullptr);
    git_index_write(index);
    git_index_write_tree(&new_tree_id, index);
    git_tree_lookup(&new_tree, rep, &new_tree_id);

    git_signature_now(&me, "XiaochenFTX", "*****@*****.**");

    git_repository_head(&head, rep);
    git_commit_lookup(&parent_our, rep, git_reference_target(head));
    git_commit_lookup(&parent_their, rep, git_reference_target(branch));

    git_commit_create_v(&commit_id, rep, "HEAD", me, me, "UTF-8", "merge commit", new_tree, 2, parent_our, parent_their);

    git_repository_state_cleanup(rep);

SHUTDOWN:
    git_repository_free(rep);
    git_libgit2_shutdown();
    return 0;
}