add -p: adjust offsets of subsequent hunks when one is skipped
[gitweb.git] / run-command.c
index 2ffbd7e67b20d2680cbe00b76b7ff3a5dcf2da06..31fc5ea86eb6a3fe3650b8ac50f19f8621d90b9d 100644 (file)
@@ -5,6 +5,7 @@
 #include "argv-array.h"
 #include "thread-utils.h"
 #include "strbuf.h"
+#include "string-list.h"
 
 void child_process_init(struct child_process *child)
 {
@@ -159,6 +160,23 @@ int is_executable(const char *name)
        return st.st_mode & S_IXUSR;
 }
 
+/*
+ * Search $PATH for a command.  This emulates the path search that
+ * execvp would perform, without actually executing the command so it
+ * can be used before fork() to prepare to run a command using
+ * execve() or after execvp() to diagnose why it failed.
+ *
+ * The caller should ensure that file contains no directory
+ * separators.
+ *
+ * Returns the path to the command, as found in $PATH or NULL if the
+ * command could not be found.  The caller inherits ownership of the memory
+ * used to store the resultant path.
+ *
+ * This should not be used on Windows, where the $PATH search rules
+ * are more complicated (e.g., a search for "foo" should find
+ * "foo.exe").
+ */
 static char *locate_in_PATH(const char *file)
 {
        const char *p = getenv("PATH");
@@ -179,7 +197,7 @@ static char *locate_in_PATH(const char *file)
                }
                strbuf_addstr(&buf, file);
 
-               if (!access(buf.buf, F_OK))
+               if (is_executable(buf.buf))
                        return strbuf_detach(&buf, NULL);
 
                if (!*end)
@@ -435,7 +453,7 @@ static char **prep_childenv(const char *const *deltaenv)
        }
 
        /* Create an array of 'char *' to be used as the childenv */
-       childenv = xmalloc((env.nr + 1) * sizeof(char *));
+       ALLOC_ARRAY(childenv, env.nr + 1);
        for (i = 0; i < env.nr; i++)
                childenv[i] = env.items[i].util;
        childenv[env.nr] = NULL;
@@ -1152,11 +1170,28 @@ const char *find_hook(const char *name)
        strbuf_reset(&path);
        strbuf_git_path(&path, "hooks/%s", name);
        if (access(path.buf, X_OK) < 0) {
+               int err = errno;
+
 #ifdef STRIP_EXTENSION
                strbuf_addstr(&path, STRIP_EXTENSION);
                if (access(path.buf, X_OK) >= 0)
                        return path.buf;
+               if (errno == EACCES)
+                       err = errno;
 #endif
+
+               if (err == EACCES && advice_ignored_hook) {
+                       static struct string_list advise_given = STRING_LIST_INIT_DUP;
+
+                       if (!string_list_lookup(&advise_given, name)) {
+                               string_list_insert(&advise_given, name);
+                               advise(_("The '%s' hook was ignored because "
+                                        "it's not set as executable.\n"
+                                        "You can disable this warning with "
+                                        "`git config advice.ignoredHook false`."),
+                                      path.buf);
+                       }
+               }
                return NULL;
        }
        return path.buf;
@@ -1516,7 +1551,7 @@ static int pp_start_one(struct parallel_processes *pp)
        if (start_command(&pp->children[i].process)) {
                code = pp->start_failure(&pp->children[i].err,
                                         pp->data,
-                                        &pp->children[i].data);
+                                        pp->children[i].data);
                strbuf_addbuf(&pp->buffered_output, &pp->children[i].err);
                strbuf_reset(&pp->children[i].err);
                if (code)
@@ -1584,7 +1619,7 @@ static int pp_collect_finished(struct parallel_processes *pp)
 
                code = pp->task_finished(code,
                                         &pp->children[i].err, pp->data,
-                                        &pp->children[i].data);
+                                        pp->children[i].data);
 
                if (code)
                        result = code;