Ejemplo n.º 1
0
static void execute_test(void)
{
	git_oid oid, check;
	git_commit *commit;
	git_tree *tree;
	git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;

	cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/branch1"));
	cl_git_pass(git_commit_lookup(&commit, g_repo, &oid));
	cl_git_pass(git_commit_tree(&tree, commit));

	opts.checkout_strategy = GIT_CHECKOUT_SAFE;

	cl_git_pass(git_checkout_tree(g_repo, (git_object *)tree, &opts));

	git_tree_free(tree);
	git_commit_free(commit);

	/* Verify that the lenna.jpg file was checked out correctly */
	cl_git_pass(git_oid_fromstr(&check, "8ab005d890fe53f65eda14b23672f60d9f4ec5a1"));
	cl_git_pass(git_odb_hashfile(&oid, "binaryunicode/lenna.jpg", GIT_OBJ_BLOB));
	cl_assert(git_oid_equal(&oid, &check));

	/* Verify that the text file was checked out correctly */
	cl_git_pass(git_oid_fromstr(&check, "965b223880dd4249e2c66a0cc0b4cffe1dc40f5a"));
	cl_git_pass(git_odb_hashfile(&oid, "binaryunicode/utf16_withbom_noeol_crlf.txt", GIT_OBJ_BLOB));
	cl_assert(git_oid_equal(&oid, &check));
}
Ejemplo n.º 2
0
int RemoteProgressCommand::RemoteUpdatetipsCallback(const char* refname, const git_oid* oldOid, const git_oid* newOid, void* data)
{
	auto ptr = (CGitProgressList::Payload*)data;
	bool nonff = false;
	if (!git_oid_iszero(oldOid) && !git_oid_iszero(newOid))
	{
		git_oid baseOid = { 0 };
		if (!git_merge_base(&baseOid, ptr->repo, newOid, oldOid))
			if (!git_oid_equal(oldOid, &baseOid))
				nonff = true;
	}

	CString change;
	if (!git_oid_iszero(oldOid) && !git_oid_iszero(newOid))
	{
		if (git_oid_equal(oldOid, newOid))
		{
			change.LoadString(IDS_SAME);
		}
		else
		{
			size_t ahead = 0, behind = 0;
			if (!git_graph_ahead_behind(&ahead, &behind, ptr->repo, newOid, oldOid))
			{
				if (ahead > 0 && behind == 0)
				{
					change.Format(IDS_FORWARDN, ahead);
				}
				else if (ahead == 0 && behind > 0)
				{
					change.Format(IDS_REWINDN, behind);
				}
				else
				{
					git_commit* oldCommit, * newCommit;
					git_time_t oldTime = 0, newTime = 0;
					if (!git_commit_lookup(&oldCommit, ptr->repo, oldOid))
						oldTime = git_commit_committer(oldCommit)->when.time;
					if (!git_commit_lookup(&newCommit, ptr->repo, newOid))
						newTime = git_commit_committer(newCommit)->when.time;
					if (oldTime < newTime)
						change.LoadString(IDS_SUBMODULEDIFF_NEWERTIME);
					else if (oldTime > newTime)
						change.LoadString(IDS_SUBMODULEDIFF_OLDERTIME);
					else
						change.LoadString(IDS_SUBMODULEDIFF_SAMETIME);
				}
			}
		}
	}
	else if (!git_oid_iszero(oldOid))
		change.LoadString(IDS_DELETED);
	else if (!git_oid_iszero(newOid))
		change.LoadString(IDS_NEW);

	ptr->list->AddNotify(new RefUpdateNotificationData(refname, oldOid, newOid, change));
	return 0;
}
Ejemplo n.º 3
0
static int try_to_update(git_repository *repo, git_remote *origin, git_reference *local, git_reference *remote, enum remote_transport rt)
{
	git_oid base;
	const git_oid *local_id, *remote_id;

	if (!git_reference_cmp(local, remote))
		return 0;

	// Dirty modified state in the working tree? We're not going
	// to update either way
	if (git_status_foreach(repo, check_clean, NULL))
		return report_error("local cached copy is dirty, skipping update");

	local_id = git_reference_target(local);
	remote_id = git_reference_target(remote);

	if (!local_id || !remote_id)
		return report_error("Unable to get local or remote SHA1");

	if (git_merge_base(&base, repo, local_id, remote_id))
		return report_error("Unable to find common commit of local and remote branches");

	/* Is the remote strictly newer? Use it */
	if (git_oid_equal(&base, local_id))
		return reset_to_remote(repo, local, remote_id);

	/* Is the local repo the more recent one? See if we can update upstream */
	if (git_oid_equal(&base, remote_id))
		return update_remote(repo, origin, local, remote, rt);

	/* Merging a bare repository always needs user action */
	if (git_repository_is_bare(repo))
		return report_error("Local and remote have diverged, merge of bare branch needed");

	/* Merging will definitely need the head branch too */
	if (git_branch_is_head(local) != 1)
		return report_error("Local and remote do not match, local branch not HEAD - cannot update");

	/*
	 * Some day we migth try a clean merge here.
	 *
	 * But I couldn't find any good examples of this, so for now
	 * you'd need to merge divergent histories manually. But we've
	 * at least verified above that we have a working tree and the
	 * current branch is checked out and clean, so we *could* try
	 * to merge.
	 */
	return report_error("Local and remote have diverged, need to merge");
}
Ejemplo n.º 4
0
void test_repo_hashfile__filtered(void)
{
	git_oid a, b;
	git_config *config;

	cl_git_pass(git_repository_config(&config, _repo));
	cl_git_pass(git_config_set_bool(config, "core.autocrlf", true));
	git_config_free(config);

	cl_git_append2file("status/.gitattributes", "*.txt text\n*.bin binary\n\n");

	/* create some sample content with CRLF in it */
	cl_git_mkfile("status/testfile.txt", "content\r\n");
	cl_git_mkfile("status/testfile.bin", "other\r\nstuff\r\n");

	/* not equal hashes because of filtering */
	cl_git_pass(git_odb_hashfile(&a, "status/testfile.txt", GIT_OBJ_BLOB));
	cl_git_pass(git_repository_hashfile(&b, _repo, "testfile.txt", GIT_OBJ_BLOB, NULL));
	cl_assert(git_oid_cmp(&a, &b));

	/* equal hashes because filter is binary */
	cl_git_pass(git_odb_hashfile(&a, "status/testfile.bin", GIT_OBJ_BLOB));
	cl_git_pass(git_repository_hashfile(&b, _repo, "testfile.bin", GIT_OBJ_BLOB, NULL));
	cl_assert(git_oid_equal(&a, &b));

	/* equal hashes when 'as_file' points to binary filtering */
	cl_git_pass(git_odb_hashfile(&a, "status/testfile.txt", GIT_OBJ_BLOB));
	cl_git_pass(git_repository_hashfile(&b, _repo, "testfile.txt", GIT_OBJ_BLOB, "foo.bin"));
	cl_assert(git_oid_equal(&a, &b));

	/* not equal hashes when 'as_file' points to text filtering */
	cl_git_pass(git_odb_hashfile(&a, "status/testfile.bin", GIT_OBJ_BLOB));
	cl_git_pass(git_repository_hashfile(&b, _repo, "testfile.bin", GIT_OBJ_BLOB, "foo.txt"));
	cl_assert(git_oid_cmp(&a, &b));

	/* equal hashes when 'as_file' is empty and turns off filtering */
	cl_git_pass(git_odb_hashfile(&a, "status/testfile.txt", GIT_OBJ_BLOB));
	cl_git_pass(git_repository_hashfile(&b, _repo, "testfile.txt", GIT_OBJ_BLOB, ""));
	cl_assert(git_oid_equal(&a, &b));

	cl_git_pass(git_odb_hashfile(&a, "status/testfile.bin", GIT_OBJ_BLOB));
	cl_git_pass(git_repository_hashfile(&b, _repo, "testfile.bin", GIT_OBJ_BLOB, ""));
	cl_assert(git_oid_equal(&a, &b));

	/* some hash type failures */
	cl_git_fail(git_odb_hashfile(&a, "status/testfile.txt", 0));
	cl_git_fail(git_repository_hashfile(&b, _repo, "testfile.txt", GIT_OBJ_ANY, NULL));
}
Ejemplo n.º 5
0
Archivo: merge.c Proyecto: mikeando/agb
static inline int agb_git_tree_entry_equal(const git_tree_entry * tree_a, const git_tree_entry * tree_b ) {
	if(tree_a==NULL && tree_b==NULL) return 1;
	if(tree_a==NULL || tree_b==NULL) return 0;
	const git_oid * oid_a = git_tree_entry_id(tree_a);
	const git_oid * oid_b = git_tree_entry_id(tree_b);
	return git_oid_equal(oid_a,oid_b);
}
Ejemplo n.º 6
0
void test_network_remote_defaultbranch__detached_sharing_nonbranch_id(void)
{
    git_oid id, id_cloned;
    git_reference *ref;
    git_buf buf = GIT_BUF_INIT;
    git_repository *cloned_repo;

    cl_git_pass(git_reference_name_to_id(&id, g_repo_a, "HEAD"));
    cl_git_pass(git_repository_detach_head(g_repo_a, NULL, NULL));
    cl_git_pass(git_reference_remove(g_repo_a, "refs/heads/master"));
    cl_git_pass(git_reference_remove(g_repo_a, "refs/heads/not-good"));
    cl_git_pass(git_reference_create(&ref, g_repo_a, "refs/foo/bar", &id, 1, NULL, NULL));
    git_reference_free(ref);

    cl_git_pass(git_remote_connect(g_remote, GIT_DIRECTION_FETCH));
    cl_git_fail_with(GIT_ENOTFOUND, git_remote_default_branch(&buf, g_remote));

    cl_git_pass(git_clone(&cloned_repo, git_repository_path(g_repo_a), "./local-detached", NULL));

    cl_assert(git_repository_head_detached(cloned_repo));
    cl_git_pass(git_reference_name_to_id(&id_cloned, g_repo_a, "HEAD"));
    cl_assert(git_oid_equal(&id, &id_cloned));

    git_repository_free(cloned_repo);
}
Ejemplo n.º 7
0
PyObject *
Object_richcompare(PyObject *o1, PyObject *o2, int op)
{
    PyObject *res;
    Object *obj1;
    Object *obj2;

    if (!PyObject_TypeCheck(o2, &ObjectType)) {
        Py_INCREF(Py_NotImplemented);
        return Py_NotImplemented;
    }

    switch (op) {
        case Py_NE:
            obj1 = (Object *) o1;
            obj2 = (Object *) o2;
            if (git_oid_equal(git_object_id(obj1->obj), git_object_id(obj2->obj))) {
                res = Py_False;
            } else {
                res = Py_True;
            }
            break;
        case Py_EQ:
            obj1 = (Object *) o1;
            obj2 = (Object *) o2;
            if (git_oid_equal(git_object_id(obj1->obj), git_object_id(obj2->obj))) {
                res = Py_True;
            } else {
                res = Py_False;
            }
            break;
        case Py_LT:
        case Py_LE:
        case Py_GT:
        case Py_GE:
            Py_INCREF(Py_NotImplemented);
            return Py_NotImplemented;
        default:
            PyErr_Format(PyExc_RuntimeError, "Unexpected '%d' op", op);
            return NULL;
    }

    Py_INCREF(res);
    return res;
}
Ejemplo n.º 8
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);
}
Ejemplo n.º 9
0
static int try_to_update(git_repository *repo, git_remote *origin, git_reference *local, git_reference *remote, enum remote_transport rt)
{
	git_oid base;
	const git_oid *local_id, *remote_id;

	if (!git_reference_cmp(local, remote))
		return 0;

	// Dirty modified state in the working tree? We're not going
	// to update either way
	if (git_status_foreach(repo, check_clean, NULL))
		return report_error("local cached copy is dirty, skipping update");

	local_id = git_reference_target(local);
	remote_id = git_reference_target(remote);

	if (!local_id || !remote_id)
		return report_error("Unable to get local or remote SHA1");

	if (git_merge_base(&base, repo, local_id, remote_id))
		return report_error("Unable to find common commit of local and remote branches");

	/* Is the remote strictly newer? Use it */
	if (git_oid_equal(&base, local_id))
		return reset_to_remote(repo, local, remote_id);

	/* Is the local repo the more recent one? See if we can update upstream */
	if (git_oid_equal(&base, remote_id))
		return update_remote(repo, origin, local, remote, rt);

	/* Merging a bare repository always needs user action */
	if (git_repository_is_bare(repo))
		return report_error("Local and remote have diverged, merge of bare branch needed");

	/* Merging will definitely need the head branch too */
	if (git_branch_is_head(local) != 1)
		return report_error("Local and remote do not match, local branch not HEAD - cannot update");

	/* Ok, let's try to merge these */
	return try_to_git_merge(repo, local, remote, &base, local_id, remote_id);
}
Ejemplo n.º 10
0
void test_repo_hashfile__simple(void)
{
	git_oid a, b;
	git_buf full = GIT_BUF_INIT;

	/* hash with repo relative path */
	cl_git_pass(git_odb_hashfile(&a, "status/current_file", GIT_OBJ_BLOB));
	cl_git_pass(git_repository_hashfile(&b, _repo, "current_file", GIT_OBJ_BLOB, NULL));
	cl_assert(git_oid_equal(&a, &b));

	cl_git_pass(git_buf_joinpath(&full, git_repository_workdir(_repo), "current_file"));

	/* hash with full path */
	cl_git_pass(git_odb_hashfile(&a, full.ptr, GIT_OBJ_BLOB));
	cl_git_pass(git_repository_hashfile(&b, _repo, full.ptr, GIT_OBJ_BLOB, NULL));
	cl_assert(git_oid_equal(&a, &b));

	/* hash with invalid type */
	cl_git_fail(git_odb_hashfile(&a, full.ptr, GIT_OBJ_ANY));
	cl_git_fail(git_repository_hashfile(&b, _repo, full.ptr, GIT_OBJ_OFS_DELTA, NULL));

	git_buf_free(&full);
}
Ejemplo n.º 11
0
void test_odb_backend_simple__exists_prefix_succeeds(void)
{
	const fake_object objs[] = {
		{ "1234567890111111111111111111111111111111", "first content" },
		{ "1234567890222222222222222222222222222222", "second content" },
		{ NULL, NULL }
	};
	git_oid found;

	setup_backend(objs);

	cl_git_pass(git_oid_fromstr(&_oid, objs[0].oid));
	cl_git_pass(git_odb_exists_prefix(&found, _odb, &_oid, 12));
	cl_assert(git_oid_equal(&found, &_oid));
}
Ejemplo n.º 12
0
void test_odb_backend_simple__exists_with_highly_ambiguous_prefix(void)
{
	const fake_object objs[] = {
		{ "1234567890111111111111111111111111111111", "first content" },
		{ "1234567890111111111111111111111111111112", "second content" },
		{ NULL, NULL }
	};
	git_oid found;

	setup_backend(objs);

	cl_git_pass(git_oid_fromstr(&_oid, objs[0].oid));
	cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION, 0));
	cl_git_fail_with(GIT_EAMBIGUOUS, git_odb_exists_prefix(&found, _odb, &_oid, 39));
	cl_git_pass(git_odb_exists_prefix(&found, _odb, &_oid, 40));
	cl_assert(git_oid_equal(&found, &_oid));
}
Ejemplo n.º 13
0
static bool roundtrip_with_read_index(const char *tree_idstr)
{
	git_oid tree_id, new_tree_id;
	git_tree *tree;
	git_index *tree_index;

	cl_git_pass(git_oid_fromstr(&tree_id, tree_idstr));
	cl_git_pass(git_tree_lookup(&tree, _repo, &tree_id));
	cl_git_pass(git_index_new(&tree_index));
	cl_git_pass(git_index_read_tree(tree_index, tree));
	cl_git_pass(git_index_read_index(_index, tree_index));
	cl_git_pass(git_index_write_tree(&new_tree_id, _index));

	git_tree_free(tree);
	git_index_free(tree_index);

	return git_oid_equal(&tree_id, &new_tree_id);
}
Ejemplo n.º 14
0
static int try_to_update(git_repository *repo, git_remote *origin, git_reference *local, git_reference *remote,
			 const char *remote_url, const char *branch, enum remote_transport rt)
{
	git_oid base;
	const git_oid *local_id, *remote_id;
	int ret = 0;

	if (verbose)
		fprintf(stderr, "git storage: try to update\n");

	if (!git_reference_cmp(local, remote))
		return 0;

	// Dirty modified state in the working tree? We're not going
	// to update either way
	if (git_status_foreach(repo, check_clean, NULL)) {
		if (is_subsurface_cloud)
			goto cloud_data_error;
		else
			return report_error("local cached copy is dirty, skipping update");
	}
	local_id = git_reference_target(local);
	remote_id = git_reference_target(remote);

	if (!local_id || !remote_id) {
		if (is_subsurface_cloud)
			goto cloud_data_error;
		else
			return report_error("Unable to get local or remote SHA1");
	}
	if (git_merge_base(&base, repo, local_id, remote_id)) {
		// TODO:
		// if they have no merge base, they actually are different repos
		// so instead merge this as merging a commit into a repo - git_merge() appears to do that
		// but needs testing and cleanup afterwards
		//
		if (is_subsurface_cloud)
			goto cloud_data_error;
		else
			return report_error("Unable to find common commit of local and remote branches");
	}
	/* Is the remote strictly newer? Use it */
	if (git_oid_equal(&base, local_id)) {
		git_storage_update_progress(translate("gettextFromC", "Update local storage to match cloud storage"));
		return reset_to_remote(repo, local, remote_id);
	}

	/* Is the local repo the more recent one? See if we can update upstream */
	if (git_oid_equal(&base, remote_id)) {
		if (verbose)
			fprintf(stderr, "local is newer than remote, update remote\n");
		git_storage_update_progress(translate("gettextFromC", "Push local changes to cloud storage"));
		return update_remote(repo, origin, local, remote, rt);
	}
	/* Merging a bare repository always needs user action */
	if (git_repository_is_bare(repo)) {
		if (is_subsurface_cloud)
			goto cloud_data_error;
		else
			return report_error("Local and remote have diverged, merge of bare branch needed");
	}
	/* Merging will definitely need the head branch too */
	if (git_branch_is_head(local) != 1) {
		if (is_subsurface_cloud)
			goto cloud_data_error;
		else
			return report_error("Local and remote do not match, local branch not HEAD - cannot update");
	}
	/* Ok, let's try to merge these */
	git_storage_update_progress(translate("gettextFromC", "Try to merge local changes into cloud storage"));
	ret = try_to_git_merge(repo, &local, remote, &base, local_id, remote_id);
	if (ret == 0)
		return update_remote(repo, origin, local, remote, rt);
	else
		return ret;

cloud_data_error:
	// since we are working with Subsurface cloud storage we want to make the user interaction
	// as painless as possible. So if something went wrong with the local cache, tell the user
	// about it an move it away
	return cleanup_local_cache(remote_url, branch);
}
Ejemplo n.º 15
0
static int workdir_reader_read(
	git_buf *out,
	git_oid *out_id,
	git_filemode_t *out_filemode,
	git_reader *_reader,
	const char *filename)
{
	workdir_reader *reader = (workdir_reader *)_reader;
	git_buf path = GIT_BUF_INIT;
	struct stat st;
	git_filemode_t filemode;
	git_filter_list *filters = NULL;
	const git_index_entry *idx_entry;
	git_oid id;
	int error;

	if ((error = git_buf_joinpath(&path,
		git_repository_workdir(reader->repo), filename)) < 0)
		goto done;

	if ((error = p_lstat(path.ptr, &st)) < 0) {
		if (error == -1 && errno == ENOENT)
			error = GIT_ENOTFOUND;

		giterr_set(GITERR_OS, "could not stat '%s'", path.ptr);
		goto done;
	}

	filemode = git_futils_canonical_mode(st.st_mode);

	/*
	 * Patch application - for example - uses the filtered version of
	 * the working directory data to match git.  So we will run the
	 * workdir -> ODB filter on the contents in this workdir reader.
	 */
	if ((error = git_filter_list_load(&filters, reader->repo, NULL, filename,
		GIT_FILTER_TO_ODB, GIT_FILTER_DEFAULT)) < 0)
		goto done;

	if ((error = git_filter_list_apply_to_file(out,
	    filters, reader->repo, path.ptr)) < 0)
		goto done;

	if (out_id || reader->index) {
		if ((error = git_odb_hash(&id, out->ptr, out->size, GIT_OBJ_BLOB)) < 0)
			goto done;
	}

	if (reader->index) {
		if (!(idx_entry = git_index_get_bypath(reader->index, filename, 0)) ||
		    filemode != idx_entry->mode ||
		    !git_oid_equal(&id, &idx_entry->id)) {
			error = GIT_READER_MISMATCH;
			goto done;
		}
	}

	if (out_id)
		git_oid_cpy(out_id, &id);

	if (out_filemode)
		*out_filemode = filemode;

done:
	git_filter_list_free(filters);
	git_buf_dispose(&path);
	return error;
}
Ejemplo n.º 16
0
void test_odb_mixed__dup_oid_prefix_0(void) {
	char hex[10];
	git_oid oid, found;
	git_odb_object *obj;

	/* ambiguous in the same pack file */

	strncpy(hex, "dea509d0", sizeof(hex));
	cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex)));
	cl_assert_equal_i(
		GIT_EAMBIGUOUS, git_odb_read_prefix(&obj, _odb, &oid, strlen(hex)));
	cl_assert_equal_i(
		GIT_EAMBIGUOUS, git_odb_exists_prefix(&found, _odb, &oid, strlen(hex)));

	strncpy(hex, "dea509d09", sizeof(hex));
	cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex)));
	cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex)));
	cl_git_pass(git_odb_exists_prefix(&found, _odb, &oid, strlen(hex)));
	cl_assert(git_oid_equal(&found, git_odb_object_id(obj)));
	git_odb_object_free(obj);

	strncpy(hex, "dea509d0b", sizeof(hex));
	cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex)));
	cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex)));
	git_odb_object_free(obj);

	/* ambiguous in different pack files */

	strncpy(hex, "81b5bff5", sizeof(hex));
	cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex)));
	cl_assert_equal_i(
		GIT_EAMBIGUOUS, git_odb_read_prefix(&obj, _odb, &oid, strlen(hex)));
	cl_assert_equal_i(
		GIT_EAMBIGUOUS, git_odb_exists_prefix(&found, _odb, &oid, strlen(hex)));

	strncpy(hex, "81b5bff5b", sizeof(hex));
	cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex)));
	cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex)));
	cl_git_pass(git_odb_exists_prefix(&found, _odb, &oid, strlen(hex)));
	cl_assert(git_oid_equal(&found, git_odb_object_id(obj)));
	git_odb_object_free(obj);

	strncpy(hex, "81b5bff5f", sizeof(hex));
	cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex)));
	cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex)));
	git_odb_object_free(obj);

	/* ambiguous in pack file and loose */

	strncpy(hex, "0ddeaded", sizeof(hex));
	cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex)));
	cl_assert_equal_i(
		GIT_EAMBIGUOUS, git_odb_read_prefix(&obj, _odb, &oid, strlen(hex)));
	cl_assert_equal_i(
		GIT_EAMBIGUOUS, git_odb_exists_prefix(&found, _odb, &oid, strlen(hex)));

	strncpy(hex, "0ddeaded9", sizeof(hex));
	cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex)));
	cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex)));
	cl_git_pass(git_odb_exists_prefix(&found, _odb, &oid, strlen(hex)));
	cl_assert(git_oid_equal(&found, git_odb_object_id(obj)));
	git_odb_object_free(obj);

	strncpy(hex, "0ddeadede", sizeof(hex));
	cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex)));
	cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex)));
	git_odb_object_free(obj);
}
Ejemplo n.º 17
0
static int git_commit__create_internal(
    git_oid *id,
    git_repository *repo,
    const char *update_ref,
    const git_signature *author,
    const git_signature *committer,
    const char *message_encoding,
    const char *message,
    const git_oid *tree,
    git_commit_parent_callback parent_cb,
    void *parent_payload,
    bool validate)
{
    git_reference *ref = NULL;
    int error = 0, matched_parent = 0;
    const git_oid *current_id = NULL;
    git_buf commit = GIT_BUF_INIT;
    size_t i = 0;
    git_odb *odb;
    const git_oid *parent;

    assert(id && repo && tree && parent_cb);

    if (validate && !git_object__is_valid(repo, tree, GIT_OBJ_TREE))
        return -1;

    if (update_ref) {
        error = git_reference_lookup_resolved(&ref, repo, update_ref, 10);
        if (error < 0 && error != GIT_ENOTFOUND)
            return error;
    }
    giterr_clear();

    if (ref)
        current_id = git_reference_target(ref);

    git_oid__writebuf(&commit, "tree ", tree);

    while ((parent = parent_cb(i, parent_payload)) != NULL) {
        if (validate && !git_object__is_valid(repo, parent, GIT_OBJ_COMMIT)) {
            error = -1;
            goto on_error;
        }

        git_oid__writebuf(&commit, "parent ", parent);
        if (i == 0 && current_id && git_oid_equal(current_id, parent))
            matched_parent = 1;
        i++;
    }

    if (ref && !matched_parent) {
        git_reference_free(ref);
        git_buf_free(&commit);
        giterr_set(GITERR_OBJECT, "failed to create commit: current tip is not the first parent");
        return GIT_EMODIFIED;
    }

    git_signature__writebuf(&commit, "author ", author);
    git_signature__writebuf(&commit, "committer ", committer);

    if (message_encoding != NULL)
        git_buf_printf(&commit, "encoding %s\n", message_encoding);

    git_buf_putc(&commit, '\n');

    if (git_buf_puts(&commit, message) < 0)
        goto on_error;

    if (git_repository_odb__weakptr(&odb, repo) < 0)
        goto on_error;

    if (git_odb_write(id, odb, commit.ptr, commit.size, GIT_OBJ_COMMIT) < 0)
        goto on_error;

    git_buf_free(&commit);

    if (update_ref != NULL) {
        error = git_reference__update_for_commit(
                    repo, ref, update_ref, id, "commit");
        git_reference_free(ref);
        return error;
    }

    return 0;

on_error:
    git_buf_free(&commit);
    return -1;
}
Ejemplo n.º 18
0
static int rebase_commit__create(
	git_commit **out,
	git_rebase *rebase,
	git_index *index,
	git_commit *parent_commit,
	const git_signature *author,
	const git_signature *committer,
	const char *message_encoding,
	const char *message)
{
	git_rebase_operation *operation;
	git_commit *current_commit = NULL, *commit = NULL;
	git_tree *parent_tree = NULL, *tree = NULL;
	git_oid tree_id, commit_id;
	int error;

	operation = git_array_get(rebase->operations, rebase->current);

	if (git_index_has_conflicts(index)) {
		giterr_set(GITERR_REBASE, "conflicts have not been resolved");
		error = GIT_EUNMERGED;
		goto done;
	}

	if ((error = git_commit_lookup(&current_commit, rebase->repo, &operation->id)) < 0 ||
		(error = git_commit_tree(&parent_tree, parent_commit)) < 0 ||
		(error = git_index_write_tree_to(&tree_id, index, rebase->repo)) < 0 ||
		(error = git_tree_lookup(&tree, rebase->repo, &tree_id)) < 0)
		goto done;

	if (git_oid_equal(&tree_id, git_tree_id(parent_tree))) {
		giterr_set(GITERR_REBASE, "this patch has already been applied");
		error = GIT_EAPPLIED;
		goto done;
	}

	if (!author)
		author = git_commit_author(current_commit);

	if (!message) {
		message_encoding = git_commit_message_encoding(current_commit);
		message = git_commit_message(current_commit);
	}

	if ((error = git_commit_create(&commit_id, rebase->repo, NULL, author,
		committer, message_encoding, message, tree, 1,
		(const git_commit **)&parent_commit)) < 0 ||
		(error = git_commit_lookup(&commit, rebase->repo, &commit_id)) < 0)
		goto done;

	*out = commit;

done:
	if (error < 0)
		git_commit_free(commit);

	git_commit_free(current_commit);
	git_tree_free(parent_tree);
	git_tree_free(tree);

	return error;
}