run-command: expose is_executable function

Move the logic for 'is_executable()' from help.c to run_command.c and expose it so that callers from outside help.c can access the function. This is to enable run-command to be able to query if a file is executable in a future patch. Signed-off-by: Brandon Williams <bmwill@google.com> Reviewed-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Brandon Williams committed Apr 25, 2017 at 16:46 UTC 38124a40e480c1717326b7bc27bcbca758de908e
3 files changed +44 -42
help.c
+1 -42
@@ -1,6 +1,7 @@
1 #include "cache.h"
2 #include "builtin.h"
3 #include "exec_cmd.h"
4 +#include "run-command.h"
5 #include "levenshtein.h"
6 #include "help.h"
7 #include "common-cmds.h"
@@ -96,48 +97,6 @@ static void pretty_print_cmdnames(struct cmdnames *cmds, unsigned int colopts)
97 string_list_clear(&list, 0);
98 }
99
99 -static int is_executable(const char *name)
100 -{
101 - struct stat st;
102 -
103 - if (stat(name, &st) || /* stat, not lstat */
104 - !S_ISREG(st.st_mode))
105 - return 0;
106 -
107 -#if defined(GIT_WINDOWS_NATIVE)
108 - /*
109 - * On Windows there is no executable bit. The file extension
110 - * indicates whether it can be run as an executable, and Git
111 - * has special-handling to detect scripts and launch them
112 - * through the indicated script interpreter. We test for the
113 - * file extension first because virus scanners may make
114 - * it quite expensive to open many files.
115 - */
116 - if (ends_with(name, ".exe"))
117 - return S_IXUSR;
118 -
119 -{
120 - /*
121 - * Now that we know it does not have an executable extension,
122 - * peek into the file instead.
123 - */
124 - char buf[3] = { 0 };
125 - int n;
126 - int fd = open(name, O_RDONLY);
127 - st.st_mode &= ~S_IXUSR;
128 - if (fd >= 0) {
129 - n = read(fd, buf, 2);
130 - if (n == 2)
131 - /* look for a she-bang */
132 - if (!strcmp(buf, "#!"))
133 - st.st_mode |= S_IXUSR;
134 - close(fd);
135 - }
136 -}
137 -#endif
138 - return st.st_mode & S_IXUSR;
139 -}
140 -
100 static void list_commands_in_dir(struct cmdnames *cmds,
101 const char *path,
102 const char *prefix)
run-command.c
+42
@@ -117,6 +117,48 @@ static inline void close_pair(int fd[2])
117 close(fd[1]);
118 }
119
120 +int is_executable(const char *name)
121 +{
122 + struct stat st;
123 +
124 + if (stat(name, &st) || /* stat, not lstat */
125 + !S_ISREG(st.st_mode))
126 + return 0;
127 +
128 +#if defined(GIT_WINDOWS_NATIVE)
129 + /*
130 + * On Windows there is no executable bit. The file extension
131 + * indicates whether it can be run as an executable, and Git
132 + * has special-handling to detect scripts and launch them
133 + * through the indicated script interpreter. We test for the
134 + * file extension first because virus scanners may make
135 + * it quite expensive to open many files.
136 + */
137 + if (ends_with(name, ".exe"))
138 + return S_IXUSR;
139 +
140 +{
141 + /*
142 + * Now that we know it does not have an executable extension,
143 + * peek into the file instead.
144 + */
145 + char buf[3] = { 0 };
146 + int n;
147 + int fd = open(name, O_RDONLY);
148 + st.st_mode &= ~S_IXUSR;
149 + if (fd >= 0) {
150 + n = read(fd, buf, 2);
151 + if (n == 2)
152 + /* look for a she-bang */
153 + if (!strcmp(buf, "#!"))
154 + st.st_mode |= S_IXUSR;
155 + close(fd);
156 + }
157 +}
158 +#endif
159 + return st.st_mode & S_IXUSR;
160 +}
161 +
162 static char *locate_in_PATH(const char *file)
163 {
164 const char *p = getenv("PATH");
run-command.h
+1
@@ -51,6 +51,7 @@ struct child_process {
51 #define CHILD_PROCESS_INIT { NULL, ARGV_ARRAY_INIT, ARGV_ARRAY_INIT }
52 void child_process_init(struct child_process *);
53 void child_process_clear(struct child_process *);
54 +extern int is_executable(const char *name);
55
56 int start_command(struct child_process *);
57 int finish_command(struct child_process *);