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>
This commit is contained in:
parent
45afb1ca9c
commit
38124a40e4
43
help.c
43
help.c
@ -1,6 +1,7 @@
|
|||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
#include "builtin.h"
|
#include "builtin.h"
|
||||||
#include "exec_cmd.h"
|
#include "exec_cmd.h"
|
||||||
|
#include "run-command.h"
|
||||||
#include "levenshtein.h"
|
#include "levenshtein.h"
|
||||||
#include "help.h"
|
#include "help.h"
|
||||||
#include "common-cmds.h"
|
#include "common-cmds.h"
|
||||||
@ -96,48 +97,6 @@ static void pretty_print_cmdnames(struct cmdnames *cmds, unsigned int colopts)
|
|||||||
string_list_clear(&list, 0);
|
string_list_clear(&list, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int is_executable(const char *name)
|
|
||||||
{
|
|
||||||
struct stat st;
|
|
||||||
|
|
||||||
if (stat(name, &st) || /* stat, not lstat */
|
|
||||||
!S_ISREG(st.st_mode))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
#if defined(GIT_WINDOWS_NATIVE)
|
|
||||||
/*
|
|
||||||
* On Windows there is no executable bit. The file extension
|
|
||||||
* indicates whether it can be run as an executable, and Git
|
|
||||||
* has special-handling to detect scripts and launch them
|
|
||||||
* through the indicated script interpreter. We test for the
|
|
||||||
* file extension first because virus scanners may make
|
|
||||||
* it quite expensive to open many files.
|
|
||||||
*/
|
|
||||||
if (ends_with(name, ".exe"))
|
|
||||||
return S_IXUSR;
|
|
||||||
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Now that we know it does not have an executable extension,
|
|
||||||
* peek into the file instead.
|
|
||||||
*/
|
|
||||||
char buf[3] = { 0 };
|
|
||||||
int n;
|
|
||||||
int fd = open(name, O_RDONLY);
|
|
||||||
st.st_mode &= ~S_IXUSR;
|
|
||||||
if (fd >= 0) {
|
|
||||||
n = read(fd, buf, 2);
|
|
||||||
if (n == 2)
|
|
||||||
/* look for a she-bang */
|
|
||||||
if (!strcmp(buf, "#!"))
|
|
||||||
st.st_mode |= S_IXUSR;
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return st.st_mode & S_IXUSR;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void list_commands_in_dir(struct cmdnames *cmds,
|
static void list_commands_in_dir(struct cmdnames *cmds,
|
||||||
const char *path,
|
const char *path,
|
||||||
const char *prefix)
|
const char *prefix)
|
||||||
|
@ -117,6 +117,48 @@ static inline void close_pair(int fd[2])
|
|||||||
close(fd[1]);
|
close(fd[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int is_executable(const char *name)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
if (stat(name, &st) || /* stat, not lstat */
|
||||||
|
!S_ISREG(st.st_mode))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#if defined(GIT_WINDOWS_NATIVE)
|
||||||
|
/*
|
||||||
|
* On Windows there is no executable bit. The file extension
|
||||||
|
* indicates whether it can be run as an executable, and Git
|
||||||
|
* has special-handling to detect scripts and launch them
|
||||||
|
* through the indicated script interpreter. We test for the
|
||||||
|
* file extension first because virus scanners may make
|
||||||
|
* it quite expensive to open many files.
|
||||||
|
*/
|
||||||
|
if (ends_with(name, ".exe"))
|
||||||
|
return S_IXUSR;
|
||||||
|
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Now that we know it does not have an executable extension,
|
||||||
|
* peek into the file instead.
|
||||||
|
*/
|
||||||
|
char buf[3] = { 0 };
|
||||||
|
int n;
|
||||||
|
int fd = open(name, O_RDONLY);
|
||||||
|
st.st_mode &= ~S_IXUSR;
|
||||||
|
if (fd >= 0) {
|
||||||
|
n = read(fd, buf, 2);
|
||||||
|
if (n == 2)
|
||||||
|
/* look for a she-bang */
|
||||||
|
if (!strcmp(buf, "#!"))
|
||||||
|
st.st_mode |= S_IXUSR;
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return st.st_mode & S_IXUSR;
|
||||||
|
}
|
||||||
|
|
||||||
static char *locate_in_PATH(const char *file)
|
static char *locate_in_PATH(const char *file)
|
||||||
{
|
{
|
||||||
const char *p = getenv("PATH");
|
const char *p = getenv("PATH");
|
||||||
|
@ -51,6 +51,7 @@ struct child_process {
|
|||||||
#define CHILD_PROCESS_INIT { NULL, ARGV_ARRAY_INIT, ARGV_ARRAY_INIT }
|
#define CHILD_PROCESS_INIT { NULL, ARGV_ARRAY_INIT, ARGV_ARRAY_INIT }
|
||||||
void child_process_init(struct child_process *);
|
void child_process_init(struct child_process *);
|
||||||
void child_process_clear(struct child_process *);
|
void child_process_clear(struct child_process *);
|
||||||
|
extern int is_executable(const char *name);
|
||||||
|
|
||||||
int start_command(struct child_process *);
|
int start_command(struct child_process *);
|
||||||
int finish_command(struct child_process *);
|
int finish_command(struct child_process *);
|
||||||
|
Loading…
Reference in New Issue
Block a user