Skip to content

Commit 88731e3

Browse files
committed
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 parent 1f44079 commit 88731e3

File tree

3 files changed

+159
-0
lines changed

3 files changed

+159
-0
lines changed

examples/common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ extern int lg2_remote(git_repository *repo, int argc, char **argv);
5555
extern int lg2_rev_list(git_repository *repo, int argc, char **argv);
5656
extern int lg2_rev_parse(git_repository *repo, int argc, char **argv);
5757
extern int lg2_show_index(git_repository *repo, int argc, char **argv);
58+
extern int lg2_stash(git_repository *repo, int argc, char **argv);
5859
extern int lg2_status(git_repository *repo, int argc, char **argv);
5960
extern int lg2_tag(git_repository *repo, int argc, char **argv);
6061

examples/lg2.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ struct {
3131
{ "rev-list", lg2_rev_list, 1 },
3232
{ "rev-parse", lg2_rev_parse, 1 },
3333
{ "show-index", lg2_show_index, 0 },
34+
{ "stash", lg2_stash, 1 },
3435
{ "status", lg2_status, 1 },
3536
{ "tag", lg2_tag, 1 },
3637
};

examples/stash.c

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
/*
2+
* libgit2 "stash" example - shows how to use the stash API
3+
*
4+
* Written by the libgit2 contributors
5+
*
6+
* To the extent possible under law, the author(s) have dedicated all copyright
7+
* and related and neighboring rights to this software to the public domain
8+
* worldwide. This software is distributed without any warranty.
9+
*
10+
* You should have received a copy of the CC0 Public Domain Dedication along
11+
* with this software. If not, see
12+
* <http://creativecommons.org/publicdomain/zero/1.0/>.
13+
*/
14+
15+
#include <stdarg.h>
16+
17+
#include "common.h"
18+
19+
enum subcmd {
20+
SUBCMD_APPLY,
21+
SUBCMD_LIST,
22+
SUBCMD_POP,
23+
SUBCMD_PUSH
24+
};
25+
26+
struct opts {
27+
enum subcmd cmd;
28+
int argc;
29+
char **argv;
30+
};
31+
32+
static void usage(const char *fmt, ...)
33+
{
34+
va_list ap;
35+
36+
fputs("usage: git stash list\n", stderr);
37+
fputs(" or: git stash ( pop | apply )\n", stderr);
38+
fputs(" or: git stash [push]\n", stderr);
39+
fputs("\n", stderr);
40+
41+
va_start(ap, fmt);
42+
vfprintf(stderr, fmt, ap);
43+
va_end(ap);
44+
45+
exit(1);
46+
}
47+
48+
static void parse_subcommand(struct opts *opts, int argc, char *argv[])
49+
{
50+
char *arg = (argc < 2) ? "push" : argv[1];
51+
enum subcmd cmd;
52+
53+
if (!strcmp(arg, "apply")) {
54+
cmd = SUBCMD_APPLY;
55+
} else if (!strcmp(arg, "list")) {
56+
cmd = SUBCMD_LIST;
57+
} else if (!strcmp(arg, "pop")) {
58+
cmd = SUBCMD_POP;
59+
} else if (!strcmp(arg, "push")) {
60+
cmd = SUBCMD_PUSH;
61+
} else {
62+
usage("invalid command %s", arg);
63+
return;
64+
}
65+
66+
opts->cmd = cmd;
67+
opts->argc = (argc < 2) ? argc - 1 : argc - 2;
68+
opts->argv = argv;
69+
}
70+
71+
static int cmd_apply(git_repository *repo, struct opts *opts)
72+
{
73+
if (opts->argc)
74+
usage("apply does not accept any parameters");
75+
76+
check_lg2(git_stash_apply(repo, 0, NULL),
77+
"Unable to apply stash", NULL);
78+
79+
return 0;
80+
}
81+
82+
static int list_stash_cb(size_t index, const char *message,
83+
const git_oid *stash_id, void *payload)
84+
{
85+
UNUSED(stash_id);
86+
UNUSED(payload);
87+
printf("stash@{%"PRIuZ"}: %s\n", index, message);
88+
return 0;
89+
}
90+
91+
static int cmd_list(git_repository *repo, struct opts *opts)
92+
{
93+
if (opts->argc)
94+
usage("list does not accept any parameters");
95+
96+
check_lg2(git_stash_foreach(repo, list_stash_cb, NULL),
97+
"Unable to list stashes", NULL);
98+
99+
return 0;
100+
}
101+
102+
static int cmd_push(git_repository *repo, struct opts *opts)
103+
{
104+
git_signature *signature;
105+
git_commit *stash;
106+
git_oid stashid;
107+
108+
if (opts->argc)
109+
usage("push does not accept any parameters");
110+
111+
check_lg2(git_signature_default(&signature, repo),
112+
"Unable to get signature", NULL);
113+
check_lg2(git_stash_save(&stashid, repo, signature, NULL, GIT_STASH_DEFAULT),
114+
"Unable to save stash", NULL);
115+
check_lg2(git_commit_lookup(&stash, repo, &stashid),
116+
"Unable to lookup stash commit", NULL);
117+
118+
printf("Saved working directory %s\n", git_commit_summary(stash));
119+
120+
git_signature_free(signature);
121+
git_commit_free(stash);
122+
123+
return 0;
124+
}
125+
126+
static int cmd_pop(git_repository *repo, struct opts *opts)
127+
{
128+
if (opts->argc)
129+
usage("pop does not accept any parameters");
130+
131+
check_lg2(git_stash_pop(repo, 0, NULL),
132+
"Unable to pop stash", NULL);
133+
134+
printf("Dropped refs/stash@{0}\n");
135+
136+
return 0;
137+
}
138+
139+
int lg2_stash(git_repository *repo, int argc, char *argv[])
140+
{
141+
struct opts opts = { 0 };
142+
143+
parse_subcommand(&opts, argc, argv);
144+
145+
switch (opts.cmd) {
146+
case SUBCMD_APPLY:
147+
return cmd_apply(repo, &opts);
148+
case SUBCMD_LIST:
149+
return cmd_list(repo, &opts);
150+
case SUBCMD_PUSH:
151+
return cmd_push(repo, &opts);
152+
case SUBCMD_POP:
153+
return cmd_pop(repo, &opts);
154+
}
155+
156+
return -1;
157+
}

0 commit comments

Comments
 (0)