Hi brian, On Fri, 27 Nov 2020, brian m. carlson wrote: > @@ -80,6 +97,16 @@ static void get_root_part(struct strbuf *resolved, struct strbuf *remaining) > */ > char *strbuf_realpath(struct strbuf *resolved, const char *path, > int die_on_error) > +{ > + return strbuf_realpath_missing(resolved, path, 1, die_on_error); > +} > + > +/* > + * Just like strbuf_realpath, but allows specifying how many missing components > + * are permitted. -1 may be specified to allow an unlimited number. > + */ > +char *strbuf_realpath_missing(struct strbuf *resolved, const char *path, > + int missing_components, int die_on_error) I am having a hard time with the name `missing_components`. Taking a step back, I think that we are interested in essentially two modes: allow one missing component, or an arbitrary amount of missing components. If this assumption is correct, we may not even need to count components at all. We only need a flag indicating whether we allow only the last component to be missing, or any number of components. Maybe something like `error_on_missing_parent_directory` or some such? Ciao, Dscho > { > struct strbuf remaining = STRBUF_INIT; > struct strbuf next = STRBUF_INIT; > @@ -128,8 +155,12 @@ char *strbuf_realpath(struct strbuf *resolved, const char *path, > strbuf_addbuf(resolved, &next); > > if (lstat(resolved->buf, &st)) { > + int trailing_components = count_dir_separators(remaining.buf) + > + (remaining.len != 0); > /* error out unless this was the last component */ > - if (errno != ENOENT || remaining.len) { > + if (errno != ENOENT || > + !(missing_components == -1 || > + trailing_components < missing_components)) { > if (die_on_error) > die_errno("Invalid path '%s'", > resolved->buf); > diff --git a/cache.h b/cache.h > index c0072d43b1..ee4bc5ec04 100644 > --- a/cache.h > +++ b/cache.h > @@ -1320,6 +1320,8 @@ static inline int is_absolute_path(const char *path) > int is_directory(const char *); > char *strbuf_realpath(struct strbuf *resolved, const char *path, > int die_on_error); > +char *strbuf_realpath_missing(struct strbuf *resolved, const char *path, > + int missing_components, int die_on_error); > char *real_pathdup(const char *path, int die_on_error); > const char *absolute_path(const char *path); > char *absolute_pathdup(const char *path); >