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