Refactor getting prefix into a separate function
[git-cheetah/kirill.git] / common / cheetahmenu.c
blob4a540556eeb84f766574c168571e02fc5d85f243
2 #include "cache.h"
3 #include "exec.h"
4 #include "menuengine.h"
5 #include "cheetahmenu.h"
6 #include "debug.h"
7 #include "systeminfo.h"
9 char *wd_from_path(const char *path, BOOL *is_path_dir)
11 BOOL directory = TRUE;
12 char *cheetah_wd = strdup(path);
13 if (!is_directory(cheetah_wd)) {
14 char *c = strrchr(cheetah_wd, PATH_SEPERATOR);
15 if (c) /* sanity check in case it's a weird directory */
16 *c = 0;
18 directory = FALSE;
21 if (is_path_dir)
22 *is_path_dir = directory;
24 return cheetah_wd;
27 static char *get_git_prefix(const char *wd, int *out_status)
29 char *prefix = NULL, *eol;
30 int status;
31 struct strbuf output = STRBUF_INIT;
33 status = exec_program(wd, &output, NULL, WAITMODE,
34 "git", "rev-parse", "--show-prefix", NULL);
35 if (out_status)
36 *out_status = status;
38 eol = strchr(output.buf, '\n');
39 if (eol)
40 *eol = 0;
42 if (!status) /* we're in the repo */
43 prefix = strdup(output.buf);
45 strbuf_release(&output);
46 return prefix;
50 * Cheetah-specific menu
53 static int menu_gui(struct git_data *this_, UINT id)
55 char *wd = wd_from_path(this_->name, NULL);
56 const char **argv;
58 free_func_t argv_free;
59 void *argv_data;
61 const char *generic_argv[] = { "git", "gui", NULL };
63 argv = menu_get_platform_argv(MENU_GUI, NULL,
64 &argv_free, &argv_data);
66 if (!argv)
67 argv = generic_argv;
69 exec_program_v(wd, NULL, NULL, HIDDENMODE, argv);
71 if (argv_free)
72 argv_free(argv_data);
73 free(wd);
75 return 0;
78 static int menu_init(struct git_data *this_, UINT id)
80 char *wd = wd_from_path(this_->name, NULL);
81 const char **argv;
83 free_func_t argv_free;
84 void *argv_data;
86 const char *generic_argv[] = { "git", "init", NULL };
88 argv = menu_get_platform_argv(MENU_INIT, NULL,
89 &argv_free, &argv_data);
90 if (!argv)
91 argv = generic_argv;
93 exec_program_v(wd, NULL, NULL, HIDDENMODE | WAITMODE, argv);
95 if (argv_free)
96 argv_free(argv_data);
97 free(wd);
99 return 1;
102 static int menu_history(struct git_data *this_, unsigned int id)
104 BOOL is_directory;
105 char *wd = wd_from_path(this_->name, &is_directory);
106 char *name = NULL;
107 const char **argv;
109 free_func_t argv_free;
110 void *argv_data;
112 const char *generic_argv[] = { "gitk", "HEAD", "--",
113 NULL, NULL };
115 if (!is_directory)
116 name = this_->name + strlen(wd) + 1;
117 generic_argv[3] = name;
119 argv = menu_get_platform_argv(MENU_HISTORY, name,
120 &argv_free, &argv_data);
121 if (!argv)
122 argv = generic_argv;
124 exec_program_v(wd, NULL, NULL, HIDDENMODE, argv);
126 if (argv_free)
127 argv_free(argv_data);
128 free(wd);
130 return 0;
133 static int menu_bash(struct git_data *this_, UINT id)
135 char *wd = wd_from_path(this_->name, NULL);
136 const char **argv;
138 free_func_t argv_free;
139 void *argv_data;
141 argv = menu_get_platform_argv(MENU_BASH, wd,
142 &argv_free, &argv_data);
143 /* There is no generic implementation for this item */
144 if (!argv) {
145 debug_git("Error: Got no platform terminal for bash");
146 return 0;
149 exec_program_v(wd, NULL, NULL, NORMALMODE, argv);
151 if (argv_free)
152 argv_free(argv_data);
153 free(wd);
155 return 0;
158 static int menu_blame(struct git_data *this_, UINT id)
160 BOOL is_directory;
161 char *wd = wd_from_path(this_->name, &is_directory);
162 char *name = "";
163 const char **argv;
165 free_func_t argv_free = NULL;
166 void *argv_data;
168 const char *generic_argv[] = { "git", "gui", "blame",
169 NULL, NULL };
171 if (!is_directory) {
172 name = this_->name + strlen(wd) + 1;
173 generic_argv[3] = name;
175 argv = menu_get_platform_argv(MENU_BLAME, name,
176 &argv_free, &argv_data);
177 if (!argv)
178 argv = generic_argv;
180 exec_program_v(wd, NULL, NULL, HIDDENMODE, argv);
183 if (argv_free)
184 argv_free(argv_data);
185 free(wd);
187 return 0;
190 static int menu_citool(struct git_data *this_, UINT id)
192 char *wd = wd_from_path(this_->name, NULL);
193 const char **argv;
195 free_func_t argv_free;
196 void *argv_data;
198 const char *generic_argv[] = { "git", "citool", NULL };
200 argv = menu_get_platform_argv(MENU_CITOOL, NULL,
201 &argv_free, &argv_data);
202 if (!argv)
203 argv = generic_argv;
205 exec_program_v(wd, NULL, NULL, HIDDENMODE, argv);
207 if (argv_free)
208 argv_free(argv_data);
209 free(wd);
211 return 0;
214 static int menu_addall(struct git_data *this_, UINT id)
216 char *wd = wd_from_path(this_->name, NULL);
217 const char **argv;
219 free_func_t argv_free;
220 void *argv_data;
222 const char *generic_argv[] = { "git", "add", "--all", NULL };
224 argv = menu_get_platform_argv(MENU_ADDALL, NULL,
225 &argv_free, &argv_data);
226 if (!argv)
227 argv = generic_argv;
229 exec_program_v(wd, NULL, NULL, HIDDENMODE, argv);
231 if (argv_free)
232 argv_free(argv_data);
233 free(wd);
235 return 0;
238 static int menu_branch(struct git_data *this_, UINT id)
240 int status;
241 char *wd = wd_from_path(this_->name, NULL);
242 struct strbuf err;
243 const char *menu_item_text;
244 const char **argv;
246 free_func_t argv_free;
247 void *argv_data;
249 const char *generic_argv[] = { "git", "checkout", NULL, NULL };
251 menu_item_text = get_menu_item_text(id);
252 generic_argv[2] = menu_item_text;
254 argv = menu_get_platform_argv(MENU_BRANCH, menu_item_text,
255 &argv_free, &argv_data);
256 if (!argv)
257 argv = generic_argv;
259 strbuf_init(&err, 0);
261 status = exec_program_v(wd, NULL, &err, HIDDENMODE | WAITMODE, argv);
263 /* if nothing, terribly wrong happened, show the confirmation */
264 if (-1 != status)
265 /* strangely enough even success message is on stderr */
266 debug_git_mbox(err.buf);
268 if (argv_free)
269 argv_free(argv_data);
270 free(wd);
272 return 1;
275 static BOOL build_branch_menu(struct git_data *data,
276 const struct menu_item *item,
277 void *platform)
279 void *submenu;
281 int status;
282 char *wd = wd_from_path(data->name, NULL);
284 struct strbuf output;
285 struct strbuf **lines, **it;
286 strbuf_init(&output, 0);
288 status = exec_program(wd, &output, NULL, WAITMODE,
289 "git", "branch", NULL);
290 free(wd);
291 if (status)
292 return FALSE;
294 submenu = start_submenu(data, item, platform);
296 lines = strbuf_split(&output, '\n');
297 for (it = lines; *it; it++) {
298 struct menu_item item = {
299 MENU_ITEM_CLEANUP, 0,
300 NULL, NULL,
301 NULL, menu_branch
304 strbuf_rtrim(*it);
305 item.string = strdup((*it)->buf + 2);
306 item.helptext = strdup((*it)->buf + 2);
307 item.flags = '*' == (*it)->buf[0] ?
308 MI_CHECKED | MI_DISABLED : 0;
309 if (build_item(data, &item, submenu))
310 append_active_menu(&item);
311 else
313 * if the platform failed to create an item
314 * there is no point to try other items
316 break;
319 end_submenu(platform, submenu);
321 /* technically, there is nothing to track for the menu engine */
322 return FALSE;
325 UINT cheetah_menu_mask(struct git_data *this_)
327 BOOL is_directory;
328 char *wd = wd_from_path(this_->name, &is_directory);
329 UINT selection = is_directory ? MENU_ITEM_DIR : MENU_ITEM_FILE;
330 int status;
331 char *prefix = get_git_prefix(wd, &status);
333 if (status < 0) /* something went terribly wrong */
334 selection = MENU_ITEM_LAST;
335 else if (status)
336 selection |= MENU_ITEM_NOREPO;
337 else {
338 char head_path[MAX_PATH] = "HEAD";
339 if (!is_directory)
340 sprintf(head_path, "HEAD:%s%s",
341 prefix,
342 this_->name + strlen(wd) + 1);
344 status = exec_program(wd, NULL, NULL, WAITMODE,
345 "git", "rev-parse", "--verify", head_path, NULL);
346 if (status < 0) /* something went terribly wrong */
347 selection = MENU_ITEM_LAST;
348 else
349 selection |= MENU_ITEM_REPO |
350 (status ?
351 MENU_ITEM_NOTRACK : MENU_ITEM_TRACK);
354 free(prefix);
355 free(wd);
356 return selection;
359 const struct menu_item cheetah_menu[] = {
360 { MENU_ITEM_ALWAYS, 0, NULL, NULL, build_separator, NULL },
362 { MENU_ITEM_REPO, 0, "Git &Add all files now",
363 "Add all files from this folder now",
364 build_item, menu_addall },
365 { MENU_ITEM_REPO, 0, "Git &Commit Tool",
366 "Launch the GIT commit tool in the local or chosen directory.",
367 build_item, menu_citool },
368 { MENU_ITEM_TRACK, 0, "Git &History",
369 "Show GIT history of the chosen file or directory.",
370 build_item,
371 menu_history },
372 { MENU_ITEM_TRACK | MENU_ITEM_FILE, 0, "Git &Blame",
373 "Start a blame viewer on the specified file.",
374 build_item, menu_blame },
376 { MENU_ITEM_REPO, 0, "Git &Gui",
377 "Launch the GIT Gui in the local or chosen directory.",
378 build_item, menu_gui },
380 { MENU_ITEM_REPO, 0, "Git Bra&nch",
381 "Checkout a branch",
382 build_branch_menu, NULL },
384 { MENU_ITEM_NOREPO, 0, "Git I&nit Here",
385 "Initialize GIT repo in the local directory.",
386 build_item, menu_init },
387 { MENU_ITEM_NOREPO | MENU_ITEM_DIR, 0, "Git &Gui",
388 "Launch the GIT Gui in the local or chosen directory.",
389 build_item, menu_gui },
391 { MENU_ITEM_ALWAYS, 0, "Git Ba&sh",
392 "Start GIT shell in the local or chosen directory",
393 build_item, menu_bash },
394 { MENU_ITEM_ALWAYS, 0, NULL, NULL, build_separator, NULL },
397 void build_cheetah_menu(struct git_data *data, void *platform_data)
399 reset_platform(platform_data);
400 build_menu_items(data, cheetah_menu_mask,
401 cheetah_menu,
402 sizeof(cheetah_menu) / sizeof(cheetah_menu[0]),
403 platform_data);