examples: implement git-stash example Implement a new example that resembles the git-stash(1) command. Right now, it only provides the apply, list, save and pop subcommands without any options. This example is mostly used to test libgit2's stashing performance on big repositories.
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 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
diff --git a/examples/common.h b/examples/common.h
index 724a5c0..dcc662d 100644
--- a/examples/common.h
+++ b/examples/common.h
@@ -55,6 +55,7 @@ extern int lg2_remote(git_repository *repo, int argc, char **argv);
extern int lg2_rev_list(git_repository *repo, int argc, char **argv);
extern int lg2_rev_parse(git_repository *repo, int argc, char **argv);
extern int lg2_show_index(git_repository *repo, int argc, char **argv);
+extern int lg2_stash(git_repository *repo, int argc, char **argv);
extern int lg2_status(git_repository *repo, int argc, char **argv);
extern int lg2_tag(git_repository *repo, int argc, char **argv);
diff --git a/examples/lg2.c b/examples/lg2.c
index 4ee0110..f1a8843 100644
--- a/examples/lg2.c
+++ b/examples/lg2.c
@@ -31,6 +31,7 @@ struct {
{ "rev-list", lg2_rev_list, 1 },
{ "rev-parse", lg2_rev_parse, 1 },
{ "show-index", lg2_show_index, 0 },
+ { "stash", lg2_stash, 1 },
{ "status", lg2_status, 1 },
{ "tag", lg2_tag, 1 },
};
diff --git a/examples/stash.c b/examples/stash.c
new file mode 100644
index 0000000..8142439
--- /dev/null
+++ b/examples/stash.c
@@ -0,0 +1,157 @@
+/*
+ * libgit2 "stash" example - shows how to use the stash API
+ *
+ * Written by the libgit2 contributors
+ *
+ * To the extent possible under law, the author(s) have dedicated all copyright
+ * and related and neighboring rights to this software to the public domain
+ * worldwide. This software is distributed without any warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication along
+ * with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include <stdarg.h>
+
+#include "common.h"
+
+enum subcmd {
+ SUBCMD_APPLY,
+ SUBCMD_LIST,
+ SUBCMD_POP,
+ SUBCMD_PUSH
+};
+
+struct opts {
+ enum subcmd cmd;
+ int argc;
+ char **argv;
+};
+
+static void usage(const char *fmt, ...)
+{
+ va_list ap;
+
+ fputs("usage: git stash list\n", stderr);
+ fputs(" or: git stash ( pop | apply )\n", stderr);
+ fputs(" or: git stash [push]\n", stderr);
+ fputs("\n", stderr);
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+
+ exit(1);
+}
+
+static void parse_subcommand(struct opts *opts, int argc, char *argv[])
+{
+ char *arg = (argc < 2) ? "push" : argv[1];
+ enum subcmd cmd;
+
+ if (!strcmp(arg, "apply")) {
+ cmd = SUBCMD_APPLY;
+ } else if (!strcmp(arg, "list")) {
+ cmd = SUBCMD_LIST;
+ } else if (!strcmp(arg, "pop")) {
+ cmd = SUBCMD_POP;
+ } else if (!strcmp(arg, "push")) {
+ cmd = SUBCMD_PUSH;
+ } else {
+ usage("invalid command %s", arg);
+ return;
+ }
+
+ opts->cmd = cmd;
+ opts->argc = (argc < 2) ? argc - 1 : argc - 2;
+ opts->argv = argv;
+}
+
+static int cmd_apply(git_repository *repo, struct opts *opts)
+{
+ if (opts->argc)
+ usage("apply does not accept any parameters");
+
+ check_lg2(git_stash_apply(repo, 0, NULL),
+ "Unable to apply stash", NULL);
+
+ return 0;
+}
+
+static int list_stash_cb(size_t index, const char *message,
+ const git_oid *stash_id, void *payload)
+{
+ UNUSED(stash_id);
+ UNUSED(payload);
+ printf("stash@{%"PRIuZ"}: %s\n", index, message);
+ return 0;
+}
+
+static int cmd_list(git_repository *repo, struct opts *opts)
+{
+ if (opts->argc)
+ usage("list does not accept any parameters");
+
+ check_lg2(git_stash_foreach(repo, list_stash_cb, NULL),
+ "Unable to list stashes", NULL);
+
+ return 0;
+}
+
+static int cmd_push(git_repository *repo, struct opts *opts)
+{
+ git_signature *signature;
+ git_commit *stash;
+ git_oid stashid;
+
+ if (opts->argc)
+ usage("push does not accept any parameters");
+
+ check_lg2(git_signature_default(&signature, repo),
+ "Unable to get signature", NULL);
+ check_lg2(git_stash_save(&stashid, repo, signature, NULL, GIT_STASH_DEFAULT),
+ "Unable to save stash", NULL);
+ check_lg2(git_commit_lookup(&stash, repo, &stashid),
+ "Unable to lookup stash commit", NULL);
+
+ printf("Saved working directory %s\n", git_commit_summary(stash));
+
+ git_signature_free(signature);
+ git_commit_free(stash);
+
+ return 0;
+}
+
+static int cmd_pop(git_repository *repo, struct opts *opts)
+{
+ if (opts->argc)
+ usage("pop does not accept any parameters");
+
+ check_lg2(git_stash_pop(repo, 0, NULL),
+ "Unable to pop stash", NULL);
+
+ printf("Dropped refs/stash@{0}\n");
+
+ return 0;
+}
+
+int lg2_stash(git_repository *repo, int argc, char *argv[])
+{
+ struct opts opts = { 0 };
+
+ parse_subcommand(&opts, argc, argv);
+
+ switch (opts.cmd) {
+ case SUBCMD_APPLY:
+ return cmd_apply(repo, &opts);
+ case SUBCMD_LIST:
+ return cmd_list(repo, &opts);
+ case SUBCMD_PUSH:
+ return cmd_push(repo, &opts);
+ case SUBCMD_POP:
+ return cmd_pop(repo, &opts);
+ }
+
+ return -1;
+}