upload-pack: Run rev-list in an asynchronous function.
[gitweb.git] / diff.c
diff --git a/diff.c b/diff.c
index fb6d077f06338271f16bfabb3e0c45f000de15ac..30b75441712edc29213589760bcb47900830fe7b 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -9,6 +9,7 @@
 #include "xdiff-interface.h"
 #include "color.h"
 #include "attr.h"
+#include "run-command.h"
 
 #ifdef NO_FAST_WORKING_DIRECTORY
 #define FAST_WORKING_DIRECTORY 0
@@ -197,7 +198,7 @@ static char *quote_two(const char *one, const char *two)
                strbuf_addstr(&res, one);
                strbuf_addstr(&res, two);
        }
-       return res.buf;
+       return strbuf_detach(&res, NULL);
 }
 
 static const char *external_diff(void)
@@ -662,7 +663,7 @@ static char *pprint_rename(const char *a, const char *b)
                quote_c_style(a, &name, NULL, 0);
                strbuf_addstr(&name, " => ");
                quote_c_style(b, &name, NULL, 0);
-               return name.buf;
+               return strbuf_detach(&name, NULL);
        }
 
        /* Find common prefix */
@@ -710,7 +711,7 @@ static char *pprint_rename(const char *a, const char *b)
                strbuf_addch(&name, '}');
                strbuf_add(&name, a + len_a - sfx_length, sfx_length);
        }
-       return name.buf;
+       return strbuf_detach(&name, NULL);
 }
 
 struct diffstat_t {
@@ -827,7 +828,7 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options)
                        strbuf_init(&buf, 0);
                        if (quote_c_style(file->name, &buf, NULL, 0)) {
                                free(file->name);
-                               file->name = buf.buf;
+                               file->name = strbuf_detach(&buf, NULL);
                        } else {
                                strbuf_release(&buf);
                        }
@@ -1519,8 +1520,7 @@ static int populate_from_stdin(struct diff_filespec *s)
                                     strerror(errno));
 
        s->should_munmap = 0;
-       s->size = buf.len;
-       s->data = strbuf_detach(&buf);
+       s->data = strbuf_detach(&buf, &s->size);
        s->should_free = 1;
        return 0;
 }
@@ -1612,8 +1612,7 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only)
                if (convert_to_git(s->path, s->data, s->size, &buf)) {
                        munmap(s->data, s->size);
                        s->should_munmap = 0;
-                       s->data = buf.buf;
-                       s->size = buf.len;
+                       s->data = strbuf_detach(&buf, &s->size);
                        s->should_free = 1;
                }
        }
@@ -1629,7 +1628,7 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only)
        return 0;
 }
 
-void diff_free_filespec_data(struct diff_filespec *s)
+void diff_free_filespec_blob(struct diff_filespec *s)
 {
        if (s->should_free)
                free(s->data);
@@ -1640,6 +1639,11 @@ void diff_free_filespec_data(struct diff_filespec *s)
                s->should_free = s->should_munmap = 0;
                s->data = NULL;
        }
+}
+
+void diff_free_filespec_data(struct diff_filespec *s)
+{
+       diff_free_filespec_blob(s);
        free(s->cnt_data);
        s->cnt_data = NULL;
 }
@@ -1745,40 +1749,6 @@ static void remove_tempfile_on_signal(int signo)
        raise(signo);
 }
 
-static int spawn_prog(const char *pgm, const char **arg)
-{
-       pid_t pid;
-       int status;
-
-       fflush(NULL);
-       pid = fork();
-       if (pid < 0)
-               die("unable to fork");
-       if (!pid) {
-               execvp(pgm, (char *const*) arg);
-               exit(255);
-       }
-
-       while (waitpid(pid, &status, 0) < 0) {
-               if (errno == EINTR)
-                       continue;
-               return -1;
-       }
-
-       /* Earlier we did not check the exit status because
-        * diff exits non-zero if files are different, and
-        * we are not interested in knowing that.  It was a
-        * mistake which made it harder to quit a diff-*
-        * session that uses the git-apply-patch-script as
-        * the GIT_EXTERNAL_DIFF.  A custom GIT_EXTERNAL_DIFF
-        * should also exit non-zero only when it wants to
-        * abort the entire diff-* session.
-        */
-       if (WIFEXITED(status) && !WEXITSTATUS(status))
-               return 0;
-       return -1;
-}
-
 /* An external diff command takes:
  *
  * diff-cmd name infile1 infile1-sha1 infile1-mode \
@@ -1831,7 +1801,8 @@ static void run_external_diff(const char *pgm,
                *arg++ = name;
        }
        *arg = NULL;
-       retval = spawn_prog(pgm, spawn_arg);
+       fflush(NULL);
+       retval = run_command_v_opt(spawn_arg, 0);
        remove_tempfile();
        if (retval) {
                fprintf(stderr, "external diff died, stopping at %s.\n", name);