Skip to content

Commit 9ba366f

Browse files
committed
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
2 parents 6dbbae1 + fac60b8 commit 9ba366f

File tree

5 files changed

+242
-61
lines changed

5 files changed

+242
-61
lines changed

Documentation/git-rev-parse.txt

Lines changed: 44 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,18 @@ Options for Files
212212
Only the names of the variables are listed, not their value,
213213
even if they are set.
214214

215+
--path-format=(absolute|relative)::
216+
Controls the behavior of certain other options. If specified as absolute, the
217+
paths printed by those options will be absolute and canonical. If specified as
218+
relative, the paths will be relative to the current working directory if that
219+
is possible. The default is option specific.
220+
+
221+
This option may be specified multiple times and affects only the arguments that
222+
follow it on the command line, either to the end of the command line or the next
223+
instance of this option.
224+
225+
The following options are modified by `--path-format`:
226+
215227
--git-dir::
216228
Show `$GIT_DIR` if defined. Otherwise show the path to
217229
the .git directory. The path shown, when relative, is
@@ -221,27 +233,9 @@ If `$GIT_DIR` is not defined and the current directory
221233
is not detected to lie in a Git repository or work tree
222234
print a message to stderr and exit with nonzero status.
223235

224-
--absolute-git-dir::
225-
Like `--git-dir`, but its output is always the canonicalized
226-
absolute path.
227-
228236
--git-common-dir::
229237
Show `$GIT_COMMON_DIR` if defined, else `$GIT_DIR`.
230238

231-
--is-inside-git-dir::
232-
When the current working directory is below the repository
233-
directory print "true", otherwise "false".
234-
235-
--is-inside-work-tree::
236-
When the current working directory is inside the work tree of the
237-
repository print "true", otherwise "false".
238-
239-
--is-bare-repository::
240-
When the repository is bare print "true", otherwise "false".
241-
242-
--is-shallow-repository::
243-
When the repository is shallow print "true", otherwise "false".
244-
245239
--resolve-git-dir <path>::
246240
Check if <path> is a valid repository or a gitfile that
247241
points at a valid repository, and print the location of the
@@ -255,19 +249,9 @@ print a message to stderr and exit with nonzero status.
255249
$GIT_OBJECT_DIRECTORY is set to /foo/bar then "git rev-parse
256250
--git-path objects/abc" returns /foo/bar/abc.
257251

258-
--show-cdup::
259-
When the command is invoked from a subdirectory, show the
260-
path of the top-level directory relative to the current
261-
directory (typically a sequence of "../", or an empty string).
262-
263-
--show-prefix::
264-
When the command is invoked from a subdirectory, show the
265-
path of the current directory relative to the top-level
266-
directory.
267-
268252
--show-toplevel::
269-
Show the absolute path of the top-level directory of the working
270-
tree. If there is no working tree, report an error.
253+
Show the (by default, absolute) path of the top-level directory
254+
of the working tree. If there is no working tree, report an error.
271255

272256
--show-superproject-working-tree::
273257
Show the absolute path of the root of the superproject's
@@ -279,6 +263,36 @@ print a message to stderr and exit with nonzero status.
279263
Show the path to the shared index file in split index mode, or
280264
empty if not in split-index mode.
281265

266+
The following options are unaffected by `--path-format`:
267+
268+
--absolute-git-dir::
269+
Like `--git-dir`, but its output is always the canonicalized
270+
absolute path.
271+
272+
--is-inside-git-dir::
273+
When the current working directory is below the repository
274+
directory print "true", otherwise "false".
275+
276+
--is-inside-work-tree::
277+
When the current working directory is inside the work tree of the
278+
repository print "true", otherwise "false".
279+
280+
--is-bare-repository::
281+
When the repository is bare print "true", otherwise "false".
282+
283+
--is-shallow-repository::
284+
When the repository is shallow print "true", otherwise "false".
285+
286+
--show-cdup::
287+
When the command is invoked from a subdirectory, show the
288+
path of the top-level directory relative to the current
289+
directory (typically a sequence of "../", or an empty string).
290+
291+
--show-prefix::
292+
When the command is invoked from a subdirectory, show the
293+
path of the current directory relative to the top-level
294+
directory.
295+
282296
--show-object-format[=(storage|input|output)]::
283297
Show the object format (hash algorithm) used for the repository
284298
for storage inside the `.git` directory, input, or output. For

abspath.c

Lines changed: 46 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -67,19 +67,15 @@ static void get_root_part(struct strbuf *resolved, struct strbuf *remaining)
6767
#endif
6868

6969
/*
70-
* Return the real path (i.e., absolute path, with symlinks resolved
71-
* and extra slashes removed) equivalent to the specified path. (If
72-
* you want an absolute path but don't mind links, use
73-
* absolute_path().) Places the resolved realpath in the provided strbuf.
74-
*
75-
* The directory part of path (i.e., everything up to the last
76-
* dir_sep) must denote a valid, existing directory, but the last
77-
* component need not exist. If die_on_error is set, then die with an
78-
* informative error message if there is a problem. Otherwise, return
79-
* NULL on errors (without generating any output).
70+
* If set, any number of trailing components may be missing; otherwise, only one
71+
* may be.
8072
*/
81-
char *strbuf_realpath(struct strbuf *resolved, const char *path,
82-
int die_on_error)
73+
#define REALPATH_MANY_MISSING (1 << 0)
74+
/* Should we die if there's an error? */
75+
#define REALPATH_DIE_ON_ERROR (1 << 1)
76+
77+
static char *strbuf_realpath_1(struct strbuf *resolved, const char *path,
78+
int flags)
8379
{
8480
struct strbuf remaining = STRBUF_INIT;
8581
struct strbuf next = STRBUF_INIT;
@@ -89,7 +85,7 @@ char *strbuf_realpath(struct strbuf *resolved, const char *path,
8985
struct stat st;
9086

9187
if (!*path) {
92-
if (die_on_error)
88+
if (flags & REALPATH_DIE_ON_ERROR)
9389
die("The empty string is not a valid path");
9490
else
9591
goto error_out;
@@ -101,7 +97,7 @@ char *strbuf_realpath(struct strbuf *resolved, const char *path,
10197
if (!resolved->len) {
10298
/* relative path; can use CWD as the initial resolved path */
10399
if (strbuf_getcwd(resolved)) {
104-
if (die_on_error)
100+
if (flags & REALPATH_DIE_ON_ERROR)
105101
die_errno("unable to get current working directory");
106102
else
107103
goto error_out;
@@ -129,8 +125,9 @@ char *strbuf_realpath(struct strbuf *resolved, const char *path,
129125

130126
if (lstat(resolved->buf, &st)) {
131127
/* error out unless this was the last component */
132-
if (errno != ENOENT || remaining.len) {
133-
if (die_on_error)
128+
if (errno != ENOENT ||
129+
(!(flags & REALPATH_MANY_MISSING) && remaining.len)) {
130+
if (flags & REALPATH_DIE_ON_ERROR)
134131
die_errno("Invalid path '%s'",
135132
resolved->buf);
136133
else
@@ -143,7 +140,7 @@ char *strbuf_realpath(struct strbuf *resolved, const char *path,
143140
if (num_symlinks++ > MAXSYMLINKS) {
144141
errno = ELOOP;
145142

146-
if (die_on_error)
143+
if (flags & REALPATH_DIE_ON_ERROR)
147144
die("More than %d nested symlinks "
148145
"on path '%s'", MAXSYMLINKS, path);
149146
else
@@ -153,7 +150,7 @@ char *strbuf_realpath(struct strbuf *resolved, const char *path,
153150
len = strbuf_readlink(&symlink, resolved->buf,
154151
st.st_size);
155152
if (len < 0) {
156-
if (die_on_error)
153+
if (flags & REALPATH_DIE_ON_ERROR)
157154
die_errno("Invalid symlink '%s'",
158155
resolved->buf);
159156
else
@@ -202,6 +199,37 @@ char *strbuf_realpath(struct strbuf *resolved, const char *path,
202199
return retval;
203200
}
204201

202+
/*
203+
* Return the real path (i.e., absolute path, with symlinks resolved
204+
* and extra slashes removed) equivalent to the specified path. (If
205+
* you want an absolute path but don't mind links, use
206+
* absolute_path().) Places the resolved realpath in the provided strbuf.
207+
*
208+
* The directory part of path (i.e., everything up to the last
209+
* dir_sep) must denote a valid, existing directory, but the last
210+
* component need not exist. If die_on_error is set, then die with an
211+
* informative error message if there is a problem. Otherwise, return
212+
* NULL on errors (without generating any output).
213+
*/
214+
char *strbuf_realpath(struct strbuf *resolved, const char *path,
215+
int die_on_error)
216+
{
217+
return strbuf_realpath_1(resolved, path,
218+
die_on_error ? REALPATH_DIE_ON_ERROR : 0);
219+
}
220+
221+
/*
222+
* Just like strbuf_realpath, but allows an arbitrary number of path
223+
* components to be missing.
224+
*/
225+
char *strbuf_realpath_forgiving(struct strbuf *resolved, const char *path,
226+
int die_on_error)
227+
{
228+
return strbuf_realpath_1(resolved, path,
229+
((die_on_error ? REALPATH_DIE_ON_ERROR : 0) |
230+
REALPATH_MANY_MISSING));
231+
}
232+
205233
char *real_pathdup(const char *path, int die_on_error)
206234
{
207235
struct strbuf realpath = STRBUF_INIT;

0 commit comments

Comments
 (0)