Allow changing the working directory when getting platform arguments
[git-cheetah/kirill.git] / common / cheetahmenu.c
blob59e688965cb7ed8c4ccd08b98ad3ce9c47ee9282
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 = ".";
117 else
118 name = this_->name + strlen(wd) + 1;
120 generic_argv[3] = name;
122 argv = menu_get_platform_argv(MENU_HISTORY, name,
123 &argv_free, &argv_data);
124 if (!argv)
125 argv = generic_argv;
127 exec_program_v(wd, NULL, NULL, HIDDENMODE, argv);
129 if (argv_free)
130 argv_free(argv_data);
131 free(wd);
133 return 0;
136 static int menu_bash(struct git_data *this_, UINT id)
138 char *wd = wd_from_path(this_->name, NULL);
139 const char **argv;
141 free_func_t argv_free;
142 void *argv_data;
144 argv = menu_get_platform_argv(MENU_BASH, wd,
145 &argv_free, &argv_data);
146 /* There is no generic implementation for this item */
147 if (!argv) {
148 debug_git("Error: Got no platform terminal for bash");
149 return 0;
152 exec_program_v(wd, NULL, NULL, NORMALMODE, argv);
154 if (argv_free)
155 argv_free(argv_data);
156 free(wd);
158 return 0;
161 static int menu_blame(struct git_data *this_, UINT id)
163 BOOL is_directory;
164 char *wd = wd_from_path(this_->name, &is_directory);
165 char *name = "";
166 const char **argv;
168 free_func_t argv_free = NULL;
169 void *argv_data;
171 const char *generic_argv[] = { "git", "gui", "blame",
172 NULL, NULL };
174 if (!is_directory) {
175 name = this_->name + strlen(wd) + 1;
176 generic_argv[3] = name;
178 argv = menu_get_platform_argv(MENU_BLAME, NULL,
179 &argv_free, &argv_data);
180 if (!argv)
181 argv = generic_argv;
183 exec_program_v(wd, NULL, NULL, HIDDENMODE, argv);
186 if (argv_free)
187 argv_free(argv_data);
188 free(wd);
190 return 0;
193 static int menu_citool(struct git_data *this_, UINT id)
195 char *wd = wd_from_path(this_->name, NULL);
196 const char **argv;
198 free_func_t argv_free;
199 void *argv_data;
201 const char *generic_argv[] = { "git", "citool", NULL };
203 argv = menu_get_platform_argv(MENU_CITOOL, NULL,
204 &argv_free, &argv_data);
205 if (!argv)
206 argv = generic_argv;
208 exec_program_v(wd, NULL, NULL, HIDDENMODE, argv);
210 if (argv_free)
211 argv_free(argv_data);
212 free(wd);
214 return 0;
217 static int menu_addall(struct git_data *this_, UINT id)
219 char *wd = wd_from_path(this_->name, NULL);
220 const char **argv;
222 free_func_t argv_free;
223 void *argv_data;
225 const char *generic_argv[] = { "git", "add", "--all", NULL };
227 argv = menu_get_platform_argv(MENU_ADDALL, NULL,
228 &argv_free, &argv_data);
229 if (!argv)
230 argv = generic_argv;
232 exec_program_v(wd, NULL, NULL, HIDDENMODE, argv);
234 if (argv_free)
235 argv_free(argv_data);
236 free(wd);
238 return 0;
241 static int menu_branch(struct git_data *this_, UINT id)
243 int status;
244 char *wd = wd_from_path(this_->name, NULL);
245 struct strbuf err;
246 const char *menu_item_text;
247 const char **argv;
249 free_func_t argv_free;
250 void *argv_data;
252 const char *generic_argv[] = { "git", "checkout", NULL, NULL };
254 menu_item_text = get_menu_item_text(id);
255 generic_argv[2] = menu_item_text;
257 argv = menu_get_platform_argv(MENU_BRANCH, NULL,
258 &argv_free, &argv_data);
259 if (!argv)
260 argv = generic_argv;
262 strbuf_init(&err, 0);
264 status = exec_program_v(wd, NULL, &err, HIDDENMODE | WAITMODE, argv);
266 /* if nothing, terribly wrong happened, show the confirmation */
267 if (-1 != status)
268 /* strangely enough even success message is on stderr */
269 debug_git_mbox(err.buf);
271 if (argv_free)
272 argv_free(argv_data);
273 free(wd);
275 return 1;
278 static BOOL build_branch_menu(struct git_data *data,
279 const struct menu_item *item,
280 void *platform)
282 void *submenu;
284 int status;
285 char *wd = wd_from_path(data->name, NULL);
287 struct strbuf output;
288 struct strbuf **lines, **it;
289 strbuf_init(&output, 0);
291 status = exec_program(wd, &output, NULL, WAITMODE,
292 "git", "branch", NULL);
293 free(wd);
294 if (status)
295 return FALSE;
297 submenu = start_submenu(data, item, platform);
299 lines = strbuf_split(&output, '\n');
300 for (it = lines; *it; it++) {
301 struct menu_item item = {
302 MENU_ITEM_CLEANUP, 0,
303 NULL, NULL,
304 NULL, menu_branch
307 strbuf_rtrim(*it);
308 item.string = strdup((*it)->buf + 2);
309 item.helptext = strdup((*it)->buf + 2);
310 item.flags = '*' == (*it)->buf[0] ?
311 MI_CHECKED | MI_DISABLED : 0;
312 if (build_item(data, &item, submenu))
313 append_active_menu(&item);
314 else
316 * if the platform failed to create an item
317 * there is no point to try other items
319 break;
322 end_submenu(platform, submenu);
324 /* technically, there is nothing to track for the menu engine */
325 return FALSE;
328 UINT cheetah_menu_mask(struct git_data *this_)
330 BOOL is_directory;
331 char *wd = wd_from_path(this_->name, &is_directory);
332 UINT selection = is_directory ? MENU_ITEM_DIR : MENU_ITEM_FILE;
333 int status;
334 char *prefix = get_git_prefix(wd, &status);
336 if (status < 0) /* something went terribly wrong */
337 selection = MENU_ITEM_LAST;
338 else if (status)
339 selection |= MENU_ITEM_NOREPO;
340 else {
341 char head_path[MAX_PATH] = "HEAD";
342 if (!is_directory)
343 sprintf(head_path, "HEAD:%s%s",
344 prefix,
345 this_->name + strlen(wd) + 1);
347 status = exec_program(wd, NULL, NULL, WAITMODE,
348 "git", "rev-parse", "--verify", head_path, NULL);
349 if (status < 0) /* something went terribly wrong */
350 selection = MENU_ITEM_LAST;
351 else
352 selection |= MENU_ITEM_REPO |
353 (status ?
354 MENU_ITEM_NOTRACK : MENU_ITEM_TRACK);
357 free(prefix);
358 free(wd);
359 return selection;
362 const struct menu_item cheetah_menu[] = {
363 { MENU_ITEM_ALWAYS, 0, NULL, NULL, build_separator, NULL },
365 { MENU_ITEM_REPO, 0, "Git &Add all files now",
366 "Add all files from this folder now",
367 build_item, menu_addall },
368 { MENU_ITEM_REPO, 0, "Git &Commit Tool",
369 "Launch the GIT commit tool in the local or chosen directory.",
370 build_item, menu_citool },
371 { MENU_ITEM_TRACK, 0, "Git &History",
372 "Show GIT history of the chosen file or directory.",
373 build_item,
374 menu_history },
375 { MENU_ITEM_TRACK | MENU_ITEM_FILE, 0, "Git &Blame",
376 "Start a blame viewer on the specified file.",
377 build_item, menu_blame },
379 { MENU_ITEM_REPO, 0, "Git &Gui",
380 "Launch the GIT Gui in the local or chosen directory.",
381 build_item, menu_gui },
383 { MENU_ITEM_REPO, 0, "Git Bra&nch",
384 "Checkout a branch",
385 build_branch_menu, NULL },
387 { MENU_ITEM_NOREPO, 0, "Git I&nit Here",
388 "Initialize GIT repo in the local directory.",
389 build_item, menu_init },
390 { MENU_ITEM_NOREPO | MENU_ITEM_DIR, 0, "Git &Gui",
391 "Launch the GIT Gui in the local or chosen directory.",
392 build_item, menu_gui },
394 { MENU_ITEM_ALWAYS, 0, "Git Ba&sh",
395 "Start GIT shell in the local or chosen directory",
396 build_item, menu_bash },
397 { MENU_ITEM_ALWAYS, 0, NULL, NULL, build_separator, NULL },
400 void build_cheetah_menu(struct git_data *data, void *platform_data)
402 reset_platform(platform_data);
403 build_menu_items(data, cheetah_menu_mask,
404 cheetah_menu,
405 sizeof(cheetah_menu) / sizeof(cheetah_menu[0]),
406 platform_data);