Merge branch 'bc/rev-parse-path-format'
"git rev-parse" can be explicitly told to give output as absolute or relative path with the `--path-format=(absolute|relative)` option. * bc/rev-parse-path-format: rev-parse: add option for absolute or relative path formatting abspath: add a function to resolve paths with missing components
This commit is contained in:
commit
9ba366f12b
@ -212,6 +212,18 @@ Options for Files
|
|||||||
Only the names of the variables are listed, not their value,
|
Only the names of the variables are listed, not their value,
|
||||||
even if they are set.
|
even if they are set.
|
||||||
|
|
||||||
|
--path-format=(absolute|relative)::
|
||||||
|
Controls the behavior of certain other options. If specified as absolute, the
|
||||||
|
paths printed by those options will be absolute and canonical. If specified as
|
||||||
|
relative, the paths will be relative to the current working directory if that
|
||||||
|
is possible. The default is option specific.
|
||||||
|
+
|
||||||
|
This option may be specified multiple times and affects only the arguments that
|
||||||
|
follow it on the command line, either to the end of the command line or the next
|
||||||
|
instance of this option.
|
||||||
|
|
||||||
|
The following options are modified by `--path-format`:
|
||||||
|
|
||||||
--git-dir::
|
--git-dir::
|
||||||
Show `$GIT_DIR` if defined. Otherwise show the path to
|
Show `$GIT_DIR` if defined. Otherwise show the path to
|
||||||
the .git directory. The path shown, when relative, is
|
the .git directory. The path shown, when relative, is
|
||||||
@ -221,13 +233,42 @@ If `$GIT_DIR` is not defined and the current directory
|
|||||||
is not detected to lie in a Git repository or work tree
|
is not detected to lie in a Git repository or work tree
|
||||||
print a message to stderr and exit with nonzero status.
|
print a message to stderr and exit with nonzero status.
|
||||||
|
|
||||||
|
--git-common-dir::
|
||||||
|
Show `$GIT_COMMON_DIR` if defined, else `$GIT_DIR`.
|
||||||
|
|
||||||
|
--resolve-git-dir <path>::
|
||||||
|
Check if <path> is a valid repository or a gitfile that
|
||||||
|
points at a valid repository, and print the location of the
|
||||||
|
repository. If <path> is a gitfile then the resolved path
|
||||||
|
to the real repository is printed.
|
||||||
|
|
||||||
|
--git-path <path>::
|
||||||
|
Resolve "$GIT_DIR/<path>" and takes other path relocation
|
||||||
|
variables such as $GIT_OBJECT_DIRECTORY,
|
||||||
|
$GIT_INDEX_FILE... into account. For example, if
|
||||||
|
$GIT_OBJECT_DIRECTORY is set to /foo/bar then "git rev-parse
|
||||||
|
--git-path objects/abc" returns /foo/bar/abc.
|
||||||
|
|
||||||
|
--show-toplevel::
|
||||||
|
Show the (by default, absolute) path of the top-level directory
|
||||||
|
of the working tree. If there is no working tree, report an error.
|
||||||
|
|
||||||
|
--show-superproject-working-tree::
|
||||||
|
Show the absolute path of the root of the superproject's
|
||||||
|
working tree (if exists) that uses the current repository as
|
||||||
|
its submodule. Outputs nothing if the current repository is
|
||||||
|
not used as a submodule by any project.
|
||||||
|
|
||||||
|
--shared-index-path::
|
||||||
|
Show the path to the shared index file in split index mode, or
|
||||||
|
empty if not in split-index mode.
|
||||||
|
|
||||||
|
The following options are unaffected by `--path-format`:
|
||||||
|
|
||||||
--absolute-git-dir::
|
--absolute-git-dir::
|
||||||
Like `--git-dir`, but its output is always the canonicalized
|
Like `--git-dir`, but its output is always the canonicalized
|
||||||
absolute path.
|
absolute path.
|
||||||
|
|
||||||
--git-common-dir::
|
|
||||||
Show `$GIT_COMMON_DIR` if defined, else `$GIT_DIR`.
|
|
||||||
|
|
||||||
--is-inside-git-dir::
|
--is-inside-git-dir::
|
||||||
When the current working directory is below the repository
|
When the current working directory is below the repository
|
||||||
directory print "true", otherwise "false".
|
directory print "true", otherwise "false".
|
||||||
@ -242,19 +283,6 @@ print a message to stderr and exit with nonzero status.
|
|||||||
--is-shallow-repository::
|
--is-shallow-repository::
|
||||||
When the repository is shallow print "true", otherwise "false".
|
When the repository is shallow print "true", otherwise "false".
|
||||||
|
|
||||||
--resolve-git-dir <path>::
|
|
||||||
Check if <path> is a valid repository or a gitfile that
|
|
||||||
points at a valid repository, and print the location of the
|
|
||||||
repository. If <path> is a gitfile then the resolved path
|
|
||||||
to the real repository is printed.
|
|
||||||
|
|
||||||
--git-path <path>::
|
|
||||||
Resolve "$GIT_DIR/<path>" and takes other path relocation
|
|
||||||
variables such as $GIT_OBJECT_DIRECTORY,
|
|
||||||
$GIT_INDEX_FILE... into account. For example, if
|
|
||||||
$GIT_OBJECT_DIRECTORY is set to /foo/bar then "git rev-parse
|
|
||||||
--git-path objects/abc" returns /foo/bar/abc.
|
|
||||||
|
|
||||||
--show-cdup::
|
--show-cdup::
|
||||||
When the command is invoked from a subdirectory, show the
|
When the command is invoked from a subdirectory, show the
|
||||||
path of the top-level directory relative to the current
|
path of the top-level directory relative to the current
|
||||||
@ -265,20 +293,6 @@ print a message to stderr and exit with nonzero status.
|
|||||||
path of the current directory relative to the top-level
|
path of the current directory relative to the top-level
|
||||||
directory.
|
directory.
|
||||||
|
|
||||||
--show-toplevel::
|
|
||||||
Show the absolute path of the top-level directory of the working
|
|
||||||
tree. If there is no working tree, report an error.
|
|
||||||
|
|
||||||
--show-superproject-working-tree::
|
|
||||||
Show the absolute path of the root of the superproject's
|
|
||||||
working tree (if exists) that uses the current repository as
|
|
||||||
its submodule. Outputs nothing if the current repository is
|
|
||||||
not used as a submodule by any project.
|
|
||||||
|
|
||||||
--shared-index-path::
|
|
||||||
Show the path to the shared index file in split index mode, or
|
|
||||||
empty if not in split-index mode.
|
|
||||||
|
|
||||||
--show-object-format[=(storage|input|output)]::
|
--show-object-format[=(storage|input|output)]::
|
||||||
Show the object format (hash algorithm) used for the repository
|
Show the object format (hash algorithm) used for the repository
|
||||||
for storage inside the `.git` directory, input, or output. For
|
for storage inside the `.git` directory, input, or output. For
|
||||||
|
64
abspath.c
64
abspath.c
@ -67,19 +67,15 @@ static void get_root_part(struct strbuf *resolved, struct strbuf *remaining)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return the real path (i.e., absolute path, with symlinks resolved
|
* If set, any number of trailing components may be missing; otherwise, only one
|
||||||
* and extra slashes removed) equivalent to the specified path. (If
|
* may be.
|
||||||
* 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,
|
#define REALPATH_MANY_MISSING (1 << 0)
|
||||||
int die_on_error)
|
/* 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)
|
||||||
{
|
{
|
||||||
struct strbuf remaining = STRBUF_INIT;
|
struct strbuf remaining = STRBUF_INIT;
|
||||||
struct strbuf next = STRBUF_INIT;
|
struct strbuf next = STRBUF_INIT;
|
||||||
@ -89,7 +85,7 @@ char *strbuf_realpath(struct strbuf *resolved, const char *path,
|
|||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
if (!*path) {
|
if (!*path) {
|
||||||
if (die_on_error)
|
if (flags & REALPATH_DIE_ON_ERROR)
|
||||||
die("The empty string is not a valid path");
|
die("The empty string is not a valid path");
|
||||||
else
|
else
|
||||||
goto error_out;
|
goto error_out;
|
||||||
@ -101,7 +97,7 @@ char *strbuf_realpath(struct strbuf *resolved, const char *path,
|
|||||||
if (!resolved->len) {
|
if (!resolved->len) {
|
||||||
/* relative path; can use CWD as the initial resolved path */
|
/* relative path; can use CWD as the initial resolved path */
|
||||||
if (strbuf_getcwd(resolved)) {
|
if (strbuf_getcwd(resolved)) {
|
||||||
if (die_on_error)
|
if (flags & REALPATH_DIE_ON_ERROR)
|
||||||
die_errno("unable to get current working directory");
|
die_errno("unable to get current working directory");
|
||||||
else
|
else
|
||||||
goto error_out;
|
goto error_out;
|
||||||
@ -129,8 +125,9 @@ char *strbuf_realpath(struct strbuf *resolved, const char *path,
|
|||||||
|
|
||||||
if (lstat(resolved->buf, &st)) {
|
if (lstat(resolved->buf, &st)) {
|
||||||
/* error out unless this was the last component */
|
/* error out unless this was the last component */
|
||||||
if (errno != ENOENT || remaining.len) {
|
if (errno != ENOENT ||
|
||||||
if (die_on_error)
|
(!(flags & REALPATH_MANY_MISSING) && remaining.len)) {
|
||||||
|
if (flags & REALPATH_DIE_ON_ERROR)
|
||||||
die_errno("Invalid path '%s'",
|
die_errno("Invalid path '%s'",
|
||||||
resolved->buf);
|
resolved->buf);
|
||||||
else
|
else
|
||||||
@ -143,7 +140,7 @@ char *strbuf_realpath(struct strbuf *resolved, const char *path,
|
|||||||
if (num_symlinks++ > MAXSYMLINKS) {
|
if (num_symlinks++ > MAXSYMLINKS) {
|
||||||
errno = ELOOP;
|
errno = ELOOP;
|
||||||
|
|
||||||
if (die_on_error)
|
if (flags & REALPATH_DIE_ON_ERROR)
|
||||||
die("More than %d nested symlinks "
|
die("More than %d nested symlinks "
|
||||||
"on path '%s'", MAXSYMLINKS, path);
|
"on path '%s'", MAXSYMLINKS, path);
|
||||||
else
|
else
|
||||||
@ -153,7 +150,7 @@ char *strbuf_realpath(struct strbuf *resolved, const char *path,
|
|||||||
len = strbuf_readlink(&symlink, resolved->buf,
|
len = strbuf_readlink(&symlink, resolved->buf,
|
||||||
st.st_size);
|
st.st_size);
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
if (die_on_error)
|
if (flags & REALPATH_DIE_ON_ERROR)
|
||||||
die_errno("Invalid symlink '%s'",
|
die_errno("Invalid symlink '%s'",
|
||||||
resolved->buf);
|
resolved->buf);
|
||||||
else
|
else
|
||||||
@ -202,6 +199,37 @@ error_out:
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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));
|
||||||
|
}
|
||||||
|
|
||||||
char *real_pathdup(const char *path, int die_on_error)
|
char *real_pathdup(const char *path, int die_on_error)
|
||||||
{
|
{
|
||||||
struct strbuf realpath = STRBUF_INIT;
|
struct strbuf realpath = STRBUF_INIT;
|
||||||
|
@ -583,6 +583,75 @@ static void handle_ref_opt(const char *pattern, const char *prefix)
|
|||||||
clear_ref_exclusion(&ref_excludes);
|
clear_ref_exclusion(&ref_excludes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum format_type {
|
||||||
|
/* We would like a relative path. */
|
||||||
|
FORMAT_RELATIVE,
|
||||||
|
/* We would like a canonical absolute path. */
|
||||||
|
FORMAT_CANONICAL,
|
||||||
|
/* We would like the default behavior. */
|
||||||
|
FORMAT_DEFAULT,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum default_type {
|
||||||
|
/* Our default is a relative path. */
|
||||||
|
DEFAULT_RELATIVE,
|
||||||
|
/* Our default is a relative path if there's a shared root. */
|
||||||
|
DEFAULT_RELATIVE_IF_SHARED,
|
||||||
|
/* Our default is a canonical absolute path. */
|
||||||
|
DEFAULT_CANONICAL,
|
||||||
|
/* Our default is not to modify the item. */
|
||||||
|
DEFAULT_UNMODIFIED,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void print_path(const char *path, const char *prefix, enum format_type format, enum default_type def)
|
||||||
|
{
|
||||||
|
char *cwd = NULL;
|
||||||
|
/*
|
||||||
|
* We don't ever produce a relative path if prefix is NULL, so set the
|
||||||
|
* prefix to the current directory so that we can produce a relative
|
||||||
|
* path whenever possible. If we're using RELATIVE_IF_SHARED mode, then
|
||||||
|
* we want an absolute path unless the two share a common prefix, so don't
|
||||||
|
* set it in that case, since doing so causes a relative path to always
|
||||||
|
* be produced if possible.
|
||||||
|
*/
|
||||||
|
if (!prefix && (format != FORMAT_DEFAULT || def != DEFAULT_RELATIVE_IF_SHARED))
|
||||||
|
prefix = cwd = xgetcwd();
|
||||||
|
if (format == FORMAT_DEFAULT && def == DEFAULT_UNMODIFIED) {
|
||||||
|
puts(path);
|
||||||
|
} else if (format == FORMAT_RELATIVE ||
|
||||||
|
(format == FORMAT_DEFAULT && def == DEFAULT_RELATIVE)) {
|
||||||
|
/*
|
||||||
|
* In order for relative_path to work as expected, we need to
|
||||||
|
* make sure that both paths are absolute paths. If we don't,
|
||||||
|
* we can end up with an unexpected absolute path that the user
|
||||||
|
* didn't want.
|
||||||
|
*/
|
||||||
|
struct strbuf buf = STRBUF_INIT, realbuf = STRBUF_INIT, prefixbuf = STRBUF_INIT;
|
||||||
|
if (!is_absolute_path(path)) {
|
||||||
|
strbuf_realpath_forgiving(&realbuf, path, 1);
|
||||||
|
path = realbuf.buf;
|
||||||
|
}
|
||||||
|
if (!is_absolute_path(prefix)) {
|
||||||
|
strbuf_realpath_forgiving(&prefixbuf, prefix, 1);
|
||||||
|
prefix = prefixbuf.buf;
|
||||||
|
}
|
||||||
|
puts(relative_path(path, prefix, &buf));
|
||||||
|
strbuf_release(&buf);
|
||||||
|
strbuf_release(&realbuf);
|
||||||
|
strbuf_release(&prefixbuf);
|
||||||
|
} else if (format == FORMAT_DEFAULT && def == DEFAULT_RELATIVE_IF_SHARED) {
|
||||||
|
struct strbuf buf = STRBUF_INIT;
|
||||||
|
puts(relative_path(path, prefix, &buf));
|
||||||
|
strbuf_release(&buf);
|
||||||
|
} else {
|
||||||
|
struct strbuf buf = STRBUF_INIT;
|
||||||
|
strbuf_realpath_forgiving(&buf, path, 1);
|
||||||
|
puts(buf.buf);
|
||||||
|
strbuf_release(&buf);
|
||||||
|
}
|
||||||
|
free(cwd);
|
||||||
|
}
|
||||||
|
|
||||||
int cmd_rev_parse(int argc, const char **argv, const char *prefix)
|
int cmd_rev_parse(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
int i, as_is = 0, verify = 0, quiet = 0, revs_count = 0, type = 0;
|
int i, as_is = 0, verify = 0, quiet = 0, revs_count = 0, type = 0;
|
||||||
@ -596,6 +665,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
|
|||||||
struct strbuf buf = STRBUF_INIT;
|
struct strbuf buf = STRBUF_INIT;
|
||||||
const int hexsz = the_hash_algo->hexsz;
|
const int hexsz = the_hash_algo->hexsz;
|
||||||
int seen_end_of_options = 0;
|
int seen_end_of_options = 0;
|
||||||
|
enum format_type format = FORMAT_DEFAULT;
|
||||||
|
|
||||||
if (argc > 1 && !strcmp("--parseopt", argv[1]))
|
if (argc > 1 && !strcmp("--parseopt", argv[1]))
|
||||||
return cmd_parseopt(argc - 1, argv + 1, prefix);
|
return cmd_parseopt(argc - 1, argv + 1, prefix);
|
||||||
@ -668,8 +738,9 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
|
|||||||
if (!argv[i + 1])
|
if (!argv[i + 1])
|
||||||
die("--git-path requires an argument");
|
die("--git-path requires an argument");
|
||||||
strbuf_reset(&buf);
|
strbuf_reset(&buf);
|
||||||
puts(relative_path(git_path("%s", argv[i + 1]),
|
print_path(git_path("%s", argv[i + 1]), prefix,
|
||||||
prefix, &buf));
|
format,
|
||||||
|
DEFAULT_RELATIVE_IF_SHARED);
|
||||||
i++;
|
i++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -687,6 +758,16 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
|
|||||||
show(arg);
|
show(arg);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (opt_with_value(arg, "--path-format", &arg)) {
|
||||||
|
if (!strcmp(arg, "absolute")) {
|
||||||
|
format = FORMAT_CANONICAL;
|
||||||
|
} else if (!strcmp(arg, "relative")) {
|
||||||
|
format = FORMAT_RELATIVE;
|
||||||
|
} else {
|
||||||
|
die("unknown argument to --path-format: %s", arg);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!strcmp(arg, "--default")) {
|
if (!strcmp(arg, "--default")) {
|
||||||
def = argv[++i];
|
def = argv[++i];
|
||||||
if (!def)
|
if (!def)
|
||||||
@ -807,7 +888,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
|
|||||||
if (!strcmp(arg, "--show-toplevel")) {
|
if (!strcmp(arg, "--show-toplevel")) {
|
||||||
const char *work_tree = get_git_work_tree();
|
const char *work_tree = get_git_work_tree();
|
||||||
if (work_tree)
|
if (work_tree)
|
||||||
puts(work_tree);
|
print_path(work_tree, prefix, format, DEFAULT_UNMODIFIED);
|
||||||
else
|
else
|
||||||
die("this operation must be run in a work tree");
|
die("this operation must be run in a work tree");
|
||||||
continue;
|
continue;
|
||||||
@ -815,7 +896,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
|
|||||||
if (!strcmp(arg, "--show-superproject-working-tree")) {
|
if (!strcmp(arg, "--show-superproject-working-tree")) {
|
||||||
struct strbuf superproject = STRBUF_INIT;
|
struct strbuf superproject = STRBUF_INIT;
|
||||||
if (get_superproject_working_tree(&superproject))
|
if (get_superproject_working_tree(&superproject))
|
||||||
puts(superproject.buf);
|
print_path(superproject.buf, prefix, format, DEFAULT_UNMODIFIED);
|
||||||
strbuf_release(&superproject);
|
strbuf_release(&superproject);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -850,16 +931,18 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
|
|||||||
const char *gitdir = getenv(GIT_DIR_ENVIRONMENT);
|
const char *gitdir = getenv(GIT_DIR_ENVIRONMENT);
|
||||||
char *cwd;
|
char *cwd;
|
||||||
int len;
|
int len;
|
||||||
|
enum format_type wanted = format;
|
||||||
if (arg[2] == 'g') { /* --git-dir */
|
if (arg[2] == 'g') { /* --git-dir */
|
||||||
if (gitdir) {
|
if (gitdir) {
|
||||||
puts(gitdir);
|
print_path(gitdir, prefix, format, DEFAULT_UNMODIFIED);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!prefix) {
|
if (!prefix) {
|
||||||
puts(".git");
|
print_path(".git", prefix, format, DEFAULT_UNMODIFIED);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else { /* --absolute-git-dir */
|
} else { /* --absolute-git-dir */
|
||||||
|
wanted = FORMAT_CANONICAL;
|
||||||
if (!gitdir && !prefix)
|
if (!gitdir && !prefix)
|
||||||
gitdir = ".git";
|
gitdir = ".git";
|
||||||
if (gitdir) {
|
if (gitdir) {
|
||||||
@ -872,14 +955,14 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
|
|||||||
}
|
}
|
||||||
cwd = xgetcwd();
|
cwd = xgetcwd();
|
||||||
len = strlen(cwd);
|
len = strlen(cwd);
|
||||||
printf("%s%s.git\n", cwd, len && cwd[len-1] != '/' ? "/" : "");
|
strbuf_reset(&buf);
|
||||||
|
strbuf_addf(&buf, "%s%s.git", cwd, len && cwd[len-1] != '/' ? "/" : "");
|
||||||
free(cwd);
|
free(cwd);
|
||||||
|
print_path(buf.buf, prefix, wanted, DEFAULT_CANONICAL);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!strcmp(arg, "--git-common-dir")) {
|
if (!strcmp(arg, "--git-common-dir")) {
|
||||||
strbuf_reset(&buf);
|
print_path(get_git_common_dir(), prefix, format, DEFAULT_RELATIVE_IF_SHARED);
|
||||||
puts(relative_path(get_git_common_dir(),
|
|
||||||
prefix, &buf));
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!strcmp(arg, "--is-inside-git-dir")) {
|
if (!strcmp(arg, "--is-inside-git-dir")) {
|
||||||
@ -909,8 +992,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
|
|||||||
if (the_index.split_index) {
|
if (the_index.split_index) {
|
||||||
const struct object_id *oid = &the_index.split_index->base_oid;
|
const struct object_id *oid = &the_index.split_index->base_oid;
|
||||||
const char *path = git_path("sharedindex.%s", oid_to_hex(oid));
|
const char *path = git_path("sharedindex.%s", oid_to_hex(oid));
|
||||||
strbuf_reset(&buf);
|
print_path(path, prefix, format, DEFAULT_RELATIVE);
|
||||||
puts(relative_path(path, prefix, &buf));
|
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
2
cache.h
2
cache.h
@ -1231,6 +1231,8 @@ static inline int is_absolute_path(const char *path)
|
|||||||
int is_directory(const char *);
|
int is_directory(const char *);
|
||||||
char *strbuf_realpath(struct strbuf *resolved, const char *path,
|
char *strbuf_realpath(struct strbuf *resolved, const char *path,
|
||||||
int die_on_error);
|
int die_on_error);
|
||||||
|
char *strbuf_realpath_forgiving(struct strbuf *resolved, const char *path,
|
||||||
|
int die_on_error);
|
||||||
char *real_pathdup(const char *path, int die_on_error);
|
char *real_pathdup(const char *path, int die_on_error);
|
||||||
const char *absolute_path(const char *path);
|
const char *absolute_path(const char *path);
|
||||||
char *absolute_pathdup(const char *path);
|
char *absolute_pathdup(const char *path);
|
||||||
|
@ -3,6 +3,16 @@
|
|||||||
test_description='test git rev-parse'
|
test_description='test git rev-parse'
|
||||||
. ./test-lib.sh
|
. ./test-lib.sh
|
||||||
|
|
||||||
|
test_one () {
|
||||||
|
dir="$1" &&
|
||||||
|
expect="$2" &&
|
||||||
|
shift &&
|
||||||
|
shift &&
|
||||||
|
echo "$expect" >expect &&
|
||||||
|
git -C "$dir" rev-parse "$@" >actual &&
|
||||||
|
test_cmp expect actual
|
||||||
|
}
|
||||||
|
|
||||||
# usage: [options] label is-bare is-inside-git is-inside-work prefix git-dir absolute-git-dir
|
# usage: [options] label is-bare is-inside-git is-inside-work prefix git-dir absolute-git-dir
|
||||||
test_rev_parse () {
|
test_rev_parse () {
|
||||||
d=
|
d=
|
||||||
@ -60,7 +70,13 @@ ROOT=$(pwd)
|
|||||||
|
|
||||||
test_expect_success 'setup' '
|
test_expect_success 'setup' '
|
||||||
mkdir -p sub/dir work &&
|
mkdir -p sub/dir work &&
|
||||||
cp -R .git repo.git
|
cp -R .git repo.git &&
|
||||||
|
git checkout -B main &&
|
||||||
|
test_commit abc &&
|
||||||
|
git checkout -b side &&
|
||||||
|
test_commit def &&
|
||||||
|
git checkout main &&
|
||||||
|
git worktree add worktree side
|
||||||
'
|
'
|
||||||
|
|
||||||
test_rev_parse toplevel false false true '' .git "$ROOT/.git"
|
test_rev_parse toplevel false false true '' .git "$ROOT/.git"
|
||||||
@ -88,6 +104,45 @@ test_rev_parse -C work -g ../repo.git -b t 'GIT_DIR=../repo.git, core.bare = tru
|
|||||||
|
|
||||||
test_rev_parse -C work -g ../repo.git -b u 'GIT_DIR=../repo.git, core.bare undefined' false false true ''
|
test_rev_parse -C work -g ../repo.git -b u 'GIT_DIR=../repo.git, core.bare undefined' false false true ''
|
||||||
|
|
||||||
|
test_expect_success 'rev-parse --path-format=absolute' '
|
||||||
|
test_one "." "$ROOT/.git" --path-format=absolute --git-dir &&
|
||||||
|
test_one "." "$ROOT/.git" --path-format=absolute --git-common-dir &&
|
||||||
|
test_one "sub/dir" "$ROOT/.git" --path-format=absolute --git-dir &&
|
||||||
|
test_one "sub/dir" "$ROOT/.git" --path-format=absolute --git-common-dir &&
|
||||||
|
test_one "worktree" "$ROOT/.git/worktrees/worktree" --path-format=absolute --git-dir &&
|
||||||
|
test_one "worktree" "$ROOT/.git" --path-format=absolute --git-common-dir &&
|
||||||
|
test_one "." "$ROOT" --path-format=absolute --show-toplevel &&
|
||||||
|
test_one "." "$ROOT/.git/objects" --path-format=absolute --git-path objects &&
|
||||||
|
test_one "." "$ROOT/.git/objects/foo/bar/baz" --path-format=absolute --git-path objects/foo/bar/baz
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'rev-parse --path-format=relative' '
|
||||||
|
test_one "." ".git" --path-format=relative --git-dir &&
|
||||||
|
test_one "." ".git" --path-format=relative --git-common-dir &&
|
||||||
|
test_one "sub/dir" "../../.git" --path-format=relative --git-dir &&
|
||||||
|
test_one "sub/dir" "../../.git" --path-format=relative --git-common-dir &&
|
||||||
|
test_one "worktree" "../.git/worktrees/worktree" --path-format=relative --git-dir &&
|
||||||
|
test_one "worktree" "../.git" --path-format=relative --git-common-dir &&
|
||||||
|
test_one "." "./" --path-format=relative --show-toplevel &&
|
||||||
|
test_one "." ".git/objects" --path-format=relative --git-path objects &&
|
||||||
|
test_one "." ".git/objects/foo/bar/baz" --path-format=relative --git-path objects/foo/bar/baz
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success '--path-format=relative does not affect --absolute-git-dir' '
|
||||||
|
git rev-parse --path-format=relative --absolute-git-dir >actual &&
|
||||||
|
echo "$ROOT/.git" >expect &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success '--path-format can change in the middle of the command line' '
|
||||||
|
git rev-parse --path-format=absolute --git-dir --path-format=relative --git-path objects/foo/bar >actual &&
|
||||||
|
cat >expect <<-EOF &&
|
||||||
|
$ROOT/.git
|
||||||
|
.git/objects/foo/bar
|
||||||
|
EOF
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'git-common-dir from worktree root' '
|
test_expect_success 'git-common-dir from worktree root' '
|
||||||
echo .git >expect &&
|
echo .git >expect &&
|
||||||
git rev-parse --git-common-dir >actual &&
|
git rev-parse --git-common-dir >actual &&
|
||||||
|
Loading…
x
Reference in New Issue
Block a user