common: initialize argv_free
[git-cheetah/kirill.git] / common / cheetahmenu.c
blob07cc19f36fde525ccf73719b495888404086b79e
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;
28 * Cheetah-specific menu
31 static void menu_gui(struct git_data *this_, UINT id)
33 char *wd = wd_from_path(this_->name, NULL);
34 const char **argv;
36 free_func_t argv_free;
37 void *argv_data;
39 const char *generic_argv[] = { "git", "gui", NULL };
41 argv = menu_get_platform_argv(MENU_GUI, NULL,
42 &argv_free, &argv_data);
44 if (!argv)
45 argv = generic_argv;
47 exec_program_v(wd, NULL, NULL, HIDDENMODE, argv);
49 if (argv_free)
50 argv_free(argv_data);
51 free(wd);
54 static void menu_init(struct git_data *this_, UINT id)
56 char *wd = wd_from_path(this_->name, NULL);
57 const char **argv;
59 free_func_t argv_free;
60 void *argv_data;
62 const char *generic_argv[] = { "git", "init", NULL };
64 argv = menu_get_platform_argv(MENU_INIT, NULL,
65 &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);
76 static void menu_history(struct git_data *this_, unsigned int id)
78 BOOL is_directory;
79 char *wd = wd_from_path(this_->name, &is_directory);
80 char *name = "";
81 const char **argv;
83 free_func_t argv_free;
84 void *argv_data;
86 const char *generic_argv[] = { "gitk", "HEAD", "--",
87 NULL, NULL };
89 if (!is_directory)
90 name = this_->name + strlen(wd) + 1;
91 generic_argv[3] = name;
93 argv = menu_get_platform_argv(MENU_HISTORY, name,
94 &argv_free, &argv_data);
95 if (!argv)
96 argv = generic_argv;
98 exec_program_v(wd, NULL, NULL, HIDDENMODE, argv);
100 if (argv_free)
101 argv_free(argv_data);
102 free(wd);
105 static void menu_bash(struct git_data *this_, UINT id)
107 char *wd = wd_from_path(this_->name, NULL);
108 const char **argv;
110 free_func_t argv_free;
111 void *argv_data;
113 argv = menu_get_platform_argv(MENU_BASH, wd,
114 &argv_free, &argv_data);
115 /* There is no generic implementation for this item */
116 if (!argv) {
117 debug_git("Error: Got no platform terminal for bash");
118 return;
121 exec_program_v(wd, NULL, NULL, NORMALMODE, argv);
123 if (argv_free)
124 argv_free(argv_data);
125 free(wd);
128 static void menu_blame(struct git_data *this_, UINT id)
130 BOOL is_directory;
131 char *wd = wd_from_path(this_->name, &is_directory);
132 char *name = "";
133 const char **argv;
135 free_func_t argv_free = NULL;
136 void *argv_data;
138 const char *generic_argv[] = { "git", "gui", "blame",
139 NULL, NULL };
141 if (!is_directory) {
142 name = this_->name + strlen(wd) + 1;
143 generic_argv[3] = name;
145 argv = menu_get_platform_argv(MENU_BLAME, name,
146 &argv_free, &argv_data);
147 if (!argv)
148 argv = generic_argv;
150 exec_program_v(wd, NULL, NULL, HIDDENMODE, argv);
153 if (argv_free)
154 argv_free(argv_data);
155 free(wd);
158 static void menu_citool(struct git_data *this_, UINT id)
160 char *wd = wd_from_path(this_->name, NULL);
161 const char **argv;
163 free_func_t argv_free;
164 void *argv_data;
166 const char *generic_argv[] = { "git", "citool", NULL };
168 argv = menu_get_platform_argv(MENU_CITOOL, NULL,
169 &argv_free, &argv_data);
170 if (!argv)
171 argv = generic_argv;
173 exec_program_v(wd, NULL, NULL, HIDDENMODE, argv);
175 if (argv_free)
176 argv_free(argv_data);
177 free(wd);
180 static void menu_addall(struct git_data *this_, UINT id)
182 char *wd = wd_from_path(this_->name, NULL);
183 const char **argv;
185 free_func_t argv_free;
186 void *argv_data;
188 const char *generic_argv[] = { "git", "add", "--all", NULL };
190 argv = menu_get_platform_argv(MENU_ADDALL, NULL,
191 &argv_free, &argv_data);
192 if (!argv)
193 argv = generic_argv;
195 exec_program_v(wd, NULL, NULL, HIDDENMODE, argv);
197 if (argv_free)
198 argv_free(argv_data);
199 free(wd);
202 static void menu_branch(struct git_data *this_, UINT id)
204 int status;
205 char *wd = wd_from_path(this_->name, NULL);
206 struct strbuf err;
207 const char *menu_item_text;
208 const char **argv;
210 free_func_t argv_free;
211 void *argv_data;
213 const char *generic_argv[] = { "git", "checkout", NULL, NULL };
215 menu_item_text = get_menu_item_text(id);
216 generic_argv[2] = menu_item_text;
218 argv = menu_get_platform_argv(MENU_BRANCH, menu_item_text,
219 &argv_free, &argv_data);
220 if (!argv)
221 argv = generic_argv;
223 strbuf_init(&err, 0);
225 status = exec_program_v(wd, NULL, &err, HIDDENMODE, argv);
227 /* if nothing, terribly wrong happened, show the confirmation */
228 if (-1 != status)
229 /* strangely enough even success message is on stderr */
230 debug_git_mbox(err.buf);
232 if (argv_free)
233 argv_free(argv_data);
234 free(wd);
237 static BOOL build_branch_menu(struct git_data *data,
238 const struct menu_item *item,
239 void *platform)
241 void *submenu;
243 int status;
244 char *wd = wd_from_path(data->name, NULL);
246 struct strbuf output;
247 struct strbuf **lines, **it;
248 strbuf_init(&output, 0);
250 status = exec_program(wd, &output, NULL, WAITMODE,
251 "git", "branch", NULL);
252 free(wd);
253 if (status)
254 return FALSE;
256 submenu = start_submenu(data, item, platform);
258 lines = strbuf_split(&output, '\n');
259 for (it = lines; *it; it++) {
260 struct menu_item item = {
261 MENU_ITEM_CLEANUP, 0,
262 NULL, NULL,
263 NULL, menu_branch
266 strbuf_rtrim(*it);
267 item.string = strdup((*it)->buf + 2);
268 item.helptext = strdup((*it)->buf + 2);
269 item.flags = '*' == (*it)->buf[0] ? MI_CHECKED : 0;
270 if (build_item(data, &item, submenu))
271 append_active_menu(&item);
272 else
274 * if the platform failed to create an item
275 * there is no point to try other items
277 break;
280 end_submenu(platform, submenu);
282 /* technically, there is nothing to track for the menu engine */
283 return FALSE;
286 UINT cheetah_menu_mask(struct git_data *this_)
288 BOOL is_directory;
289 char *wd = wd_from_path(this_->name, &is_directory);
290 UINT selection = is_directory ? MENU_ITEM_DIR : MENU_ITEM_FILE;
291 int status;
293 struct strbuf output;
294 char *eol;
295 strbuf_init(&output, 0);
297 status = exec_program(wd, &output, NULL, WAITMODE,
298 "git", "rev-parse", "--show-prefix", NULL);
299 eol = strchr(output.buf, '\n');
300 if (eol)
301 *eol = 0;
303 if (status < 0) /* something went terribly wrong */
304 selection = MENU_ITEM_LAST;
305 else if (status)
306 selection |= MENU_ITEM_NOREPO;
307 else {
308 char head_path[MAX_PATH] = "HEAD";
309 if (!is_directory)
310 sprintf(head_path, "HEAD:%s%s",
311 output.buf,
312 this_->name + strlen(wd) + 1);
314 status = exec_program(wd, NULL, NULL, WAITMODE,
315 "git", "rev-parse", "--verify", head_path, NULL);
316 if (status < 0) /* something went terribly wrong */
317 selection = MENU_ITEM_LAST;
318 else
319 selection |= MENU_ITEM_REPO |
320 (status ?
321 MENU_ITEM_NOTRACK : MENU_ITEM_TRACK);
324 strbuf_release(&output);
325 free(wd);
326 return selection;
329 const struct menu_item cheetah_menu[] = {
330 { MENU_ITEM_ALWAYS, 0, NULL, NULL, build_separator, NULL },
332 { MENU_ITEM_REPO, 0, "Git &Add all files now",
333 "Add all files from this folder now",
334 build_item, menu_addall },
335 { MENU_ITEM_REPO, 0, "Git &Commit Tool",
336 "Launch the GIT commit tool in the local or chosen directory.",
337 build_item, menu_citool },
338 { MENU_ITEM_TRACK, 0, "Git &History",
339 "Show GIT history of the chosen file or directory.",
340 build_item,
341 menu_history },
342 { MENU_ITEM_TRACK | MENU_ITEM_FILE, 0, "Git &Blame",
343 "Start a blame viewer on the specified file.",
344 build_item, menu_blame },
346 { MENU_ITEM_REPO, 0, "Git &Gui",
347 "Launch the GIT Gui in the local or chosen directory.",
348 build_item, menu_gui },
350 { MENU_ITEM_REPO, 0, "Git Bra&nch",
351 "Checkout a branch",
352 build_branch_menu, NULL },
354 { MENU_ITEM_NOREPO, 0, "Git I&nit Here",
355 "Initialize GIT repo in the local directory.",
356 build_item, menu_init },
357 { MENU_ITEM_NOREPO | MENU_ITEM_DIR, 0, "Git &Gui",
358 "Launch the GIT Gui in the local or chosen directory.",
359 build_item, menu_gui },
361 { MENU_ITEM_ALWAYS, 0, "Git Ba&sh",
362 "Start GIT shell in the local or chosen directory",
363 build_item, menu_bash },
364 { MENU_ITEM_ALWAYS, 0, NULL, NULL, build_separator, NULL },
367 void build_cheetah_menu(struct git_data *data, void *platform_data)
369 reset_platform(platform_data);
370 build_menu_items(data, cheetah_menu_mask,
371 cheetah_menu,
372 sizeof(cheetah_menu) / sizeof(cheetah_menu[0]),
373 platform_data);