2023-03-21 14:25:58 +08:00
|
|
|
#include "git-compat-util.h"
|
|
|
|
#include "abspath.h"
|
|
|
|
#include "strbuf.h"
|
2008-06-28 04:46:42 +08:00
|
|
|
|
2008-09-09 16:27:07 +08:00
|
|
|
/*
|
|
|
|
* Do not use this for inspecting *tracked* content. When path is a
|
|
|
|
* symlink to a directory, we do not want to say it is a directory when
|
|
|
|
* dealing with tracked content in the working tree.
|
|
|
|
*/
|
|
|
|
int is_directory(const char *path)
|
|
|
|
{
|
|
|
|
struct stat st;
|
|
|
|
return (!stat(path, &st) && S_ISDIR(st.st_mode));
|
|
|
|
}
|
|
|
|
|
2016-12-13 02:16:52 +08:00
|
|
|
/* removes the last path component from 'path' except if 'path' is root */
|
|
|
|
static void strip_last_component(struct strbuf *path)
|
|
|
|
{
|
|
|
|
size_t offset = offset_1st_component(path->buf);
|
|
|
|
size_t len = path->len;
|
|
|
|
|
|
|
|
/* Find start of the last component */
|
|
|
|
while (offset < len && !is_dir_sep(path->buf[len - 1]))
|
|
|
|
len--;
|
|
|
|
/* Skip sequences of multiple path-separators */
|
|
|
|
while (offset < len && is_dir_sep(path->buf[len - 1]))
|
|
|
|
len--;
|
|
|
|
|
|
|
|
strbuf_setlen(path, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* get (and remove) the next component in 'remaining' and place it in 'next' */
|
|
|
|
static void get_next_component(struct strbuf *next, struct strbuf *remaining)
|
|
|
|
{
|
|
|
|
char *start = NULL;
|
|
|
|
char *end = NULL;
|
|
|
|
|
|
|
|
strbuf_reset(next);
|
|
|
|
|
|
|
|
/* look for the next component */
|
|
|
|
/* Skip sequences of multiple path-separators */
|
|
|
|
for (start = remaining->buf; is_dir_sep(*start); start++)
|
|
|
|
; /* nothing */
|
|
|
|
/* Find end of the path component */
|
|
|
|
for (end = start; *end && !is_dir_sep(*end); end++)
|
|
|
|
; /* nothing */
|
|
|
|
|
|
|
|
strbuf_add(next, start, end - start);
|
|
|
|
/* remove the component from 'remaining' */
|
|
|
|
strbuf_remove(remaining, 0, end - remaining->buf);
|
|
|
|
}
|
|
|
|
|
2016-12-22 05:51:35 +08:00
|
|
|
/* copies root part from remaining to resolved, canonicalizing it on the way */
|
|
|
|
static void get_root_part(struct strbuf *resolved, struct strbuf *remaining)
|
|
|
|
{
|
|
|
|
int offset = offset_1st_component(remaining->buf);
|
|
|
|
|
|
|
|
strbuf_reset(resolved);
|
|
|
|
strbuf_add(resolved, remaining->buf, offset);
|
|
|
|
#ifdef GIT_WINDOWS_NATIVE
|
|
|
|
convert_slashes(resolved->buf);
|
|
|
|
#endif
|
|
|
|
strbuf_remove(remaining, 0, offset);
|
|
|
|
}
|
|
|
|
|
2008-06-28 04:46:42 +08:00
|
|
|
/* We allow "recursive" symbolic links. Only within reason, though. */
|
2017-01-10 02:50:23 +08:00
|
|
|
#ifndef MAXSYMLINKS
|
|
|
|
#define MAXSYMLINKS 32
|
|
|
|
#endif
|
2008-06-28 04:46:42 +08:00
|
|
|
|
2011-03-17 19:26:46 +08:00
|
|
|
/*
|
abspath: add a function to resolve paths with missing components
Currently, we have a function to resolve paths, strbuf_realpath. This
function canonicalizes paths like realpath(3), but permits a trailing
component to be absent from the file system. In other words, this is
the behavior of the GNU realpath(1) without any arguments.
In the future, we'll need this same behavior, except that we want to
allow for any number of missing trailing components, which is the
behavior of GNU realpath(1) with the -m option. This is useful because
we'll want to canonicalize a path that may point to a not yet present
path under the .git directory. For example, a user may want to know
where an arbitrary ref would be stored if it existed in the file system.
Let's refactor strbuf_realpath to move most of the code to an internal
function and then pass it two flags to control its behavior. We'll add
a strbuf_realpath_forgiving function that has our new behavior, and
leave strbuf_realpath with the older, stricter behavior.
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-12-13 08:25:28 +08:00
|
|
|
* If set, any number of trailing components may be missing; otherwise, only one
|
|
|
|
* may be.
|
2011-03-17 19:26:46 +08:00
|
|
|
*/
|
abspath: add a function to resolve paths with missing components
Currently, we have a function to resolve paths, strbuf_realpath. This
function canonicalizes paths like realpath(3), but permits a trailing
component to be absent from the file system. In other words, this is
the behavior of the GNU realpath(1) without any arguments.
In the future, we'll need this same behavior, except that we want to
allow for any number of missing trailing components, which is the
behavior of GNU realpath(1) with the -m option. This is useful because
we'll want to canonicalize a path that may point to a not yet present
path under the .git directory. For example, a user may want to know
where an arbitrary ref would be stored if it existed in the file system.
Let's refactor strbuf_realpath to move most of the code to an internal
function and then pass it two flags to control its behavior. We'll add
a strbuf_realpath_forgiving function that has our new behavior, and
leave strbuf_realpath with the older, stricter behavior.
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-12-13 08:25:28 +08:00
|
|
|
#define REALPATH_MANY_MISSING (1 << 0)
|
|
|
|
/* Should we die if there's an error? */
|
|
|
|
#define REALPATH_DIE_ON_ERROR (1 << 1)
|
|
|
|
|
|
|
|
static char *strbuf_realpath_1(struct strbuf *resolved, const char *path,
|
|
|
|
int flags)
|
2008-06-28 04:46:42 +08:00
|
|
|
{
|
2016-12-13 02:16:52 +08:00
|
|
|
struct strbuf remaining = STRBUF_INIT;
|
|
|
|
struct strbuf next = STRBUF_INIT;
|
|
|
|
struct strbuf symlink = STRBUF_INIT;
|
2012-10-29 00:16:20 +08:00
|
|
|
char *retval = NULL;
|
2016-12-13 02:16:52 +08:00
|
|
|
int num_symlinks = 0;
|
2008-06-28 04:46:42 +08:00
|
|
|
struct stat st;
|
|
|
|
|
2012-10-29 00:16:20 +08:00
|
|
|
if (!*path) {
|
abspath: add a function to resolve paths with missing components
Currently, we have a function to resolve paths, strbuf_realpath. This
function canonicalizes paths like realpath(3), but permits a trailing
component to be absent from the file system. In other words, this is
the behavior of the GNU realpath(1) without any arguments.
In the future, we'll need this same behavior, except that we want to
allow for any number of missing trailing components, which is the
behavior of GNU realpath(1) with the -m option. This is useful because
we'll want to canonicalize a path that may point to a not yet present
path under the .git directory. For example, a user may want to know
where an arbitrary ref would be stored if it existed in the file system.
Let's refactor strbuf_realpath to move most of the code to an internal
function and then pass it two flags to control its behavior. We'll add
a strbuf_realpath_forgiving function that has our new behavior, and
leave strbuf_realpath with the older, stricter behavior.
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-12-13 08:25:28 +08:00
|
|
|
if (flags & REALPATH_DIE_ON_ERROR)
|
2012-10-29 00:16:20 +08:00
|
|
|
die("The empty string is not a valid path");
|
|
|
|
else
|
|
|
|
goto error_out;
|
|
|
|
}
|
2012-09-07 06:41:01 +08:00
|
|
|
|
2016-12-22 05:51:35 +08:00
|
|
|
strbuf_addstr(&remaining, path);
|
|
|
|
get_root_part(resolved, &remaining);
|
2008-06-28 04:46:42 +08:00
|
|
|
|
2016-12-22 05:51:35 +08:00
|
|
|
if (!resolved->len) {
|
2016-12-13 02:16:52 +08:00
|
|
|
/* relative path; can use CWD as the initial resolved path */
|
2016-12-13 02:16:53 +08:00
|
|
|
if (strbuf_getcwd(resolved)) {
|
abspath: add a function to resolve paths with missing components
Currently, we have a function to resolve paths, strbuf_realpath. This
function canonicalizes paths like realpath(3), but permits a trailing
component to be absent from the file system. In other words, this is
the behavior of the GNU realpath(1) without any arguments.
In the future, we'll need this same behavior, except that we want to
allow for any number of missing trailing components, which is the
behavior of GNU realpath(1) with the -m option. This is useful because
we'll want to canonicalize a path that may point to a not yet present
path under the .git directory. For example, a user may want to know
where an arbitrary ref would be stored if it existed in the file system.
Let's refactor strbuf_realpath to move most of the code to an internal
function and then pass it two flags to control its behavior. We'll add
a strbuf_realpath_forgiving function that has our new behavior, and
leave strbuf_realpath with the older, stricter behavior.
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-12-13 08:25:28 +08:00
|
|
|
if (flags & REALPATH_DIE_ON_ERROR)
|
2016-12-13 02:16:52 +08:00
|
|
|
die_errno("unable to get current working directory");
|
|
|
|
else
|
|
|
|
goto error_out;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Iterate over the remaining path components */
|
|
|
|
while (remaining.len > 0) {
|
|
|
|
get_next_component(&next, &remaining);
|
|
|
|
|
|
|
|
if (next.len == 0) {
|
|
|
|
continue; /* empty component */
|
|
|
|
} else if (next.len == 1 && !strcmp(next.buf, ".")) {
|
|
|
|
continue; /* '.' component */
|
|
|
|
} else if (next.len == 2 && !strcmp(next.buf, "..")) {
|
|
|
|
/* '..' component; strip the last path component */
|
2016-12-13 02:16:53 +08:00
|
|
|
strip_last_component(resolved);
|
2016-12-13 02:16:52 +08:00
|
|
|
continue;
|
2008-06-28 04:46:42 +08:00
|
|
|
}
|
|
|
|
|
2016-12-13 02:16:52 +08:00
|
|
|
/* append the next component and resolve resultant path */
|
2016-12-13 02:16:53 +08:00
|
|
|
if (!is_dir_sep(resolved->buf[resolved->len - 1]))
|
|
|
|
strbuf_addch(resolved, '/');
|
|
|
|
strbuf_addbuf(resolved, &next);
|
2016-12-13 02:16:52 +08:00
|
|
|
|
2016-12-13 02:16:53 +08:00
|
|
|
if (lstat(resolved->buf, &st)) {
|
2016-12-13 02:16:52 +08:00
|
|
|
/* error out unless this was the last component */
|
abspath: add a function to resolve paths with missing components
Currently, we have a function to resolve paths, strbuf_realpath. This
function canonicalizes paths like realpath(3), but permits a trailing
component to be absent from the file system. In other words, this is
the behavior of the GNU realpath(1) without any arguments.
In the future, we'll need this same behavior, except that we want to
allow for any number of missing trailing components, which is the
behavior of GNU realpath(1) with the -m option. This is useful because
we'll want to canonicalize a path that may point to a not yet present
path under the .git directory. For example, a user may want to know
where an arbitrary ref would be stored if it existed in the file system.
Let's refactor strbuf_realpath to move most of the code to an internal
function and then pass it two flags to control its behavior. We'll add
a strbuf_realpath_forgiving function that has our new behavior, and
leave strbuf_realpath with the older, stricter behavior.
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-12-13 08:25:28 +08:00
|
|
|
if (errno != ENOENT ||
|
|
|
|
(!(flags & REALPATH_MANY_MISSING) && remaining.len)) {
|
|
|
|
if (flags & REALPATH_DIE_ON_ERROR)
|
2016-12-13 02:16:52 +08:00
|
|
|
die_errno("Invalid path '%s'",
|
2016-12-13 02:16:53 +08:00
|
|
|
resolved->buf);
|
2012-10-29 00:16:20 +08:00
|
|
|
else
|
|
|
|
goto error_out;
|
|
|
|
}
|
2016-12-13 02:16:52 +08:00
|
|
|
} else if (S_ISLNK(st.st_mode)) {
|
|
|
|
ssize_t len;
|
|
|
|
strbuf_reset(&symlink);
|
2008-06-28 04:46:42 +08:00
|
|
|
|
2016-12-13 02:16:52 +08:00
|
|
|
if (num_symlinks++ > MAXSYMLINKS) {
|
2017-01-10 02:50:24 +08:00
|
|
|
errno = ELOOP;
|
|
|
|
|
abspath: add a function to resolve paths with missing components
Currently, we have a function to resolve paths, strbuf_realpath. This
function canonicalizes paths like realpath(3), but permits a trailing
component to be absent from the file system. In other words, this is
the behavior of the GNU realpath(1) without any arguments.
In the future, we'll need this same behavior, except that we want to
allow for any number of missing trailing components, which is the
behavior of GNU realpath(1) with the -m option. This is useful because
we'll want to canonicalize a path that may point to a not yet present
path under the .git directory. For example, a user may want to know
where an arbitrary ref would be stored if it existed in the file system.
Let's refactor strbuf_realpath to move most of the code to an internal
function and then pass it two flags to control its behavior. We'll add
a strbuf_realpath_forgiving function that has our new behavior, and
leave strbuf_realpath with the older, stricter behavior.
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-12-13 08:25:28 +08:00
|
|
|
if (flags & REALPATH_DIE_ON_ERROR)
|
2016-12-13 02:16:52 +08:00
|
|
|
die("More than %d nested symlinks "
|
|
|
|
"on path '%s'", MAXSYMLINKS, path);
|
2012-10-29 00:16:20 +08:00
|
|
|
else
|
|
|
|
goto error_out;
|
|
|
|
}
|
2008-06-28 04:46:42 +08:00
|
|
|
|
2016-12-13 02:16:53 +08:00
|
|
|
len = strbuf_readlink(&symlink, resolved->buf,
|
2016-12-13 02:16:52 +08:00
|
|
|
st.st_size);
|
2012-10-29 00:16:20 +08:00
|
|
|
if (len < 0) {
|
abspath: add a function to resolve paths with missing components
Currently, we have a function to resolve paths, strbuf_realpath. This
function canonicalizes paths like realpath(3), but permits a trailing
component to be absent from the file system. In other words, this is
the behavior of the GNU realpath(1) without any arguments.
In the future, we'll need this same behavior, except that we want to
allow for any number of missing trailing components, which is the
behavior of GNU realpath(1) with the -m option. This is useful because
we'll want to canonicalize a path that may point to a not yet present
path under the .git directory. For example, a user may want to know
where an arbitrary ref would be stored if it existed in the file system.
Let's refactor strbuf_realpath to move most of the code to an internal
function and then pass it two flags to control its behavior. We'll add
a strbuf_realpath_forgiving function that has our new behavior, and
leave strbuf_realpath with the older, stricter behavior.
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-12-13 08:25:28 +08:00
|
|
|
if (flags & REALPATH_DIE_ON_ERROR)
|
2014-07-29 02:28:30 +08:00
|
|
|
die_errno("Invalid symlink '%s'",
|
2016-12-13 02:16:53 +08:00
|
|
|
resolved->buf);
|
2012-10-29 00:16:20 +08:00
|
|
|
else
|
|
|
|
goto error_out;
|
|
|
|
}
|
2016-12-13 02:16:52 +08:00
|
|
|
|
|
|
|
if (is_absolute_path(symlink.buf)) {
|
|
|
|
/* absolute symlink; set resolved to root */
|
2016-12-22 05:51:35 +08:00
|
|
|
get_root_part(resolved, &symlink);
|
2016-12-13 02:16:52 +08:00
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* relative symlink
|
|
|
|
* strip off the last component since it will
|
|
|
|
* be replaced with the contents of the symlink
|
|
|
|
*/
|
2016-12-13 02:16:53 +08:00
|
|
|
strip_last_component(resolved);
|
2016-12-13 02:16:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* if there are still remaining components to resolve
|
|
|
|
* then append them to symlink
|
|
|
|
*/
|
|
|
|
if (remaining.len) {
|
|
|
|
strbuf_addch(&symlink, '/');
|
|
|
|
strbuf_addbuf(&symlink, &remaining);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* use the symlink as the remaining components that
|
2017-06-25 18:20:41 +08:00
|
|
|
* need to be resolved
|
2016-12-13 02:16:52 +08:00
|
|
|
*/
|
|
|
|
strbuf_swap(&symlink, &remaining);
|
|
|
|
}
|
2008-06-28 04:46:42 +08:00
|
|
|
}
|
|
|
|
|
2016-12-13 02:16:53 +08:00
|
|
|
retval = resolved->buf;
|
2016-12-13 02:16:52 +08:00
|
|
|
|
2012-10-29 00:16:20 +08:00
|
|
|
error_out:
|
2016-12-13 02:16:52 +08:00
|
|
|
strbuf_release(&remaining);
|
|
|
|
strbuf_release(&next);
|
|
|
|
strbuf_release(&symlink);
|
2008-06-28 04:46:42 +08:00
|
|
|
|
2016-12-13 02:16:53 +08:00
|
|
|
if (!retval)
|
|
|
|
strbuf_reset(resolved);
|
|
|
|
|
2012-10-29 00:16:20 +08:00
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
abspath: add a function to resolve paths with missing components
Currently, we have a function to resolve paths, strbuf_realpath. This
function canonicalizes paths like realpath(3), but permits a trailing
component to be absent from the file system. In other words, this is
the behavior of the GNU realpath(1) without any arguments.
In the future, we'll need this same behavior, except that we want to
allow for any number of missing trailing components, which is the
behavior of GNU realpath(1) with the -m option. This is useful because
we'll want to canonicalize a path that may point to a not yet present
path under the .git directory. For example, a user may want to know
where an arbitrary ref would be stored if it existed in the file system.
Let's refactor strbuf_realpath to move most of the code to an internal
function and then pass it two flags to control its behavior. We'll add
a strbuf_realpath_forgiving function that has our new behavior, and
leave strbuf_realpath with the older, stricter behavior.
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-12-13 08:25:28 +08:00
|
|
|
/*
|
|
|
|
* Return the real path (i.e., absolute path, with symlinks resolved
|
|
|
|
* and extra slashes removed) equivalent to the specified path. (If
|
|
|
|
* you want an absolute path but don't mind links, use
|
|
|
|
* absolute_path().) Places the resolved realpath in the provided strbuf.
|
|
|
|
*
|
|
|
|
* The directory part of path (i.e., everything up to the last
|
|
|
|
* dir_sep) must denote a valid, existing directory, but the last
|
|
|
|
* component need not exist. If die_on_error is set, then die with an
|
|
|
|
* informative error message if there is a problem. Otherwise, return
|
|
|
|
* NULL on errors (without generating any output).
|
|
|
|
*/
|
|
|
|
char *strbuf_realpath(struct strbuf *resolved, const char *path,
|
|
|
|
int die_on_error)
|
|
|
|
{
|
|
|
|
return strbuf_realpath_1(resolved, path,
|
|
|
|
die_on_error ? REALPATH_DIE_ON_ERROR : 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Just like strbuf_realpath, but allows an arbitrary number of path
|
|
|
|
* components to be missing.
|
|
|
|
*/
|
|
|
|
char *strbuf_realpath_forgiving(struct strbuf *resolved, const char *path,
|
|
|
|
int die_on_error)
|
|
|
|
{
|
|
|
|
return strbuf_realpath_1(resolved, path,
|
|
|
|
((die_on_error ? REALPATH_DIE_ON_ERROR : 0) |
|
|
|
|
REALPATH_MANY_MISSING));
|
|
|
|
}
|
|
|
|
|
2017-03-08 23:43:40 +08:00
|
|
|
char *real_pathdup(const char *path, int die_on_error)
|
2016-12-13 02:16:54 +08:00
|
|
|
{
|
|
|
|
struct strbuf realpath = STRBUF_INIT;
|
|
|
|
char *retval = NULL;
|
|
|
|
|
2017-03-08 23:43:40 +08:00
|
|
|
if (strbuf_realpath(&realpath, path, die_on_error))
|
2016-12-13 02:16:54 +08:00
|
|
|
retval = strbuf_detach(&realpath, NULL);
|
|
|
|
|
|
|
|
strbuf_release(&realpath);
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2011-03-17 19:26:46 +08:00
|
|
|
/*
|
|
|
|
* Use this to get an absolute path from a relative one. If you want
|
2020-03-10 21:11:22 +08:00
|
|
|
* to resolve links, you should use strbuf_realpath.
|
2011-03-17 19:26:46 +08:00
|
|
|
*/
|
|
|
|
const char *absolute_path(const char *path)
|
2008-07-22 03:19:55 +08:00
|
|
|
{
|
2014-07-29 02:33:55 +08:00
|
|
|
static struct strbuf sb = STRBUF_INIT;
|
|
|
|
strbuf_reset(&sb);
|
|
|
|
strbuf_add_absolute_path(&sb, path);
|
|
|
|
return sb.buf;
|
2008-07-22 03:19:55 +08:00
|
|
|
}
|
2011-08-11 17:15:38 +08:00
|
|
|
|
2017-01-27 01:47:45 +08:00
|
|
|
char *absolute_pathdup(const char *path)
|
|
|
|
{
|
|
|
|
struct strbuf sb = STRBUF_INIT;
|
|
|
|
strbuf_add_absolute_path(&sb, path);
|
|
|
|
return strbuf_detach(&sb, NULL);
|
|
|
|
}
|
|
|
|
|
2017-03-21 09:28:49 +08:00
|
|
|
char *prefix_filename(const char *pfx, const char *arg)
|
2011-08-11 17:15:38 +08:00
|
|
|
{
|
2017-03-21 09:28:49 +08:00
|
|
|
struct strbuf path = STRBUF_INIT;
|
2017-03-21 09:22:28 +08:00
|
|
|
size_t pfx_len = pfx ? strlen(pfx) : 0;
|
|
|
|
|
2017-03-21 09:30:41 +08:00
|
|
|
if (!pfx_len)
|
|
|
|
; /* nothing to prefix */
|
|
|
|
else if (is_absolute_path(arg))
|
2011-08-11 17:15:38 +08:00
|
|
|
pfx_len = 0;
|
2017-03-21 09:30:41 +08:00
|
|
|
else
|
2013-12-14 19:31:16 +08:00
|
|
|
strbuf_add(&path, pfx, pfx_len);
|
2017-03-21 09:30:41 +08:00
|
|
|
|
2013-12-14 19:31:16 +08:00
|
|
|
strbuf_addstr(&path, arg);
|
2017-03-21 09:30:41 +08:00
|
|
|
#ifdef GIT_WINDOWS_NATIVE
|
2016-04-03 03:03:14 +08:00
|
|
|
convert_slashes(path.buf + pfx_len);
|
2011-08-11 17:15:38 +08:00
|
|
|
#endif
|
2017-03-21 09:28:49 +08:00
|
|
|
return strbuf_detach(&path, NULL);
|
2011-08-11 17:15:38 +08:00
|
|
|
}
|
bundle: don't blindly apply prefix_filename() to "-"
A user can specify a filename to a command from the command line,
either as the value given to a command line option, or a command
line argument. When it is given as a relative filename, in the
user's mind, it is relative to the directory "git" was started from,
but by the time the filename is used, "git" would almost always have
chdir()'ed up to the root level of the working tree.
The given filename, if it is relative, needs to be prefixed with the
path to the current directory, and it typically is done by calling
prefix_filename() helper function. For commands that can also take
"-" to use the standard input or the standard output, however, this
needs to be done with care.
"git bundle create" uses the next word on the command line as the
output filename, and can take "-" to mean "write to the standard
output". It blindly called prefix_filename(), so running it in a
subdirectory did not quite work as expected.
Introduce a new helper, prefix_filename_except_for_dash(), and use
it to help "git bundle create" codepath.
Reported-by: Michael Henry
Helped-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-03-04 18:27:56 +08:00
|
|
|
|
|
|
|
char *prefix_filename_except_for_dash(const char *pfx, const char *arg)
|
|
|
|
{
|
|
|
|
if (!strcmp(arg, "-"))
|
|
|
|
return xstrdup(arg);
|
|
|
|
return prefix_filename(pfx, arg);
|
|
|
|
}
|
2023-06-07 03:48:39 +08:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
void strbuf_add_real_path(struct strbuf *sb, const char *path)
|
|
|
|
{
|
|
|
|
if (sb->len) {
|
|
|
|
struct strbuf resolved = STRBUF_INIT;
|
|
|
|
strbuf_realpath(&resolved, path, 1);
|
|
|
|
strbuf_addbuf(sb, &resolved);
|
|
|
|
strbuf_release(&resolved);
|
|
|
|
} else
|
|
|
|
strbuf_realpath(sb, path, 1);
|
|
|
|
}
|