Skip to content

Commit cc3b82e

Browse files
committed
Merge pull request libgit2#151 from carlosmn/root-commit.
Support root commits
2 parents fde9766 + 79b6155 commit cc3b82e

File tree

3 files changed

+81
-3
lines changed

3 files changed

+81
-3
lines changed

src/commit.c

+11-2
Original file line numberDiff line numberDiff line change
@@ -224,9 +224,18 @@ int git_commit_create(
224224
if (error < GIT_SUCCESS)
225225
return error;
226226

227-
if (git_reference_type(head) == GIT_REF_SYMBOLIC) {
228-
if ((error = git_reference_resolve(&head, head)) < GIT_SUCCESS)
227+
error = git_reference_resolve(&head, head);
228+
if (error < GIT_SUCCESS) {
229+
if (error != GIT_ENOTFOUND)
229230
return error;
231+
/*
232+
* The target of the reference was not found. This can happen
233+
* just after a repository has been initialized (the master
234+
* branch doesn't exist yet, as it doesn't have anything to
235+
* point to) or after an orphan checkout, so if the target
236+
* branch doesn't exist yet, create it and return.
237+
*/
238+
return git_reference_create_oid_f(&head, repo, git_reference_target(head), oid);
230239
}
231240

232241
error = git_reference_set_oid(head, oid);

src/refs.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -1482,8 +1482,9 @@ int git_reference_resolve(git_reference **resolved_ref, git_reference *ref)
14821482
for (i = 0; i < MAX_NESTING_LEVEL; ++i) {
14831483
reference_symbolic *ref_sym;
14841484

1485+
*resolved_ref = ref;
1486+
14851487
if (ref->type & GIT_REF_OID) {
1486-
*resolved_ref = ref;
14871488
return GIT_SUCCESS;
14881489
}
14891490

tests/t04-commit.c

+68
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,72 @@ BEGIN_TEST(write0, "write a new commit object from memory to disk")
474474
git_repository_free(repo);
475475
END_TEST
476476

477+
#define ROOT_COMMIT_MESSAGE "This is a root commit\n\
478+
This is a root commit and should be the only one in this branch\n"
479+
480+
BEGIN_TEST(root0, "create a root commit")
481+
git_repository *repo;
482+
git_commit *commit;
483+
git_oid tree_id, commit_id;
484+
const git_oid *branch_oid;
485+
const git_signature *author, *committer;
486+
const char *branch_name = "refs/heads/root-commit-branch";
487+
git_reference *head, *branch;
488+
char *head_old;
489+
490+
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
491+
492+
git_oid_mkstr(&tree_id, tree_oid);
493+
494+
/* create signatures */
495+
committer = git_signature_new(COMMITTER_NAME, COMMITTER_EMAIL, 123456789, 60);
496+
must_be_true(committer != NULL);
497+
498+
author = git_signature_new(COMMITTER_NAME, COMMITTER_EMAIL, 987654321, 90);
499+
must_be_true(author != NULL);
500+
501+
/* First we need to update HEAD so it points to our non-existant branch */
502+
must_pass(git_reference_lookup(&head, repo, "HEAD"));
503+
must_be_true(git_reference_type(head) == GIT_REF_SYMBOLIC);
504+
head_old = git__strdup(git_reference_target(head));
505+
must_be_true(head_old != NULL);
506+
507+
must_pass(git_reference_set_target(head, branch_name));
508+
509+
must_pass(git_commit_create_v(
510+
&commit_id, /* out id */
511+
repo,
512+
"HEAD",
513+
author,
514+
committer,
515+
ROOT_COMMIT_MESSAGE,
516+
&tree_id,
517+
0));
518+
519+
git_signature_free((git_signature *)committer);
520+
git_signature_free((git_signature *)author);
521+
522+
/*
523+
* The fact that creating a commit works has already been
524+
* tested. Here we just make sure it's our commit and that it was
525+
* written as a root commit.
526+
*/
527+
must_pass(git_commit_lookup(&commit, repo, &commit_id));
528+
must_be_true(git_commit_parentcount(commit) == 0);
529+
must_pass(git_reference_lookup(&branch, repo, branch_name));
530+
branch_oid = git_reference_oid(branch);
531+
must_pass(git_oid_cmp(branch_oid, &commit_id));
532+
must_be_true(!strcmp(git_commit_message(commit), ROOT_COMMIT_MESSAGE));
533+
534+
/* Remove the data we just added to the repo */
535+
must_pass(git_reference_lookup(&head, repo, "HEAD"));
536+
must_pass(git_reference_set_target(head, head_old));
537+
must_pass(git_reference_delete(branch));
538+
must_pass(remove_loose_object(REPOSITORY_FOLDER, (git_object *)commit));
539+
free(head_old);
540+
git_commit_close(commit);
541+
git_repository_free(repo);
542+
END_TEST
477543

478544
BEGIN_SUITE(commit)
479545
ADD_TEST(parse0);
@@ -483,4 +549,6 @@ BEGIN_SUITE(commit)
483549

484550
ADD_TEST(write0);
485551
//ADD_TEST(write1);
552+
553+
ADD_TEST(root0);
486554
END_SUITE

0 commit comments

Comments
 (0)