зеркало из https://github.com/microsoft/git.git
Merge branch 'rs/strbuf-getcwd'
Reduce the use of fixed sized buffer passed to getcwd() calls by introducing xgetcwd() helper. * rs/strbuf-getcwd: use strbuf_add_absolute_path() to add absolute paths abspath: convert absolute_path() to strbuf use xgetcwd() to set $GIT_DIR use xgetcwd() to get the current directory or die wrapper: add xgetcwd() abspath: convert real_path_internal() to strbuf abspath: use strbuf_getcwd() to remember original working directory setup: convert setup_git_directory_gently_1 et al. to strbuf unix-sockets: use strbuf_getcwd() strbuf: add strbuf_getcwd()
This commit is contained in:
Коммит
f655651e09
|
@ -307,6 +307,16 @@ same behaviour as well.
|
|||
use it unless you need the correct position in the file
|
||||
descriptor.
|
||||
|
||||
`strbuf_getcwd`::
|
||||
|
||||
Set the buffer to the path of the current working directory.
|
||||
|
||||
`strbuf_add_absolute_path`
|
||||
|
||||
Add a path to a buffer, converting a relative path to an
|
||||
absolute one in the process. Symbolic links are not
|
||||
resolved.
|
||||
|
||||
`stripspace`::
|
||||
|
||||
Strip whitespace from a buffer. The second parameter controls if
|
||||
|
|
124
abspath.c
124
abspath.c
|
@ -33,7 +33,7 @@ int is_directory(const char *path)
|
|||
*/
|
||||
static const char *real_path_internal(const char *path, int die_on_error)
|
||||
{
|
||||
static char bufs[2][PATH_MAX + 1], *buf = bufs[0], *next_buf = bufs[1];
|
||||
static struct strbuf sb = STRBUF_INIT;
|
||||
char *retval = NULL;
|
||||
|
||||
/*
|
||||
|
@ -41,16 +41,14 @@ static const char *real_path_internal(const char *path, int die_on_error)
|
|||
* here so that we can chdir() back to it at the end of the
|
||||
* function:
|
||||
*/
|
||||
char cwd[1024] = "";
|
||||
|
||||
int buf_index = 1;
|
||||
struct strbuf cwd = STRBUF_INIT;
|
||||
|
||||
int depth = MAXDEPTH;
|
||||
char *last_elem = NULL;
|
||||
struct stat st;
|
||||
|
||||
/* We've already done it */
|
||||
if (path == buf || path == next_buf)
|
||||
if (path == sb.buf)
|
||||
return path;
|
||||
|
||||
if (!*path) {
|
||||
|
@ -60,41 +58,38 @@ static const char *real_path_internal(const char *path, int die_on_error)
|
|||
goto error_out;
|
||||
}
|
||||
|
||||
if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX) {
|
||||
if (die_on_error)
|
||||
die("Too long path: %.*s", 60, path);
|
||||
else
|
||||
goto error_out;
|
||||
}
|
||||
strbuf_reset(&sb);
|
||||
strbuf_addstr(&sb, path);
|
||||
|
||||
while (depth--) {
|
||||
if (!is_directory(buf)) {
|
||||
char *last_slash = find_last_dir_sep(buf);
|
||||
if (!is_directory(sb.buf)) {
|
||||
char *last_slash = find_last_dir_sep(sb.buf);
|
||||
if (last_slash) {
|
||||
last_elem = xstrdup(last_slash + 1);
|
||||
last_slash[1] = '\0';
|
||||
strbuf_setlen(&sb, last_slash - sb.buf + 1);
|
||||
} else {
|
||||
last_elem = xstrdup(buf);
|
||||
*buf = '\0';
|
||||
last_elem = xmemdupz(sb.buf, sb.len);
|
||||
strbuf_reset(&sb);
|
||||
}
|
||||
}
|
||||
|
||||
if (*buf) {
|
||||
if (!*cwd && !getcwd(cwd, sizeof(cwd))) {
|
||||
if (sb.len) {
|
||||
if (!cwd.len && strbuf_getcwd(&cwd)) {
|
||||
if (die_on_error)
|
||||
die_errno("Could not get current working directory");
|
||||
else
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if (chdir(buf)) {
|
||||
if (chdir(sb.buf)) {
|
||||
if (die_on_error)
|
||||
die_errno("Could not switch to '%s'", buf);
|
||||
die_errno("Could not switch to '%s'",
|
||||
sb.buf);
|
||||
else
|
||||
goto error_out;
|
||||
}
|
||||
}
|
||||
if (!getcwd(buf, PATH_MAX)) {
|
||||
if (strbuf_getcwd(&sb)) {
|
||||
if (die_on_error)
|
||||
die_errno("Could not get current working directory");
|
||||
else
|
||||
|
@ -102,48 +97,35 @@ static const char *real_path_internal(const char *path, int die_on_error)
|
|||
}
|
||||
|
||||
if (last_elem) {
|
||||
size_t len = strlen(buf);
|
||||
if (len + strlen(last_elem) + 2 > PATH_MAX) {
|
||||
if (die_on_error)
|
||||
die("Too long path name: '%s/%s'",
|
||||
buf, last_elem);
|
||||
else
|
||||
goto error_out;
|
||||
}
|
||||
if (len && !is_dir_sep(buf[len - 1]))
|
||||
buf[len++] = '/';
|
||||
strcpy(buf + len, last_elem);
|
||||
if (sb.len && !is_dir_sep(sb.buf[sb.len - 1]))
|
||||
strbuf_addch(&sb, '/');
|
||||
strbuf_addstr(&sb, last_elem);
|
||||
free(last_elem);
|
||||
last_elem = NULL;
|
||||
}
|
||||
|
||||
if (!lstat(buf, &st) && S_ISLNK(st.st_mode)) {
|
||||
ssize_t len = readlink(buf, next_buf, PATH_MAX);
|
||||
if (!lstat(sb.buf, &st) && S_ISLNK(st.st_mode)) {
|
||||
struct strbuf next_sb = STRBUF_INIT;
|
||||
ssize_t len = strbuf_readlink(&next_sb, sb.buf, 0);
|
||||
if (len < 0) {
|
||||
if (die_on_error)
|
||||
die_errno("Invalid symlink '%s'", buf);
|
||||
die_errno("Invalid symlink '%s'",
|
||||
sb.buf);
|
||||
else
|
||||
goto error_out;
|
||||
}
|
||||
if (PATH_MAX <= len) {
|
||||
if (die_on_error)
|
||||
die("symbolic link too long: %s", buf);
|
||||
else
|
||||
goto error_out;
|
||||
}
|
||||
next_buf[len] = '\0';
|
||||
buf = next_buf;
|
||||
buf_index = 1 - buf_index;
|
||||
next_buf = bufs[buf_index];
|
||||
strbuf_swap(&sb, &next_sb);
|
||||
strbuf_release(&next_sb);
|
||||
} else
|
||||
break;
|
||||
}
|
||||
|
||||
retval = buf;
|
||||
retval = sb.buf;
|
||||
error_out:
|
||||
free(last_elem);
|
||||
if (*cwd && chdir(cwd))
|
||||
die_errno("Could not change back to '%s'", cwd);
|
||||
if (cwd.len && chdir(cwd.buf))
|
||||
die_errno("Could not change back to '%s'", cwd.buf);
|
||||
strbuf_release(&cwd);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -158,54 +140,16 @@ const char *real_path_if_valid(const char *path)
|
|||
return real_path_internal(path, 0);
|
||||
}
|
||||
|
||||
static const char *get_pwd_cwd(void)
|
||||
{
|
||||
static char cwd[PATH_MAX + 1];
|
||||
char *pwd;
|
||||
struct stat cwd_stat, pwd_stat;
|
||||
if (getcwd(cwd, PATH_MAX) == NULL)
|
||||
return NULL;
|
||||
pwd = getenv("PWD");
|
||||
if (pwd && strcmp(pwd, cwd)) {
|
||||
stat(cwd, &cwd_stat);
|
||||
if ((cwd_stat.st_dev || cwd_stat.st_ino) &&
|
||||
!stat(pwd, &pwd_stat) &&
|
||||
pwd_stat.st_dev == cwd_stat.st_dev &&
|
||||
pwd_stat.st_ino == cwd_stat.st_ino) {
|
||||
strlcpy(cwd, pwd, PATH_MAX);
|
||||
}
|
||||
}
|
||||
return cwd;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use this to get an absolute path from a relative one. If you want
|
||||
* to resolve links, you should use real_path.
|
||||
*
|
||||
* If the path is already absolute, then return path. As the user is
|
||||
* never meant to free the return value, we're safe.
|
||||
*/
|
||||
const char *absolute_path(const char *path)
|
||||
{
|
||||
static char buf[PATH_MAX + 1];
|
||||
|
||||
if (!*path) {
|
||||
die("The empty string is not a valid path");
|
||||
} else if (is_absolute_path(path)) {
|
||||
if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
|
||||
die("Too long path: %.*s", 60, path);
|
||||
} else {
|
||||
size_t len;
|
||||
const char *fmt;
|
||||
const char *cwd = get_pwd_cwd();
|
||||
if (!cwd)
|
||||
die_errno("Cannot determine the current working directory");
|
||||
len = strlen(cwd);
|
||||
fmt = (len > 0 && is_dir_sep(cwd[len - 1])) ? "%s%s" : "%s/%s";
|
||||
if (snprintf(buf, PATH_MAX, fmt, cwd, path) >= PATH_MAX)
|
||||
die("Too long path: %.*s", 60, path);
|
||||
}
|
||||
return buf;
|
||||
static struct strbuf sb = STRBUF_INIT;
|
||||
strbuf_reset(&sb);
|
||||
strbuf_add_absolute_path(&sb, path);
|
||||
return sb.buf;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -426,8 +426,9 @@ int init_db(const char *template_dir, unsigned int flags)
|
|||
|
||||
static int guess_repository_type(const char *git_dir)
|
||||
{
|
||||
char cwd[PATH_MAX];
|
||||
const char *slash;
|
||||
char *cwd;
|
||||
int cwd_is_git_dir;
|
||||
|
||||
/*
|
||||
* "GIT_DIR=. git init" is always bare.
|
||||
|
@ -435,9 +436,10 @@ static int guess_repository_type(const char *git_dir)
|
|||
*/
|
||||
if (!strcmp(".", git_dir))
|
||||
return 1;
|
||||
if (!getcwd(cwd, sizeof(cwd)))
|
||||
die_errno(_("cannot tell cwd"));
|
||||
if (!strcmp(git_dir, cwd))
|
||||
cwd = xgetcwd();
|
||||
cwd_is_git_dir = !strcmp(git_dir, cwd);
|
||||
free(cwd);
|
||||
if (cwd_is_git_dir)
|
||||
return 1;
|
||||
/*
|
||||
* "GIT_DIR=.git or GIT_DIR=something/.git is usually not.
|
||||
|
@ -535,10 +537,9 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
|
|||
usage(init_db_usage[0]);
|
||||
}
|
||||
if (is_bare_repository_cfg == 1) {
|
||||
static char git_dir[PATH_MAX+1];
|
||||
|
||||
setenv(GIT_DIR_ENVIRONMENT,
|
||||
getcwd(git_dir, sizeof(git_dir)), argc > 0);
|
||||
char *cwd = xgetcwd();
|
||||
setenv(GIT_DIR_ENVIRONMENT, cwd, argc > 0);
|
||||
free(cwd);
|
||||
}
|
||||
|
||||
if (init_shared_repository != -1)
|
||||
|
@ -572,11 +573,8 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
|
|||
git_work_tree_cfg = xstrdup(real_path(rel));
|
||||
free(rel);
|
||||
}
|
||||
if (!git_work_tree_cfg) {
|
||||
git_work_tree_cfg = xcalloc(PATH_MAX, 1);
|
||||
if (!getcwd(git_work_tree_cfg, PATH_MAX))
|
||||
die_errno (_("Cannot access current working directory"));
|
||||
}
|
||||
if (!git_work_tree_cfg)
|
||||
git_work_tree_cfg = xgetcwd();
|
||||
if (work_tree)
|
||||
set_git_work_tree(work_tree);
|
||||
else
|
||||
|
|
|
@ -736,7 +736,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
|
|||
}
|
||||
if (!strcmp(arg, "--git-dir")) {
|
||||
const char *gitdir = getenv(GIT_DIR_ENVIRONMENT);
|
||||
static char cwd[PATH_MAX];
|
||||
char *cwd;
|
||||
int len;
|
||||
if (gitdir) {
|
||||
puts(gitdir);
|
||||
|
@ -746,10 +746,10 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
|
|||
puts(".git");
|
||||
continue;
|
||||
}
|
||||
if (!getcwd(cwd, PATH_MAX))
|
||||
die_errno("unable to get current working directory");
|
||||
cwd = xgetcwd();
|
||||
len = strlen(cwd);
|
||||
printf("%s%s.git\n", cwd, len && cwd[len-1] != '/' ? "/" : "");
|
||||
free(cwd);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--resolve-git-dir")) {
|
||||
|
|
12
dir.c
12
dir.c
|
@ -1507,12 +1507,16 @@ int dir_inside_of(const char *subdir, const char *dir)
|
|||
|
||||
int is_inside_dir(const char *dir)
|
||||
{
|
||||
char cwd[PATH_MAX];
|
||||
char *cwd;
|
||||
int rc;
|
||||
|
||||
if (!dir)
|
||||
return 0;
|
||||
if (!getcwd(cwd, sizeof(cwd)))
|
||||
die_errno("can't find the current directory");
|
||||
return dir_inside_of(cwd, dir) >= 0;
|
||||
|
||||
cwd = xgetcwd();
|
||||
rc = (dir_inside_of(cwd, dir) >= 0);
|
||||
free(cwd);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int is_empty_dir(const char *path)
|
||||
|
|
|
@ -86,11 +86,7 @@ const char *git_exec_path(void)
|
|||
static void add_path(struct strbuf *out, const char *path)
|
||||
{
|
||||
if (path && *path) {
|
||||
if (is_absolute_path(path))
|
||||
strbuf_addstr(out, path);
|
||||
else
|
||||
strbuf_addstr(out, absolute_path(path));
|
||||
|
||||
strbuf_add_absolute_path(out, path);
|
||||
strbuf_addch(out, PATH_SEP);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -607,6 +607,7 @@ extern int xmkstemp(char *template);
|
|||
extern int xmkstemp_mode(char *template, int mode);
|
||||
extern int odb_mkstemp(char *template, size_t limit, const char *pattern);
|
||||
extern int odb_pack_keep(char *name, size_t namesz, const unsigned char *sha1);
|
||||
extern char *xgetcwd(void);
|
||||
|
||||
static inline size_t xsize_t(off_t len)
|
||||
{
|
||||
|
|
13
git.c
13
git.c
|
@ -20,7 +20,7 @@ const char git_more_info_string[] =
|
|||
|
||||
static struct startup_info git_startup_info;
|
||||
static int use_pager = -1;
|
||||
static char orig_cwd[PATH_MAX];
|
||||
static char *orig_cwd;
|
||||
static const char *env_names[] = {
|
||||
GIT_DIR_ENVIRONMENT,
|
||||
GIT_WORK_TREE_ENVIRONMENT,
|
||||
|
@ -36,8 +36,7 @@ static void save_env(void)
|
|||
if (saved_environment)
|
||||
return;
|
||||
saved_environment = 1;
|
||||
if (!getcwd(orig_cwd, sizeof(orig_cwd)))
|
||||
die_errno("cannot getcwd");
|
||||
orig_cwd = xgetcwd();
|
||||
for (i = 0; i < ARRAY_SIZE(env_names); i++) {
|
||||
orig_env[i] = getenv(env_names[i]);
|
||||
if (orig_env[i])
|
||||
|
@ -48,8 +47,9 @@ static void save_env(void)
|
|||
static void restore_env(void)
|
||||
{
|
||||
int i;
|
||||
if (*orig_cwd && chdir(orig_cwd))
|
||||
if (orig_cwd && chdir(orig_cwd))
|
||||
die_errno("could not move to %s", orig_cwd);
|
||||
free(orig_cwd);
|
||||
for (i = 0; i < ARRAY_SIZE(env_names); i++) {
|
||||
if (orig_env[i])
|
||||
setenv(env_names[i], orig_env[i], 1);
|
||||
|
@ -161,9 +161,10 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
|
|||
if (envchanged)
|
||||
*envchanged = 1;
|
||||
} else if (!strcmp(cmd, "--bare")) {
|
||||
static char git_dir[PATH_MAX+1];
|
||||
char *cwd = xgetcwd();
|
||||
is_bare_repository_cfg = 1;
|
||||
setenv(GIT_DIR_ENVIRONMENT, getcwd(git_dir, sizeof(git_dir)), 0);
|
||||
setenv(GIT_DIR_ENVIRONMENT, cwd, 0);
|
||||
free(cwd);
|
||||
setenv(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT, "0", 1);
|
||||
if (envchanged)
|
||||
*envchanged = 1;
|
||||
|
|
93
setup.c
93
setup.c
|
@ -387,7 +387,7 @@ const char *read_gitfile(const char *path)
|
|||
}
|
||||
|
||||
static const char *setup_explicit_git_dir(const char *gitdirenv,
|
||||
char *cwd, int len,
|
||||
struct strbuf *cwd,
|
||||
int *nongit_ok)
|
||||
{
|
||||
const char *work_tree_env = getenv(GIT_WORK_TREE_ENVIRONMENT);
|
||||
|
@ -434,16 +434,16 @@ static const char *setup_explicit_git_dir(const char *gitdirenv,
|
|||
if (is_absolute_path(git_work_tree_cfg))
|
||||
set_git_work_tree(git_work_tree_cfg);
|
||||
else {
|
||||
char core_worktree[PATH_MAX];
|
||||
char *core_worktree;
|
||||
if (chdir(gitdirenv))
|
||||
die_errno("Could not chdir to '%s'", gitdirenv);
|
||||
if (chdir(git_work_tree_cfg))
|
||||
die_errno("Could not chdir to '%s'", git_work_tree_cfg);
|
||||
if (!getcwd(core_worktree, PATH_MAX))
|
||||
die_errno("Could not get directory '%s'", git_work_tree_cfg);
|
||||
if (chdir(cwd))
|
||||
core_worktree = xgetcwd();
|
||||
if (chdir(cwd->buf))
|
||||
die_errno("Could not come back to cwd");
|
||||
set_git_work_tree(core_worktree);
|
||||
free(core_worktree);
|
||||
}
|
||||
}
|
||||
else if (!git_env_bool(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT, 1)) {
|
||||
|
@ -459,21 +459,20 @@ static const char *setup_explicit_git_dir(const char *gitdirenv,
|
|||
worktree = get_git_work_tree();
|
||||
|
||||
/* both get_git_work_tree() and cwd are already normalized */
|
||||
if (!strcmp(cwd, worktree)) { /* cwd == worktree */
|
||||
if (!strcmp(cwd->buf, worktree)) { /* cwd == worktree */
|
||||
set_git_dir(gitdirenv);
|
||||
free(gitfile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
offset = dir_inside_of(cwd, worktree);
|
||||
offset = dir_inside_of(cwd->buf, worktree);
|
||||
if (offset >= 0) { /* cwd inside worktree? */
|
||||
set_git_dir(real_path(gitdirenv));
|
||||
if (chdir(worktree))
|
||||
die_errno("Could not chdir to '%s'", worktree);
|
||||
cwd[len++] = '/';
|
||||
cwd[len] = '\0';
|
||||
strbuf_addch(cwd, '/');
|
||||
free(gitfile);
|
||||
return cwd + offset;
|
||||
return cwd->buf + offset;
|
||||
}
|
||||
|
||||
/* cwd outside worktree */
|
||||
|
@ -483,7 +482,7 @@ static const char *setup_explicit_git_dir(const char *gitdirenv,
|
|||
}
|
||||
|
||||
static const char *setup_discovered_git_dir(const char *gitdir,
|
||||
char *cwd, int offset, int len,
|
||||
struct strbuf *cwd, int offset,
|
||||
int *nongit_ok)
|
||||
{
|
||||
if (check_repository_format_gently(gitdir, nongit_ok))
|
||||
|
@ -491,17 +490,17 @@ static const char *setup_discovered_git_dir(const char *gitdir,
|
|||
|
||||
/* --work-tree is set without --git-dir; use discovered one */
|
||||
if (getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) {
|
||||
if (offset != len && !is_absolute_path(gitdir))
|
||||
if (offset != cwd->len && !is_absolute_path(gitdir))
|
||||
gitdir = xstrdup(real_path(gitdir));
|
||||
if (chdir(cwd))
|
||||
if (chdir(cwd->buf))
|
||||
die_errno("Could not come back to cwd");
|
||||
return setup_explicit_git_dir(gitdir, cwd, len, nongit_ok);
|
||||
return setup_explicit_git_dir(gitdir, cwd, nongit_ok);
|
||||
}
|
||||
|
||||
/* #16.2, #17.2, #20.2, #21.2, #24, #25, #28, #29 (see t1510) */
|
||||
if (is_bare_repository_cfg > 0) {
|
||||
set_git_dir(offset == len ? gitdir : real_path(gitdir));
|
||||
if (chdir(cwd))
|
||||
set_git_dir(offset == cwd->len ? gitdir : real_path(gitdir));
|
||||
if (chdir(cwd->buf))
|
||||
die_errno("Could not come back to cwd");
|
||||
return NULL;
|
||||
}
|
||||
|
@ -512,18 +511,18 @@ static const char *setup_discovered_git_dir(const char *gitdir,
|
|||
set_git_dir(gitdir);
|
||||
inside_git_dir = 0;
|
||||
inside_work_tree = 1;
|
||||
if (offset == len)
|
||||
if (offset == cwd->len)
|
||||
return NULL;
|
||||
|
||||
/* Make "offset" point to past the '/', and add a '/' at the end */
|
||||
offset++;
|
||||
cwd[len++] = '/';
|
||||
cwd[len] = 0;
|
||||
return cwd + offset;
|
||||
strbuf_addch(cwd, '/');
|
||||
return cwd->buf + offset;
|
||||
}
|
||||
|
||||
/* #16.1, #17.1, #20.1, #21.1, #22.1 (see t1510) */
|
||||
static const char *setup_bare_git_dir(char *cwd, int offset, int len, int *nongit_ok)
|
||||
static const char *setup_bare_git_dir(struct strbuf *cwd, int offset,
|
||||
int *nongit_ok)
|
||||
{
|
||||
int root_len;
|
||||
|
||||
|
@ -536,20 +535,20 @@ static const char *setup_bare_git_dir(char *cwd, int offset, int len, int *nongi
|
|||
if (getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) {
|
||||
const char *gitdir;
|
||||
|
||||
gitdir = offset == len ? "." : xmemdupz(cwd, offset);
|
||||
if (chdir(cwd))
|
||||
gitdir = offset == cwd->len ? "." : xmemdupz(cwd->buf, offset);
|
||||
if (chdir(cwd->buf))
|
||||
die_errno("Could not come back to cwd");
|
||||
return setup_explicit_git_dir(gitdir, cwd, len, nongit_ok);
|
||||
return setup_explicit_git_dir(gitdir, cwd, nongit_ok);
|
||||
}
|
||||
|
||||
inside_git_dir = 1;
|
||||
inside_work_tree = 0;
|
||||
if (offset != len) {
|
||||
if (chdir(cwd))
|
||||
if (offset != cwd->len) {
|
||||
if (chdir(cwd->buf))
|
||||
die_errno("Cannot come back to cwd");
|
||||
root_len = offset_1st_component(cwd);
|
||||
cwd[offset > root_len ? offset : root_len] = '\0';
|
||||
set_git_dir(cwd);
|
||||
root_len = offset_1st_component(cwd->buf);
|
||||
strbuf_setlen(cwd, offset > root_len ? offset : root_len);
|
||||
set_git_dir(cwd->buf);
|
||||
}
|
||||
else
|
||||
set_git_dir(".");
|
||||
|
@ -617,10 +616,10 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
|
|||
{
|
||||
const char *env_ceiling_dirs = getenv(CEILING_DIRECTORIES_ENVIRONMENT);
|
||||
struct string_list ceiling_dirs = STRING_LIST_INIT_DUP;
|
||||
static char cwd[PATH_MAX + 1];
|
||||
static struct strbuf cwd = STRBUF_INIT;
|
||||
const char *gitdirenv, *ret;
|
||||
char *gitfile;
|
||||
int len, offset, offset_parent, ceil_offset = -1;
|
||||
int offset, offset_parent, ceil_offset = -1;
|
||||
dev_t current_device = 0;
|
||||
int one_filesystem = 1;
|
||||
|
||||
|
@ -641,9 +640,9 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
|
|||
if (nongit_ok)
|
||||
*nongit_ok = 0;
|
||||
|
||||
if (!getcwd(cwd, sizeof(cwd) - 1))
|
||||
if (strbuf_getcwd(&cwd))
|
||||
die_errno("Unable to read current working directory");
|
||||
offset = len = strlen(cwd);
|
||||
offset = cwd.len;
|
||||
|
||||
/*
|
||||
* If GIT_DIR is set explicitly, we're not going
|
||||
|
@ -652,7 +651,7 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
|
|||
*/
|
||||
gitdirenv = getenv(GIT_DIR_ENVIRONMENT);
|
||||
if (gitdirenv)
|
||||
return setup_explicit_git_dir(gitdirenv, cwd, len, nongit_ok);
|
||||
return setup_explicit_git_dir(gitdirenv, &cwd, nongit_ok);
|
||||
|
||||
if (env_ceiling_dirs) {
|
||||
int empty_entry_found = 0;
|
||||
|
@ -660,11 +659,11 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
|
|||
string_list_split(&ceiling_dirs, env_ceiling_dirs, PATH_SEP, -1);
|
||||
filter_string_list(&ceiling_dirs, 0,
|
||||
canonicalize_ceiling_entry, &empty_entry_found);
|
||||
ceil_offset = longest_ancestor_length(cwd, &ceiling_dirs);
|
||||
ceil_offset = longest_ancestor_length(cwd.buf, &ceiling_dirs);
|
||||
string_list_clear(&ceiling_dirs, 0);
|
||||
}
|
||||
|
||||
if (ceil_offset < 0 && has_dos_drive_prefix(cwd))
|
||||
if (ceil_offset < 0 && has_dos_drive_prefix(cwd.buf))
|
||||
ceil_offset = 1;
|
||||
|
||||
/*
|
||||
|
@ -692,7 +691,7 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
|
|||
|
||||
if (gitdirenv) {
|
||||
ret = setup_discovered_git_dir(gitdirenv,
|
||||
cwd, offset, len,
|
||||
&cwd, offset,
|
||||
nongit_ok);
|
||||
free(gitfile);
|
||||
return ret;
|
||||
|
@ -700,29 +699,31 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
|
|||
free(gitfile);
|
||||
|
||||
if (is_git_directory("."))
|
||||
return setup_bare_git_dir(cwd, offset, len, nongit_ok);
|
||||
return setup_bare_git_dir(&cwd, offset, nongit_ok);
|
||||
|
||||
offset_parent = offset;
|
||||
while (--offset_parent > ceil_offset && cwd[offset_parent] != '/');
|
||||
while (--offset_parent > ceil_offset && cwd.buf[offset_parent] != '/');
|
||||
if (offset_parent <= ceil_offset)
|
||||
return setup_nongit(cwd, nongit_ok);
|
||||
return setup_nongit(cwd.buf, nongit_ok);
|
||||
if (one_filesystem) {
|
||||
dev_t parent_device = get_device_or_die("..", cwd, offset);
|
||||
dev_t parent_device = get_device_or_die("..", cwd.buf,
|
||||
offset);
|
||||
if (parent_device != current_device) {
|
||||
if (nongit_ok) {
|
||||
if (chdir(cwd))
|
||||
if (chdir(cwd.buf))
|
||||
die_errno("Cannot come back to cwd");
|
||||
*nongit_ok = 1;
|
||||
return NULL;
|
||||
}
|
||||
cwd[offset] = '\0';
|
||||
strbuf_setlen(&cwd, offset);
|
||||
die("Not a git repository (or any parent up to mount point %s)\n"
|
||||
"Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).", cwd);
|
||||
"Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).",
|
||||
cwd.buf);
|
||||
}
|
||||
}
|
||||
if (chdir("..")) {
|
||||
cwd[offset] = '\0';
|
||||
die_errno("Cannot change to '%s/..'", cwd);
|
||||
strbuf_setlen(&cwd, offset);
|
||||
die_errno("Cannot change to '%s/..'", cwd.buf);
|
||||
}
|
||||
offset = offset_parent;
|
||||
}
|
||||
|
|
|
@ -350,7 +350,7 @@ static void link_alt_odb_entries(const char *alt, int len, int sep,
|
|||
return;
|
||||
}
|
||||
|
||||
strbuf_addstr(&objdirbuf, absolute_path(get_object_directory()));
|
||||
strbuf_add_absolute_path(&objdirbuf, get_object_directory());
|
||||
normalize_path_copy(objdirbuf.buf, objdirbuf.buf);
|
||||
|
||||
alt_copy = xmemdupz(alt, len);
|
||||
|
|
46
strbuf.c
46
strbuf.c
|
@ -406,6 +406,27 @@ int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint)
|
|||
return -1;
|
||||
}
|
||||
|
||||
int strbuf_getcwd(struct strbuf *sb)
|
||||
{
|
||||
size_t oldalloc = sb->alloc;
|
||||
size_t guessed_len = 128;
|
||||
|
||||
for (;; guessed_len *= 2) {
|
||||
strbuf_grow(sb, guessed_len);
|
||||
if (getcwd(sb->buf, sb->alloc)) {
|
||||
strbuf_setlen(sb, strlen(sb->buf));
|
||||
return 0;
|
||||
}
|
||||
if (errno != ERANGE)
|
||||
break;
|
||||
}
|
||||
if (oldalloc == 0)
|
||||
strbuf_release(sb);
|
||||
else
|
||||
strbuf_reset(sb);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int strbuf_getwholeline(struct strbuf *sb, FILE *fp, int term)
|
||||
{
|
||||
int ch;
|
||||
|
@ -555,6 +576,31 @@ void strbuf_humanise_bytes(struct strbuf *buf, off_t bytes)
|
|||
}
|
||||
}
|
||||
|
||||
void strbuf_add_absolute_path(struct strbuf *sb, const char *path)
|
||||
{
|
||||
if (!*path)
|
||||
die("The empty string is not a valid path");
|
||||
if (!is_absolute_path(path)) {
|
||||
struct stat cwd_stat, pwd_stat;
|
||||
size_t orig_len = sb->len;
|
||||
char *cwd = xgetcwd();
|
||||
char *pwd = getenv("PWD");
|
||||
if (pwd && strcmp(pwd, cwd) &&
|
||||
!stat(cwd, &cwd_stat) &&
|
||||
(cwd_stat.st_dev || cwd_stat.st_ino) &&
|
||||
!stat(pwd, &pwd_stat) &&
|
||||
pwd_stat.st_dev == cwd_stat.st_dev &&
|
||||
pwd_stat.st_ino == cwd_stat.st_ino)
|
||||
strbuf_addstr(sb, pwd);
|
||||
else
|
||||
strbuf_addstr(sb, cwd);
|
||||
if (sb->len > orig_len && !is_dir_sep(sb->buf[sb->len - 1]))
|
||||
strbuf_addch(sb, '/');
|
||||
free(cwd);
|
||||
}
|
||||
strbuf_addstr(sb, path);
|
||||
}
|
||||
|
||||
int printf_ln(const char *fmt, ...)
|
||||
{
|
||||
int ret;
|
||||
|
|
3
strbuf.h
3
strbuf.h
|
@ -174,6 +174,7 @@ extern size_t strbuf_fread(struct strbuf *, size_t, FILE *);
|
|||
extern ssize_t strbuf_read(struct strbuf *, int fd, size_t hint);
|
||||
extern int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint);
|
||||
extern int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint);
|
||||
extern int strbuf_getcwd(struct strbuf *sb);
|
||||
|
||||
extern int strbuf_getwholeline(struct strbuf *, FILE *, int);
|
||||
extern int strbuf_getline(struct strbuf *, FILE *, int);
|
||||
|
@ -189,6 +190,8 @@ extern void strbuf_addstr_urlencode(struct strbuf *, const char *,
|
|||
int reserved);
|
||||
extern void strbuf_humanise_bytes(struct strbuf *buf, off_t bytes);
|
||||
|
||||
extern void strbuf_add_absolute_path(struct strbuf *sb, const char *path);
|
||||
|
||||
__attribute__((format (printf,1,2)))
|
||||
extern int printf_ln(const char *fmt, ...);
|
||||
__attribute__((format (printf,2,3)))
|
||||
|
|
7
trace.c
7
trace.c
|
@ -298,13 +298,12 @@ void trace_repo_setup(const char *prefix)
|
|||
{
|
||||
static struct trace_key key = TRACE_KEY_INIT(SETUP);
|
||||
const char *git_work_tree;
|
||||
char cwd[PATH_MAX];
|
||||
char *cwd;
|
||||
|
||||
if (!trace_want(&key))
|
||||
return;
|
||||
|
||||
if (!getcwd(cwd, PATH_MAX))
|
||||
die("Unable to get current working directory");
|
||||
cwd = xgetcwd();
|
||||
|
||||
if (!(git_work_tree = get_git_work_tree()))
|
||||
git_work_tree = "(null)";
|
||||
|
@ -316,6 +315,8 @@ void trace_repo_setup(const char *prefix)
|
|||
trace_printf_key(&key, "setup: worktree: %s\n", quote_crnl(git_work_tree));
|
||||
trace_printf_key(&key, "setup: cwd: %s\n", quote_crnl(cwd));
|
||||
trace_printf_key(&key, "setup: prefix: %s\n", quote_crnl(prefix));
|
||||
|
||||
free(cwd);
|
||||
}
|
||||
|
||||
int trace_want(struct trace_key *key)
|
||||
|
|
|
@ -18,12 +18,12 @@ static int chdir_len(const char *orig, int len)
|
|||
}
|
||||
|
||||
struct unix_sockaddr_context {
|
||||
char orig_dir[PATH_MAX];
|
||||
char *orig_dir;
|
||||
};
|
||||
|
||||
static void unix_sockaddr_cleanup(struct unix_sockaddr_context *ctx)
|
||||
{
|
||||
if (!ctx->orig_dir[0])
|
||||
if (!ctx->orig_dir)
|
||||
return;
|
||||
/*
|
||||
* If we fail, we can't just return an error, since we have
|
||||
|
@ -32,6 +32,7 @@ static void unix_sockaddr_cleanup(struct unix_sockaddr_context *ctx)
|
|||
*/
|
||||
if (chdir(ctx->orig_dir) < 0)
|
||||
die("unable to restore original working directory");
|
||||
free(ctx->orig_dir);
|
||||
}
|
||||
|
||||
static int unix_sockaddr_init(struct sockaddr_un *sa, const char *path,
|
||||
|
@ -39,10 +40,11 @@ static int unix_sockaddr_init(struct sockaddr_un *sa, const char *path,
|
|||
{
|
||||
int size = strlen(path) + 1;
|
||||
|
||||
ctx->orig_dir[0] = '\0';
|
||||
ctx->orig_dir = NULL;
|
||||
if (size > sizeof(sa->sun_path)) {
|
||||
const char *slash = find_last_dir_sep(path);
|
||||
const char *dir;
|
||||
struct strbuf cwd = STRBUF_INIT;
|
||||
|
||||
if (!slash) {
|
||||
errno = ENAMETOOLONG;
|
||||
|
@ -56,11 +58,9 @@ static int unix_sockaddr_init(struct sockaddr_un *sa, const char *path,
|
|||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!getcwd(ctx->orig_dir, sizeof(ctx->orig_dir))) {
|
||||
errno = ENAMETOOLONG;
|
||||
if (strbuf_getcwd(&cwd))
|
||||
return -1;
|
||||
}
|
||||
ctx->orig_dir = strbuf_detach(&cwd, NULL);
|
||||
if (chdir_len(dir, slash - dir) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -493,3 +493,11 @@ struct passwd *xgetpwuid_self(void)
|
|||
errno ? strerror(errno) : _("no such user"));
|
||||
return pw;
|
||||
}
|
||||
|
||||
char *xgetcwd(void)
|
||||
{
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
if (strbuf_getcwd(&sb))
|
||||
die_errno(_("unable to get current working directory"));
|
||||
return strbuf_detach(&sb, NULL);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче