commit - 102ff934b46daf842c7e393a017ab35d9449c577
commit + 2c7829a4ca20def05fcbfb4e1557e8f7abbf9c1b
blob - c9d5eab615151bbeb5480b7be1367ad4ea6e6f9b
blob + 7eb019a21f9eef0e5f7ea682d71c44f495124d79
--- got/got.1
+++ got/got.1
.Nm
are as follows:
.Bl -tag -width checkout
+.It Cm init Ar path
+Create a new empty repository at the specified
+.Ar path .
+If
+.Ar path
+already exists, it must be an empty directory.
.It Cm checkout [ Fl b Ar branch ] [ Fl c Ar commit ] [ Fl p Ar path-prefix ] repository-path [ work-tree-path ]
Copy files from a repository into a new work tree.
If the
blob - 01f304f9b44e4b62576f8d26aca2b3756f8d99b0
blob + b45405f0c457c310049eeec2fa105400ab12c10a
--- got/got.c
+++ got/got.c
};
__dead static void usage(void);
+__dead static void usage_init(void);
__dead static void usage_checkout(void);
__dead static void usage_update(void);
__dead static void usage_log(void);
__dead static void usage_cherrypick(void);
__dead static void usage_backout(void);
+static const struct got_error* cmd_init(int, char *[]);
static const struct got_error* cmd_checkout(int, char *[]);
static const struct got_error* cmd_update(int, char *[]);
static const struct got_error* cmd_log(int, char *[]);
static const struct got_error* cmd_backout(int, char *[]);
static struct cmd got_commands[] = {
+ { "init", cmd_init, usage_init,
+ "create a new empty repository" },
{ "checkout", cmd_checkout, usage_checkout,
"check out a new work tree from a repository" },
{ "update", cmd_update, usage_update,
return got_error_from_errno("unveil");
return NULL;
+}
+
+__dead static void
+usage_init(void)
+{
+ fprintf(stderr, "usage: %s init path\n", getprogname());
+ exit(1);
+}
+
+static const struct got_error *
+cmd_init(int argc, char *argv[])
+{
+ const struct got_error *error = NULL;
+ char *repo_path = NULL;
+ int ch;
+
+ while ((ch = getopt(argc, argv, "")) != -1) {
+ switch (ch) {
+ default:
+ usage_init();
+ /* NOTREACHED */
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+#ifndef PROFILE
+ if (pledge("stdio rpath wpath cpath unveil", NULL) == -1)
+ err(1, "pledge");
+#endif
+ if (argc != 1)
+ usage_checkout();
+
+ repo_path = strdup(argv[0]);
+ if (repo_path == NULL)
+ return got_error_from_errno("strdup");
+
+ got_path_strip_trailing_slashes(repo_path);
+
+ error = got_path_mkdir(repo_path);
+ if (error &&
+ !(error->code == GOT_ERR_ERRNO && errno == EEXIST))
+ goto done;
+
+ error = apply_unveil(repo_path, 0, NULL, 0);
+ if (error)
+ goto done;
+
+ error = got_repo_init(repo_path);
+ if (error != NULL)
+ goto done;
+
+done:
+ free(repo_path);
+ return error;
}
__dead static void
blob - 999fdf6ddce081722e9bfc9da58ae4feafdc6c18
blob + 0930f71c8146155d8882f672a15be677ed8eadc5
--- include/got_path.h
+++ include/got_path.h
/* Look up the absolute path of a program in $PATH */
const struct got_error *got_path_find_prog(char **, const char *);
+
+/* Create a new file at a specified path, with optional content. */
+const struct got_error *got_path_create_file(const char *, const char *);
blob - c026e9bdbd4e6a2294da9829b38751ccbf812f54
blob + 0b61b49e3ed0680170a01636840b554aac156059
--- include/got_repository.h
+++ include/got_repository.h
/* Attempt to map an arbitrary path to a path within the repository. */
const struct got_error *got_repo_map_path(char **, struct got_repository *,
const char *, int);
+
+/* Create a new repository in an empty directory at a specified path. */
+const struct got_error *got_repo_init(const char *);
blob - a0cd8335240385644aab73fbf3221f9c2da0960c
blob + fb283d460760a9d031f838d8fb9053fc63930ebd
--- lib/path.c
+++ lib/path.c
#include <sys/stat.h>
#include <errno.h>
+#include <fcntl.h>
#include <limits.h>
#include <libgen.h>
#include <stdlib.h>
}
free(path);
return NULL;
+}
+
+const struct got_error *
+got_path_create_file(const char *path, const char *content)
+{
+ const struct got_error *err = NULL;
+ int fd = -1;
+
+ fd = open(path, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW,
+ GOT_DEFAULT_FILE_MODE);
+ if (fd == -1) {
+ err = got_error_from_errno2("open", path);
+ goto done;
+ }
+
+ if (content) {
+ int len = dprintf(fd, "%s\n", content);
+ if (len != strlen(content) + 1) {
+ err = got_error_from_errno("dprintf");
+ goto done;
+ }
+ }
+
+done:
+ if (fd != -1 && close(fd) == -1 && err == NULL)
+ err = got_error_from_errno("close");
+ return err;
}
blob - 0277a4437dc809ba033a7083ce7d917e0a36fd81
blob + 3e583b28ea58e79e805fdf160253840f7f33b6da
--- lib/repository.c
+++ lib/repository.c
break;
if (strcmp(pack->path_packfile, path_packfile) == 0)
return pack;
+ }
+
+ return NULL;
+}
+
+const struct got_error *
+got_repo_init(const char *repo_path)
+{
+ const struct got_error *err = NULL;
+ const char *dirnames[] = {
+ GOT_OBJECTS_DIR,
+ GOT_OBJECTS_PACK_DIR,
+ GOT_REFS_DIR,
+ };
+ const char *description_str = "Unnamed repository; "
+ "edit this file 'description' to name the repository.";
+ const char *headref_str = "ref: refs/heads/master";
+ const char *gitconfig_str = "[core]\n"
+ "\trepositoryformatversion = 0\n"
+ "\tfilemode = true\n"
+ "\tbare = true\n";
+ char *path;
+ int i;
+
+ if (!got_path_dir_is_empty(repo_path))
+ return got_error(GOT_ERR_DIR_NOT_EMPTY);
+
+ for (i = 0; i < nitems(dirnames); i++) {
+ if (asprintf(&path, "%s/%s", repo_path, dirnames[i]) == -1) {
+ return got_error_from_errno("asprintf");
+ }
+ err = got_path_mkdir(path);
+ free(path);
+ if (err)
+ return err;
}
+ if (asprintf(&path, "%s/%s", repo_path, "description") == -1)
+ return got_error_from_errno("asprintf");
+ err = got_path_create_file(path, description_str);
+ free(path);
+ if (err)
+ return err;
+
+ if (asprintf(&path, "%s/%s", repo_path, GOT_HEAD_FILE) == -1)
+ return got_error_from_errno("asprintf");
+ err = got_path_create_file(path, headref_str);
+ free(path);
+ if (err)
+ return err;
+
+ if (asprintf(&path, "%s/%s", repo_path, "config") == -1)
+ return got_error_from_errno("asprintf");
+ err = got_path_create_file(path, gitconfig_str);
+ free(path);
+ if (err)
+ return err;
+
return NULL;
}
blob - 9c8e0f6aa7469f287229ba2c42433b98972f6c62
blob + b0e00b1694127e0786c2ba99bebc3d6873e007a3
--- lib/worktree.c
+++ lib/worktree.c
{
const struct got_error *err = NULL;
char *path;
- int fd = -1;
- if (asprintf(&path, "%s/%s", path_got, name) == -1) {
- err = got_error_from_errno("asprintf");
- path = NULL;
- goto done;
- }
-
- fd = open(path, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW,
- GOT_DEFAULT_FILE_MODE);
- if (fd == -1) {
- err = got_error_from_errno2("open", path);
- goto done;
- }
+ if (asprintf(&path, "%s/%s", path_got, name) == -1)
+ return got_error_from_errno("asprintf");
- if (content) {
- int len = dprintf(fd, "%s\n", content);
- if (len != strlen(content) + 1) {
- err = got_error_from_errno("dprintf");
- goto done;
- }
- }
-
-done:
- if (fd != -1 && close(fd) == -1 && err == NULL)
- err = got_error_from_errno("close");
+ err = got_path_create_file(path, content);
free(path);
return err;
}