1 module libgit2_d.example.lg2;
2 
3 
4 private static import core.stdc.stdio;
5 private static import core.stdc.stdlib;
6 private static import core.stdc..string;
7 private static import libgit2_d.errors;
8 private static import libgit2_d.example.add;
9 private static import libgit2_d.example.args;
10 private static import libgit2_d.example.blame;
11 private static import libgit2_d.example.cat_file;
12 private static import libgit2_d.example.checkout;
13 private static import libgit2_d.example.clone;
14 private static import libgit2_d.example.commit;
15 private static import libgit2_d.example.common;
16 private static import libgit2_d.example.config;
17 private static import libgit2_d.example.describe;
18 private static import libgit2_d.example.diff;
19 private static import libgit2_d.example.fetch;
20 private static import libgit2_d.example.for_each_ref;
21 private static import libgit2_d.example.general;
22 private static import libgit2_d.example.index_pack;
23 private static import libgit2_d.example.init;
24 private static import libgit2_d.example.log;
25 private static import libgit2_d.example.ls_files;
26 private static import libgit2_d.example.ls_remote;
27 private static import libgit2_d.example.merge;
28 private static import libgit2_d.example.push;
29 private static import libgit2_d.example.remote;
30 private static import libgit2_d.example.rev_list;
31 private static import libgit2_d.example.rev_parse;
32 private static import libgit2_d.example.show_index;
33 private static import libgit2_d.example.stash;
34 private static import libgit2_d.example.status;
35 private static import libgit2_d.example.tag;
36 private static import libgit2_d.global;
37 private static import libgit2_d.repository;
38 private static import libgit2_d.types;
39 
40 package:
41 
42 /* This part is not strictly libgit2-dependent, but you can use this
43  * as a starting point for a git-like tool */
44 
45 public alias git_command_fn = extern (C) nothrow @nogc int function(libgit2_d.types.git_repository*, int, char**);
46 
47 public struct commands_t
48 {
49 	immutable (char)* name;
50 	.git_command_fn fn;
51 	char requires_repo;
52 }
53 
54 public static immutable .commands_t[] commands =
55 [
56 	{"add".ptr, &libgit2_d.example.add.lg2_add, 1},
57 	{"blame".ptr, &libgit2_d.example.blame.lg2_blame, 1},
58 	{"cat-file".ptr, &libgit2_d.example.cat_file.lg2_cat_file, 1},
59 	{"checkout".ptr, &libgit2_d.example.checkout.lg2_checkout, 1},
60 	{"clone".ptr, &libgit2_d.example.clone.lg2_clone, 0},
61 	{"commit".ptr, &libgit2_d.example.commit.lg2_commit, 1},
62 	{"config".ptr, &libgit2_d.example.config.lg2_config, 1},
63 	{"describe".ptr, &libgit2_d.example.describe.lg2_describe, 1},
64 	{"diff".ptr, &libgit2_d.example.diff.lg2_diff, 1},
65 	{"fetch".ptr, &libgit2_d.example.fetch.lg2_fetch, 1},
66 	{"for-each-ref".ptr, &libgit2_d.example.for_each_ref.lg2_for_each_ref, 1},
67 	{"general".ptr, &libgit2_d.example.general.lg2_general, 0},
68 	{"index-pack".ptr, &libgit2_d.example.index_pack.lg2_index_pack, 1},
69 	{"init".ptr, &libgit2_d.example.init.lg2_init, 0},
70 	{"log".ptr, &libgit2_d.example.log.lg2_log, 1},
71 	{"ls-files".ptr, &libgit2_d.example.ls_files.lg2_ls_files, 1},
72 	{"ls-remote".ptr, &libgit2_d.example.ls_remote.lg2_ls_remote, 1},
73 	{"merge".ptr, &libgit2_d.example.merge.lg2_merge, 1},
74 	{"push".ptr, &libgit2_d.example.push.lg2_push, 1},
75 	{"remote".ptr, &libgit2_d.example.remote.lg2_remote, 1},
76 	{"rev-list".ptr, &libgit2_d.example.rev_list.lg2_rev_list, 1},
77 	{"rev-parse".ptr, &libgit2_d.example.rev_parse.lg2_rev_parse, 1},
78 	{"show-index".ptr, &libgit2_d.example.show_index.lg2_show_index, 0},
79 	{"stash".ptr, &libgit2_d.example.stash.lg2_stash, 1},
80 	{"status".ptr, &libgit2_d.example.status.lg2_status, 1},
81 	{"tag".ptr, &libgit2_d.example.tag.lg2_tag, 1},
82 ];
83 
84 nothrow @nogc
85 private int run_command(.git_command_fn fn, libgit2_d.types.git_repository* repo, libgit2_d.example.args.args_info args)
86 
87 	in
88 	{
89 	}
90 
91 	do
92 	{
93 		/* Run the command. If something goes wrong, print the error message to stderr */
94 		int error = fn(repo, args.argc - args.pos, &args.argv[args.pos]);
95 
96 		if (error < 0) {
97 			if (libgit2_d.errors.git_error_last() == null) {
98 				core.stdc.stdio.fprintf(core.stdc.stdio.stderr, "Error without message");
99 			} else {
100 				core.stdc.stdio.fprintf(core.stdc.stdio.stderr, "Bad news:\n %s\n", libgit2_d.errors.git_error_last().message);
101 			}
102 		}
103 
104 		return !!error;
105 	}
106 
107 nothrow @nogc
108 private void usage(const (char)* prog)
109 
110 	in
111 	{
112 	}
113 
114 	do
115 	{
116 		core.stdc.stdio.fprintf(core.stdc.stdio.stderr, "usage: %s <cmd>...\n\nAvailable commands:\n\n", prog);
117 
118 		for (size_t i = 0; i < commands.length; i++) {
119 			core.stdc.stdio.fprintf(core.stdc.stdio.stderr, "\t%s\n", commands[i].name);
120 		}
121 
122 		core.stdc.stdlib.exit(core.stdc.stdlib.EXIT_FAILURE);
123 	}
124 
125 version (LIBGIT2_EXAMPLE) {
126 	extern (C)
127 	nothrow @nogc
128 	public int main(int argc, char** argv)
129 
130 		do
131 		{
132 			if (argc < 2) {
133 				.usage(argv[0]);
134 			}
135 
136 			libgit2_d.example.args.args_info args = libgit2_d.example.args.ARGS_INFO_INIT(argc, argv);
137 			libgit2_d.global.git_libgit2_init();
138 
139 			const (char)* git_dir = null;
140 
141 			for (args.pos = 1; args.pos < args.argc; ++args.pos) {
142 				char* a = args.argv[args.pos];
143 
144 				if (a[0] != '-') {
145 					/* non-arg */
146 					break;
147 				} else if (libgit2_d.example.args.optional_str_arg(&git_dir, &args, "--git-dir", ".git")) {
148 					continue;
149 				} else if (libgit2_d.example.args.match_arg_separator(&args)) {
150 					break;
151 				}
152 			}
153 
154 			if (args.pos == args.argc) {
155 				.usage(argv[0]);
156 			}
157 
158 			if (git_dir == null) {
159 				git_dir = ".";
160 			}
161 
162 			libgit2_d.types.git_repository* repo = null;
163 			int return_code = 1;
164 
165 			scope (exit) {
166 				libgit2_d.repository.git_repository_free(repo);
167 				libgit2_d.global.git_libgit2_shutdown();
168 			}
169 
170 			for (size_t i = 0; i < commands.length; ++i) {
171 				if (core.stdc..string.strcmp(args.argv[args.pos], commands[i].name)) {
172 					continue;
173 				}
174 
175 				/*
176 				 * Before running the actual command, create an instance
177 				 * of the local repository and pass it to the function.
178 				 */
179 				if (commands[i].requires_repo) {
180 					libgit2_d.example.common.check_lg2(libgit2_d.repository.git_repository_open_ext(&repo, git_dir, 0, null), "Unable to open repository '%s'", git_dir);
181 				}
182 
183 				return_code = run_command(commands[i].fn, repo, args);
184 
185 				return return_code;
186 			}
187 
188 			core.stdc.stdio.fprintf(core.stdc.stdio.stderr, "Command not found: %s\n", argv[1]);
189 
190 			return return_code;
191 		}
192 }