add a 'got checkout' command
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
diff --git a/got/Makefile b/got/Makefile
index 1336114..8e74120 100644
--- a/got/Makefile
+++ b/got/Makefile
@@ -1,8 +1,8 @@
.PATH:${.CURDIR}/../lib
PROG= got
-SRCS= got.c delta.c error.c object.c path.c pack.c refs.c \
- repository.c sha1.c zbuf.c
+SRCS= got.c delta.c error.c fileindex.c object.c path.c pack.c \
+ refs.c repository.c sha1.c worktree.c zbuf.c
CPPFLAGS = -I${.CURDIR}/../include -I${.CURDIR}/../lib
LDADD = -lutil -lz
diff --git a/got/got.c b/got/got.c
index ac347fd..8d6ac0c 100644
--- a/got/got.c
+++ b/got/got.c
@@ -24,11 +24,13 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <libgen.h>
#include "got_error.h"
#include "got_object.h"
#include "got_refs.h"
#include "got_repository.h"
+#include "got_worktree.h"
#ifndef nitems
#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
@@ -42,12 +44,16 @@ struct cmd {
};
__dead void usage(void);
+__dead void usage_checkout(void);
__dead void usage_log(void);
+const struct got_error* cmd_checkout(int, char *[]);
const struct got_error* cmd_log(int, char *[]);
const struct got_error* cmd_status(int, char *[]);
struct cmd got_commands[] = {
+ { "checkout", cmd_checkout, usage_checkout,
+ "check out a work tree from a repository" },
{ "log", cmd_log, usage_log,
"show repository history" },
#ifdef notyet
@@ -66,9 +72,6 @@ main(int argc, char *argv[])
setlocale(LC_ALL, "");
- if (pledge("stdio rpath wpath cpath", NULL) == -1)
- err(1, "pledge");
-
while ((ch = getopt(argc, argv, "h")) != -1) {
switch (ch) {
case 'h':
@@ -124,6 +127,80 @@ usage(void)
exit(1);
}
+__dead void
+usage_checkout(void)
+{
+ fprintf(stderr, "usage: %s checkout REPO_PATH [WORKTREE_PATH]\n",
+ getprogname());
+ exit(1);
+}
+
+const struct got_error *
+cmd_checkout(int argc, char *argv[])
+{
+ const struct got_error *error = NULL;
+ struct got_repository *repo = NULL;
+ struct got_reference *head_ref = NULL;
+ struct got_worktree *worktree = NULL;
+ char *repo_path = NULL;
+ char *worktree_path = NULL;
+
+ if (pledge("stdio rpath wpath cpath flock", NULL) == -1)
+ err(1, "pledge");
+
+ if (argc == 2) {
+ char *cwd, *base, *dotgit;
+ repo_path = argv[1];
+ cwd = getcwd(NULL, 0);
+ if (cwd == NULL)
+ err(1, "getcwd");
+ base = basename(repo_path);
+ if (base == NULL)
+ err(1, "basename");
+ dotgit = strstr(base, ".git");
+ if (dotgit)
+ *dotgit = '\0';
+ if (asprintf(&worktree_path, "%s/%s", cwd, base) == -1) {
+ free(cwd);
+ return got_error(GOT_ERR_NO_MEM);
+ }
+ free(cwd);
+ } else if (argc == 3) {
+ repo_path = argv[1];
+ worktree_path = strdup(argv[2]);
+ if (worktree_path == NULL)
+ return got_error(GOT_ERR_NO_MEM);
+ } else
+ usage_checkout();
+
+ printf("%s %s %s %s\n", getprogname(), argv[0], repo_path, worktree_path);
+
+ error = got_repo_open(&repo, repo_path);
+ if (error != NULL)
+ goto done;
+ error = got_ref_open(&head_ref, repo, GOT_REF_HEAD);
+ if (error != NULL)
+ goto done;
+
+ error = got_worktree_init(worktree_path, head_ref, "/", repo);
+ if (error != NULL)
+ goto done;
+
+ error = got_worktree_open(&worktree, worktree_path);
+ if (error != NULL)
+ goto done;
+
+ error = got_worktree_checkout_files(worktree, head_ref, repo);
+ if (error != NULL)
+ goto done;
+
+ printf("checked out %s\n", worktree_path);
+
+done:
+ free(worktree_path);
+ return error;
+}
+
static const struct got_error *
print_commit_object(struct got_object *, struct got_object_id *,
struct got_repository *);