From: Felipe Contreras Date: Sat, 08 Jun 2013 10:02:44 GMT Subject: Re: [Administrivia] On ruby and contrib/ Message-ID: In-Reply-To: On Fri, Jun 7, 2013 at 9:17 PM, Duy Nguyen wrote: > On Thu, Jun 6, 2013 at 11:22 PM, Johannes Schindelin > wrote: >> Hi Greg, >> >> On Thu, 6 Jun 2013, Greg Troxel wrote: >> >>> As one of the people who helps maintain git packages in pkgsrc, my >>> initial reaction is negative to adding a ruby dependency. >> >> My initial reaction, too. It was hard enough to get Perl included with Git >> for Windows (because of that pesky Subversion dependency). >> >> As you can see from the commit history, I was the primary force behind >> trying to get everything "core" in Git away from requiring scripting >> languages (I think it is an awesome thing to provide APIs for as many >> languages as possible, but a not-so-cool thing to use more than one >> language in the core code). It does not seem that anybody picked up that >> task when I left, though. > > Nobody seems to mention it yet. There's another reason behind the C > rewrite effort: fork is costly on Windows. The C rewrite allows us to > run with one process (most of the time). This applies for shell, perl > and even ruby scripts because libgit.a is never meant to be used > outside git.c context (unlike libgit2). In this regard, ruby is just > as bad as currently supported non-C languages. Are you sure? --- #!/bin/sh cat > /tmp/test < #include #include #undef NORETURN #undef PATH_SEP #include static VALUE shellwords; struct cmd_struct { const char *cmd; int (*fn)(int, const char **, const char *); int option; }; #define RUN_SETUP (1 << 0) #define RUN_SETUP_GENTLY (1 << 1) #define USE_PAGER (1 << 2) #define NEED_WORK_TREE (1 << 3) static struct cmd_struct commands[] = { { "rev-parse", cmd_rev_parse }, { "show", cmd_show, RUN_SETUP }, }; static VALUE git_rb_backticks(int o_argc, VALUE *o_argv, VALUE ctx) { int argc, i, old; int pipefd[2]; const char **argv; char buf[0x1000]; VALUE command; int do_read; struct cmd_struct *cmd = NULL; const char *prefix = NULL; if (strncmp(RSTRING_PTR(o_argv[0]), "git ", 4)) { VALUE port, result; port = rb_funcall(rb_cIO, rb_intern("popen"), 1, o_argv[0]); result = rb_funcall(port, rb_intern("read"), 0); rb_funcall(result, rb_intern("chomp!"), 0); rb_io_close(port); return result; } command = rb_funcall(shellwords, rb_intern("shellsplit"), 1, o_argv[0]); rb_ary_shift(command); argc = RARRAY_LEN(command); argv = xcalloc(sizeof(*argv), argc); VALUE *rarray = RARRAY_PTR(command); for (i = 0; i < argc; i++) argv[i] = RSTRING_PTR(rarray[i]); old = dup(1); i = pipe(pipefd); dup2(pipefd[1], 1); close(pipefd[1]); for (i = 0; i < ARRAY_SIZE(commands); i++) { struct cmd_struct *p = &commands[i]; if (strcmp(p->cmd, argv[0])) continue; cmd = p; } if (!cmd) rb_raise(rb_eArgError, "unknown command: %s", argv[0]); if (cmd->option & RUN_SETUP) prefix = setup_git_directory(); i = cmd->fn(argc, argv, prefix); rb_last_status_set(i, getpid()); fflush(stdout); dup2(old, 1); i = read(pipefd[0], buf, sizeof(buf)); if (buf[i - 1] == '\n') i -= 1; buf[i] = '\0'; return rb_str_new(buf, i); } void Init_git(void) { rb_require("shellwords"); shellwords = rb_define_module("Shellwords"); rb_define_global_function("`", git_rb_backticks, -1); }