1 /*
2  * libgit2 "add" example - shows how to modify the index
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 module libgit2_d.example.add;
15 
16 
17 private static import core.stdc.stdio;
18 private static import core.stdc.stdlib;
19 private static import core.stdc..string;
20 private static import libgit2_d.example.args;
21 private static import libgit2_d.example.common;
22 private static import libgit2_d.index;
23 private static import libgit2_d.repository;
24 private static import libgit2_d.status;
25 private static import libgit2_d.strarray;
26 private static import libgit2_d.types;
27 
28 package:
29 
30 /**
31  * The following example demonstrates how to add files with libgit2.
32  *
33  * It will use the repository in the current working directory, and act
34  * on files passed as its parameters.
35  *
36  * Recognized options are:
37  *   -v/--verbose: show the file's status after acting on it.
38  *   -n/--dry-run: do not actually change the index.
39  *   -u/--update: update the index instead of adding to it.
40  */
41 
42 public enum index_mode
43 {
44 	INDEX_NONE,
45 	INDEX_ADD,
46 }
47 
48 //Declaration name in C language
49 public enum
50 {
51 	INDEX_NONE = .index_mode.INDEX_NONE,
52 	INDEX_ADD = .index_mode.INDEX_ADD,
53 }
54 
55 public struct index_options
56 {
57 	int dry_run;
58 	int verbose;
59 	libgit2_d.types.git_repository* repo;
60 	.index_mode mode;
61 	int add_update;
62 }
63 
64 /* Forward declarations for helpers */
65 //private void parse_opts(int* options, int* count, int argc, char*[] argv);
66 //void init_array(libgit2_d.strarray.git_strarray* array, int argc, char** argv);
67 //int print_matched_cb(const (char)* path, const (char)* matched_pathspec, void* payload);
68 
69 extern (C)
70 nothrow @nogc
71 public int lg2_add(libgit2_d.types.git_repository* repo, int argc, char** argv)
72 
73 	in
74 	{
75 	}
76 
77 	do
78 	{
79 		libgit2_d.example.args.args_info args = libgit2_d.example.args.ARGS_INFO_INIT(argc, argv);
80 
81 		/* Parse the options & arguments. */
82 		.index_options options = .index_options.init;
83 		options.mode = .index_mode.INDEX_ADD;
84 		.parse_opts(null, &options, &args);
85 
86 		libgit2_d.strarray.git_strarray array = libgit2_d.strarray.git_strarray.init;
87 		libgit2_d.example.args.strarray_from_args(&array, &args);
88 
89 		/* Grab the repository's index. */
90 		libgit2_d.types.git_index* index;
91 		libgit2_d.example.common.check_lg2(libgit2_d.repository.git_repository_index(&index, repo), "Could not open repository index", null);
92 
93 		libgit2_d.index.git_index_matched_path_cb matched_cb = null;
94 
95 		/* Setup a callback if the requested options need it */
96 		if ((options.verbose) || (options.dry_run)) {
97 			matched_cb = &.print_matched_cb;
98 		}
99 
100 		options.repo = repo;
101 
102 		if (options.add_update) {
103 			libgit2_d.index.git_index_update_all(index, &array, matched_cb, &options);
104 		} else {
105 			libgit2_d.index.git_index_add_all(index, &array, 0, matched_cb, &options);
106 		}
107 
108 		/* Cleanup memory */
109 		libgit2_d.index.git_index_write(index);
110 		libgit2_d.index.git_index_free(index);
111 
112 		return 0;
113 	}
114 
115 /*
116  * This callback is called for each file under consideration by
117  * git_index_(update|add)_all above.
118  * It makes uses of the callback's ability to abort the action.
119  */
120 extern (C)
121 nothrow @nogc
122 public int print_matched_cb(const (char)* path, const (char)* matched_pathspec, void* payload)
123 
124 	in
125 	{
126 	}
127 
128 	do
129 	{
130 		.index_options opts = *cast(.index_options*)(payload);
131 		uint status;
132 		//cast(void)(matched_pathspec);
133 
134 		/* Get the file status */
135 		if (libgit2_d.status.git_status_file(&status, opts.repo, path) < 0) {
136 			return -1;
137 		}
138 
139 		int ret;
140 
141 		if ((status & libgit2_d.status.git_status_t.GIT_STATUS_WT_MODIFIED) || (status & libgit2_d.status.git_status_t.GIT_STATUS_WT_NEW)) {
142 			core.stdc.stdio.printf("add '%s'\n", path);
143 			ret = 0;
144 		} else {
145 			ret = 1;
146 		}
147 
148 		if (opts.dry_run) {
149 			ret = 1;
150 		}
151 
152 		return ret;
153 	}
154 
155 nothrow @nogc
156 public void init_array(libgit2_d.strarray.git_strarray* array, int argc, char** argv)
157 
158 	in
159 	{
160 	}
161 
162 	do
163 	{
164 		array.count = argc;
165 		array.strings = cast(char**)(core.stdc.stdlib.calloc(array.count, (char*).sizeof));
166 		assert(array.strings != null);
167 
168 		for (uint i = 0; i < array.count; i++) {
169 			array.strings[i] = argv[i];
170 		}
171 
172 		return;
173 	}
174 
175 nothrow @nogc
176 public void print_usage()
177 
178 	in
179 	{
180 	}
181 
182 	do
183 	{
184 		core.stdc.stdio.fprintf(core.stdc.stdio.stderr, "usage: add [options] [--] file-spec [file-spec] [...]\n\n");
185 		core.stdc.stdio.fprintf(core.stdc.stdio.stderr, "\t-n, --dry-run    dry run\n");
186 		core.stdc.stdio.fprintf(core.stdc.stdio.stderr, "\t-v, --verbose    be verbose\n");
187 		core.stdc.stdio.fprintf(core.stdc.stdio.stderr, "\t-u, --update     update tracked files\n");
188 		core.stdc.stdlib.exit(1);
189 	}
190 
191 nothrow @nogc
192 private void parse_opts(const (char)** repo_path, .index_options* opts, libgit2_d.example.args.args_info* args)
193 
194 	in
195 	{
196 	}
197 
198 	do
199 	{
200 		if (args.argc <= 1) {
201 			.print_usage();
202 		}
203 
204 		for (args.pos = 1; args.pos < args.argc; ++args.pos) {
205 			const (char)* curr = args.argv[args.pos];
206 
207 			if (curr[0] != '-') {
208 				if (!core.stdc..string.strcmp("add", curr)) {
209 					opts.mode = .index_mode.INDEX_ADD;
210 
211 					continue;
212 				} else if (opts.mode == .index_mode.INDEX_NONE) {
213 					core.stdc.stdio.fprintf(core.stdc.stdio.stderr, "missing command: %s", curr);
214 					.print_usage();
215 
216 					break;
217 				} else {
218 					/* We might be looking at a filename */
219 					break;
220 				}
221 			} else if ((libgit2_d.example.args.match_bool_arg(&opts.verbose, args, "--verbose")) || (libgit2_d.example.args.match_bool_arg(&opts.dry_run, args, "--dry-run")) || (libgit2_d.example.args.match_str_arg(repo_path, args, "--git-dir")) || ((opts.mode == .index_mode.INDEX_ADD) && (libgit2_d.example.args.match_bool_arg(&opts.add_update, args, "--update")))) {
222 				continue;
223 			} else if (libgit2_d.example.args.match_bool_arg(null, args, "--help")) {
224 				.print_usage();
225 
226 				break;
227 			} else if (libgit2_d.example.args.match_arg_separator(args)) {
228 				break;
229 			} else {
230 				core.stdc.stdio.fprintf(core.stdc.stdio.stderr, "Unsupported option %s.\n", curr);
231 				.print_usage();
232 			}
233 		}
234 	}