summaryrefslogtreecommitdiff
path: root/examples/init.c
diff options
context:
space:
mode:
authorVicent Martí <vicent@github.com>2013-11-01 09:38:34 -0700
committerVicent Martí <vicent@github.com>2013-11-01 09:38:34 -0700
commit567649f2ada60e5c3009cc985af238b452b14a81 (patch)
tree12a19dd97c05818557228ed2b3fcc36e183959b2 /examples/init.c
parent948f00b4e79bb60c68e03342500013246e642ae6 (diff)
parent4f62d55968d4a22a6ea03194aa34ab1b6ca8fdea (diff)
downloadlibgit2-567649f2ada60e5c3009cc985af238b452b14a81.tar.gz
Merge pull request #1916 from libgit2/simplify-examples
Fix examples to make the important stuff more obvious
Diffstat (limited to 'examples/init.c')
-rw-r--r--examples/init.c289
1 files changed, 145 insertions, 144 deletions
diff --git a/examples/init.c b/examples/init.c
index 4a379c6e3..1c371252e 100644
--- a/examples/init.c
+++ b/examples/init.c
@@ -1,4 +1,13 @@
/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+
+#include "common.h"
+
+/**
* This is a sample program that is similar to "git init". See the
* documentation for that (try "git help init") to understand what this
* program is emulating.
@@ -8,179 +17,93 @@
* This also contains a special additional option that regular "git init"
* does not support which is "--initial-commit" to make a first empty commit.
* That is demonstrated in the "create_initial_commit" helper function.
- *
- * Copyright (C) the libgit2 contributors. All rights reserved.
- *
- * This file is part of libgit2, distributed under the GNU GPL v2 with
- * a Linking Exception. For full terms see the included COPYING file.
*/
-#include <stdio.h>
-#include <git2.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-/* not actually good error handling */
-static void fail(const char *msg, const char *arg)
-{
- if (arg)
- fprintf(stderr, "%s %s\n", msg, arg);
- else
- fprintf(stderr, "%s\n", msg);
- exit(1);
-}
-
-static void usage(const char *error, const char *arg)
-{
- fprintf(stderr, "error: %s '%s'\n", error, arg);
- fprintf(stderr, "usage: init [-q | --quiet] [--bare] "
- "[--template=<dir>] [--shared[=perms]] <directory>\n");
- exit(1);
-}
-
-/* simple string prefix test used in argument parsing */
-static size_t is_prefixed(const char *arg, const char *pfx)
-{
- size_t len = strlen(pfx);
- return !strncmp(arg, pfx, len) ? len : 0;
-}
-
-/* parse the tail of the --shared= argument */
-static uint32_t parse_shared(const char *shared)
-{
- if (!strcmp(shared, "false") || !strcmp(shared, "umask"))
- return GIT_REPOSITORY_INIT_SHARED_UMASK;
-
- else if (!strcmp(shared, "true") || !strcmp(shared, "group"))
- return GIT_REPOSITORY_INIT_SHARED_GROUP;
-
- else if (!strcmp(shared, "all") || !strcmp(shared, "world") ||
- !strcmp(shared, "everybody"))
- return GIT_REPOSITORY_INIT_SHARED_ALL;
-
- else if (shared[0] == '0') {
- long val;
- char *end = NULL;
- val = strtol(shared + 1, &end, 8);
- if (end == shared + 1 || *end != 0)
- usage("invalid octal value for --shared", shared);
- return (uint32_t)val;
- }
-
- else
- usage("unknown value for --shared", shared);
-
- return 0;
-}
-
-/* forward declaration of helper to make an empty parent-less commit */
+/** Forward declarations of helpers */
+struct opts {
+ int no_options;
+ int quiet;
+ int bare;
+ int initial_commit;
+ uint32_t shared;
+ const char *template;
+ const char *gitdir;
+ const char *dir;
+};
static void create_initial_commit(git_repository *repo);
+static void parse_opts(struct opts *o, int argc, char *argv[]);
int main(int argc, char *argv[])
{
git_repository *repo = NULL;
- int no_options = 1, quiet = 0, bare = 0, initial_commit = 0, i;
- uint32_t shared = GIT_REPOSITORY_INIT_SHARED_UMASK;
- const char *template = NULL, *gitdir = NULL, *dir = NULL;
- size_t pfxlen;
+ struct opts o = { 1, 0, 0, 0, GIT_REPOSITORY_INIT_SHARED_UMASK, 0, 0, 0 };
git_threads_init();
- /* Process arguments */
+ parse_opts(&o, argc, argv);
- for (i = 1; i < argc; ++i) {
- char *a = argv[i];
+ /* Initialize repository. */
- if (a[0] == '-')
- no_options = 0;
-
- if (a[0] != '-') {
- if (dir != NULL)
- usage("extra argument", a);
- dir = a;
- }
- else if (!strcmp(a, "-q") || !strcmp(a, "--quiet"))
- quiet = 1;
- else if (!strcmp(a, "--bare"))
- bare = 1;
- else if ((pfxlen = is_prefixed(a, "--template=")) > 0)
- template = a + pfxlen;
- else if (!strcmp(a, "--separate-git-dir"))
- gitdir = argv[++i];
- else if ((pfxlen = is_prefixed(a, "--separate-git-dir=")) > 0)
- gitdir = a + pfxlen;
- else if (!strcmp(a, "--shared"))
- shared = GIT_REPOSITORY_INIT_SHARED_GROUP;
- else if ((pfxlen = is_prefixed(a, "--shared=")) > 0)
- shared = parse_shared(a + pfxlen);
- else if (!strcmp(a, "--initial-commit"))
- initial_commit = 1;
- else
- usage("unknown option", a);
- }
-
- if (!dir)
- usage("must specify directory to init", NULL);
-
- /* Initialize repository */
-
- if (no_options) {
- /* No options were specified, so let's demonstrate the default
+ if (o.no_options) {
+ /**
+ * No options were specified, so let's demonstrate the default
* simple case of git_repository_init() API usage...
*/
-
- if (git_repository_init(&repo, dir, 0) < 0)
- fail("Could not initialize repository", dir);
+ check_lg2(git_repository_init(&repo, o.dir, 0),
+ "Could not initialize repository", NULL);
}
else {
- /* Some command line options were specified, so we'll use the
+ /**
+ * Some command line options were specified, so we'll use the
* extended init API to handle them
*/
- git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
+ git_repository_init_options initopts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
+ initopts.flags = GIT_REPOSITORY_INIT_MKPATH;
- if (bare)
- opts.flags |= GIT_REPOSITORY_INIT_BARE;
+ if (o.bare)
+ initopts.flags |= GIT_REPOSITORY_INIT_BARE;
- if (template) {
- opts.flags |= GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE;
- opts.template_path = template;
+ if (o.template) {
+ initopts.flags |= GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE;
+ initopts.template_path = o.template;
}
- if (gitdir) {
- /* if you specified a separate git directory, then initialize
+ if (o.gitdir) {
+ /**
+ * If you specified a separate git directory, then initialize
* the repository at that path and use the second path as the
* working directory of the repository (with a git-link file)
*/
- opts.workdir_path = dir;
- dir = gitdir;
+ initopts.workdir_path = o.dir;
+ o.dir = o.gitdir;
}
- if (shared != 0)
- opts.mode = shared;
+ if (o.shared != 0)
+ initopts.mode = o.shared;
- if (git_repository_init_ext(&repo, dir, &opts) < 0)
- fail("Could not initialize repository", dir);
+ check_lg2(git_repository_init_ext(&repo, o.dir, &initopts),
+ "Could not initialize repository", NULL);
}
- /* Print a message to stdout like "git init" does */
+ /** Print a message to stdout like "git init" does. */
- if (!quiet) {
- if (bare || gitdir)
- dir = git_repository_path(repo);
+ if (!o.quiet) {
+ if (o.bare || o.gitdir)
+ o.dir = git_repository_path(repo);
else
- dir = git_repository_workdir(repo);
+ o.dir = git_repository_workdir(repo);
- printf("Initialized empty Git repository in %s\n", dir);
+ printf("Initialized empty Git repository in %s\n", o.dir);
}
- /* As an extension to the basic "git init" command, this example
+ /**
+ * As an extension to the basic "git init" command, this example
* gives the option to create an empty initial commit. This is
* mostly to demonstrate what it takes to do that, but also some
* people like to have that empty base commit in their repo.
*/
- if (initial_commit) {
+ if (o.initial_commit) {
create_initial_commit(repo);
printf("Created empty initial commit\n");
}
@@ -191,7 +114,8 @@ int main(int argc, char *argv[])
return 0;
}
-/* Unlike regular "git init", this example shows how to create an initial
+/**
+ * Unlike regular "git init", this example shows how to create an initial
* empty commit in the repository. This is the helper function that does
* that.
*/
@@ -202,31 +126,33 @@ static void create_initial_commit(git_repository *repo)
git_oid tree_id, commit_id;
git_tree *tree;
- /* First use the config to initialize a commit signature for the user */
+ /** First use the config to initialize a commit signature for the user. */
if (git_signature_default(&sig, repo) < 0)
- fail("Unable to create a commit signature.",
- "Perhaps 'user.name' and 'user.email' are not set");
+ fatal("Unable to create a commit signature.",
+ "Perhaps 'user.name' and 'user.email' are not set");
/* Now let's create an empty tree for this commit */
if (git_repository_index(&index, repo) < 0)
- fail("Could not open repository index", NULL);
+ fatal("Could not open repository index", NULL);
- /* Outside of this example, you could call git_index_add_bypath()
+ /**
+ * Outside of this example, you could call git_index_add_bypath()
* here to put actual files into the index. For our purposes, we'll
* leave it empty for now.
*/
if (git_index_write_tree(&tree_id, index) < 0)
- fail("Unable to write initial tree from index", NULL);
+ fatal("Unable to write initial tree from index", NULL);
git_index_free(index);
if (git_tree_lookup(&tree, repo, &tree_id) < 0)
- fail("Could not look up initial tree", NULL);
+ fatal("Could not look up initial tree", NULL);
- /* Ready to create the initial commit
+ /**
+ * Ready to create the initial commit.
*
* Normally creating a commit would involve looking up the current
* HEAD commit and making that be the parent of the initial commit,
@@ -236,10 +162,85 @@ static void create_initial_commit(git_repository *repo)
if (git_commit_create_v(
&commit_id, repo, "HEAD", sig, sig,
NULL, "Initial commit", tree, 0) < 0)
- fail("Could not create the initial commit", NULL);
+ fatal("Could not create the initial commit", NULL);
- /* Clean up so we don't leak memory */
+ /** Clean up so we don't leak memory. */
git_tree_free(tree);
git_signature_free(sig);
}
+
+static void usage(const char *error, const char *arg)
+{
+ fprintf(stderr, "error: %s '%s'\n", error, arg);
+ fprintf(stderr,
+ "usage: init [-q | --quiet] [--bare] [--template=<dir>]\n"
+ " [--shared[=perms]] [--initial-commit]\n"
+ " [--separate-git-dir] <directory>\n");
+ exit(1);
+}
+
+/** Parse the tail of the --shared= argument. */
+static uint32_t parse_shared(const char *shared)
+{
+ if (!strcmp(shared, "false") || !strcmp(shared, "umask"))
+ return GIT_REPOSITORY_INIT_SHARED_UMASK;
+
+ else if (!strcmp(shared, "true") || !strcmp(shared, "group"))
+ return GIT_REPOSITORY_INIT_SHARED_GROUP;
+
+ else if (!strcmp(shared, "all") || !strcmp(shared, "world") ||
+ !strcmp(shared, "everybody"))
+ return GIT_REPOSITORY_INIT_SHARED_ALL;
+
+ else if (shared[0] == '0') {
+ long val;
+ char *end = NULL;
+ val = strtol(shared + 1, &end, 8);
+ if (end == shared + 1 || *end != 0)
+ usage("invalid octal value for --shared", shared);
+ return (uint32_t)val;
+ }
+
+ else
+ usage("unknown value for --shared", shared);
+
+ return 0;
+}
+
+static void parse_opts(struct opts *o, int argc, char *argv[])
+{
+ struct args_info args = ARGS_INFO_INIT;
+ const char *sharedarg;
+
+ /** Process arguments. */
+
+ for (args.pos = 1; args.pos < argc; ++args.pos) {
+ char *a = argv[args.pos];
+
+ if (a[0] == '-')
+ o->no_options = 0;
+
+ if (a[0] != '-') {
+ if (o->dir != NULL)
+ usage("extra argument", a);
+ o->dir = a;
+ }
+ else if (!strcmp(a, "-q") || !strcmp(a, "--quiet"))
+ o->quiet = 1;
+ else if (!strcmp(a, "--bare"))
+ o->bare = 1;
+ else if (!strcmp(a, "--shared"))
+ o->shared = GIT_REPOSITORY_INIT_SHARED_GROUP;
+ else if (!strcmp(a, "--initial-commit"))
+ o->initial_commit = 1;
+ else if (match_str_arg(&sharedarg, &args, "--shared"))
+ o->shared = parse_shared(sharedarg);
+ else if (!match_str_arg(&o->template, &args, "--template") ||
+ !match_str_arg(&o->gitdir, &args, "--separate-git-dir"))
+ usage("unknown option", a);
+ }
+
+ if (!o->dir)
+ usage("must specify directory to init", NULL);
+}