@matheusbsbs / matheus-bagliano / commits / e69164ddb9
Fork 0

Add interactive mode to git-shell for user-friendliness

Signed-off-by: Greg Brockman <gdb@mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Greg Brockman committed Jul 28, 2010 at 00:43 UTC e69164ddb9d6092a94915bb984749d48f598cea8
1 file changed +68 -8
shell.c
+68 -8
@@ -2,8 +2,10 @@
2 #include "quote.h"
3 #include "exec_cmd.h"
4 #include "strbuf.h"
5 +#include "run-command.h"
6
7 #define COMMAND_DIR "git-shell-commands"
8 +#define HELP_COMMAND COMMAND_DIR "/help"
9
10 static int do_generic_cmd(const char *me, char *arg)
11 {
@@ -59,6 +61,56 @@ static void cd_to_homedir(void)
61 die("could not chdir to user's home directory");
62 }
63
64 +static void run_shell(void)
65 +{
66 + int done = 0;
67 + static const char *help_argv[] = { HELP_COMMAND, NULL };
68 + /* Print help if enabled */
69 + run_command_v_opt(help_argv, RUN_SILENT_EXEC_FAILURE);
70 +
71 + do {
72 + struct strbuf line = STRBUF_INIT;
73 + const char *prog;
74 + char *full_cmd;
75 + char *rawargs;
76 + const char **argv;
77 + int code;
78 +
79 + fprintf(stderr, "git> ");
80 + if (strbuf_getline(&line, stdin, '\n') == EOF) {
81 + fprintf(stderr, "\n");
82 + strbuf_release(&line);
83 + break;
84 + }
85 + strbuf_trim(&line);
86 + rawargs = strbuf_detach(&line, NULL);
87 + if (split_cmdline(rawargs, &argv) == -1) {
88 + free(rawargs);
89 + continue;
90 + }
91 +
92 + prog = argv[0];
93 + if (!strcmp(prog, "")) {
94 + } else if (!strcmp(prog, "quit") || !strcmp(prog, "logout") ||
95 + !strcmp(prog, "exit") || !strcmp(prog, "bye")) {
96 + done = 1;
97 + } else if (is_valid_cmd_name(prog)) {
98 + full_cmd = make_cmd(prog);
99 + argv[0] = full_cmd;
100 + code = run_command_v_opt(argv, RUN_SILENT_EXEC_FAILURE);
101 + if (code == -1 && errno == ENOENT) {
102 + fprintf(stderr, "unrecognized command '%s'\n", prog);
103 + }
104 + free(full_cmd);
105 + } else {
106 + fprintf(stderr, "invalid command format '%s'\n", prog);
107 + }
108 +
109 + free(argv);
110 + free(rawargs);
111 + } while (!done);
112 +}
113 +
114 static struct commands {
115 const char *name;
116 int (*exec)(const char *me, char *arg);
@@ -92,15 +144,23 @@ int main(int argc, char **argv)
144 /*
145 * Special hack to pretend to be a CVS server
146 */
95 - if (argc == 2 && !strcmp(argv[1], "cvs server"))
147 + if (argc == 2 && !strcmp(argv[1], "cvs server")) {
148 argv--;
97 -
98 - /*
99 - * We do not accept anything but "-c" followed by "cmd arg",
100 - * where "cmd" is a very limited subset of git commands.
101 - */
102 - else if (argc != 3 || strcmp(argv[1], "-c"))
103 - die("What do you think I am? A shell?");
149 + } else if (argc == 1) {
150 + /* Allow the user to run an interactive shell */
151 + cd_to_homedir();
152 + if (access(COMMAND_DIR, R_OK | X_OK) == -1)
153 + die("Sorry, the interactive git-shell is not enabled");
154 + run_shell();
155 + exit(0);
156 + } else if (argc != 3 || strcmp(argv[1], "-c")) {
157 + /*
158 + * We do not accept any other modes except "-c" followed by
159 + * "cmd arg", where "cmd" is a very limited subset of git
160 + * commands or a command in the COMMAND_DIR
161 + */
162 + die("Run with no arguments or with -c cmd");
163 + }
164
165 prog = xstrdup(argv[2]);
166 if (!strncmp(prog, "git", 3) && isspace(prog[3]))