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 
usage(const char * fmt,...)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 
parse_subcommand(struct opts * opts,int argc,char * argv[])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 
cmd_apply(git_repository * repo,struct opts * opts)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 
list_stash_cb(size_t index,const char * message,const git_oid * stash_id,void * payload)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 
cmd_list(git_repository * repo,struct opts * opts)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 
cmd_push(git_repository * repo,struct opts * opts)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 
cmd_pop(git_repository * repo,struct opts * opts)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 
lg2_stash(git_repository * repo,int argc,char * argv[])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 }
158