Commit 93a3027739b17cdd9bccd7bda53f581b919b87ea

Stefan Sperling 2018-12-24T20:11:47

make got_worktree_checkout_files() infer base commit from meta data

diff --git a/got/got.c b/got/got.c
index 4f7d237..fec08d6 100644
--- a/got/got.c
+++ b/got/got.c
@@ -283,7 +283,7 @@ cmd_checkout(int argc, char *argv[])
 	if (error != NULL)
 		goto done;
 
-	error = got_worktree_checkout_files(worktree, head_ref, repo,
+	error = got_worktree_checkout_files(worktree, repo,
 	    checkout_progress, worktree_path, checkout_cancel, NULL);
 	if (error != NULL)
 		goto done;
diff --git a/include/got_worktree.h b/include/got_worktree.h
index 806d598..06af45d 100644
--- a/include/got_worktree.h
+++ b/include/got_worktree.h
@@ -21,8 +21,8 @@ struct got_worktree;
  * The first argument is the path to a directory where the work tree
  * will be created. The path itself must not yet exist, but the dirname(3)
  * of the path must already exist.
- * The reference provided will be used as the new worktree's HEAD.
- * The third argument speficies the work tree's path prefix.
+ * The reference provided will be used to determine the new worktree's
+ * base commit. The third argument speficies the work tree's path prefix.
  */
 const struct got_error *got_worktree_init(const char *, struct got_reference *,
     const char *, struct got_repository *);
@@ -59,11 +59,10 @@ typedef const struct got_error *(*got_worktree_cancel_cb)(void *);
  * Attempt to check out files into a work tree from its associated repository
  * and path prefix, and update the work tree's file index accordingly.
  * File content is obtained from blobs within the work tree's path prefix
- * inside the tree resolved via the provided reference.
+ * inside the tree corresponding to the work tree's base commit.
  * The checkout progress callback will be invoked with the provided
  * void * argument, and the path of each checked out file.
  */
 const struct got_error *got_worktree_checkout_files(struct got_worktree *,
-    struct got_reference *, struct got_repository *,
-    got_worktree_checkout_cb progress, void *,
+    struct got_repository *, got_worktree_checkout_cb progress, void *,
     got_worktree_cancel_cb, void *);
diff --git a/lib/got_lib_worktree.h b/lib/got_lib_worktree.h
index f308ade..75906a3 100644
--- a/lib/got_lib_worktree.h
+++ b/lib/got_lib_worktree.h
@@ -18,7 +18,7 @@ struct got_worktree {
 	char *root_path;
 	char *repo_path;
 	char *path_prefix;
-	char *base_commit;
+	char *base;
 	char *head_ref;
 
 	/*
diff --git a/lib/worktree.c b/lib/worktree.c
index f44df5b..673aed2 100644
--- a/lib/worktree.c
+++ b/lib/worktree.c
@@ -324,6 +324,10 @@ got_worktree_open(struct got_worktree **worktree, const char *path)
 	if (err)
 		goto done;
 
+	err = read_meta_file(&(*worktree)->base, path_got, GOT_WORKTREE_BASE);
+	if (err)
+		goto done;
+
 	err = read_meta_file(&(*worktree)->head_ref, path_got,
 	    GOT_WORKTREE_HEAD);
 	if (err)
@@ -350,7 +354,7 @@ got_worktree_close(struct got_worktree *worktree)
 	free(worktree->root_path);
 	free(worktree->repo_path);
 	free(worktree->path_prefix);
-	free(worktree->base_commit);
+	free(worktree->base);
 	free(worktree->head_ref);
 	if (worktree->lockfd != -1)
 		close(worktree->lockfd);
@@ -603,13 +607,11 @@ tree_checkout(struct got_worktree *worktree,
 
 const struct got_error *
 got_worktree_checkout_files(struct got_worktree *worktree,
-    struct got_reference *head_ref, struct got_repository *repo,
-    got_worktree_checkout_cb progress_cb, void *progress_arg,
-    got_worktree_cancel_cb cancel_cb, void *cancel_arg)
+    struct got_repository *repo, got_worktree_checkout_cb progress_cb,
+    void *progress_arg, got_worktree_cancel_cb cancel_cb, void *cancel_arg)
 {
 	const struct got_error *err = NULL, *unlockerr;
 	struct got_object_id *commit_id = NULL;
-	struct got_object *obj = NULL;
 	struct got_commit_object *commit = NULL;
 	struct got_tree_object *tree = NULL;
 	char *fileindex_path = NULL, *new_fileindex_path = NULL;
@@ -620,6 +622,10 @@ got_worktree_checkout_files(struct got_worktree *worktree,
 	if (err)
 		return err;
 
+	err = got_object_resolve_id_str(&commit_id, repo, worktree->base);
+	if (err)
+		goto done;
+
 	fileindex = got_fileindex_alloc();
 	if (fileindex == NULL) {
 		err = got_error_from_errno();
@@ -638,34 +644,11 @@ got_worktree_checkout_files(struct got_worktree *worktree,
 	if (err)
 		goto done;
 
-	err = got_ref_resolve(&commit_id, repo, head_ref);
+	err = got_object_open_as_commit(&commit, repo, commit_id);
 	if (err)
 		goto done;
 
-	err = got_object_open(&obj, repo, commit_id);
-	if (err)
-		goto done;
-
-	if (obj->type != GOT_OBJ_TYPE_COMMIT) {
-		err = got_error(GOT_ERR_OBJ_TYPE);
-		goto done;
-	}
-
-	err = got_object_commit_open(&commit, repo, obj);
-	if (err)
-		goto done;
-
-	got_object_close(obj);
-	err = got_object_open(&obj, repo, commit->tree_id);
-	if (err)
-		goto done;
-
-	if (obj->type != GOT_OBJ_TYPE_TREE) {
-		err = got_error(GOT_ERR_OBJ_TYPE);
-		goto done;
-	}
-
-	err = got_object_tree_open(&tree, repo, obj);
+	err = got_object_open_as_tree(&tree, repo, commit->tree_id);
 	if (err)
 		goto done;
 
@@ -691,8 +674,6 @@ done:
 		got_object_tree_close(tree);
 	if (commit)
 		got_object_commit_close(commit);
-	if (obj)
-		got_object_close(obj);
 	free(commit_id);
 	if (new_fileindex_path)
 		unlink(new_fileindex_path);
diff --git a/regress/worktree/worktree_test.c b/regress/worktree/worktree_test.c
index 5157cfd..476ab3d 100644
--- a/regress/worktree/worktree_test.c
+++ b/regress/worktree/worktree_test.c
@@ -341,8 +341,8 @@ worktree_checkout(const char *repo_path)
 	if (err != NULL)
 		goto done;
 
-	err = got_worktree_checkout_files(worktree, head_ref, repo,
-	    process_cb, NULL, NULL, NULL);
+	err = got_worktree_checkout_files(worktree, repo, process_cb, NULL,
+	    NULL, NULL);
 	if (err != NULL)
 		goto done;