From: Junio C Hamano <gitster@pobox.com>
To: Robin Rosenberg <robin.rosenberg.lists@dewire.com>
Cc: Jeff King <peff@peff.net>,
Anatol Pomozov <anatol.pomozov@gmail.com>,
git@vger.kernel.org,
Linus Torvalds <torvalds@linux-foundation.org>
Subject: Re: [PATCH] Make Git accept absolute path names for files within the work tree
Date: Mon, 03 Dec 2007 15:03:10 -0800 [thread overview]
Message-ID: <7vr6i3e5zl.fsf@gitster.siamese.dyndns.org> (raw)
In-Reply-To: <200712032153.31322.robin.rosenberg.lists@dewire.com> (Robin Rosenberg's message of "Mon, 3 Dec 2007 21:53:30 +0100")
Robin Rosenberg <robin.rosenberg.lists@dewire.com> writes:
> I will not surrender to the fierce competion on this subject. Here is
> an update with hopefully correct test cases this time.
Yay, that's the spirit!
> ... Like Linus, this code does not resolve symlinks,
> but I forgot to state that it is by design.
Perhaps state it in the commit log message?
> static const char *add_prefix(const char *prefix, const char *path)
> {
> + return prefix_path(prefix, prefix ? strlen(prefix) : 0, path);
> }
Ok; prefix_path can get NULL prefix (not complaining; just a reminder in
the following discussion).
> diff --git a/setup.c b/setup.c
> index 2c7b5cb..1f0ec79 100644
> --- a/setup.c
> +++ b/setup.c
> @@ -4,9 +4,62 @@
> static int inside_git_dir = -1;
> static int inside_work_tree = -1;
>
> +static
> +const char *strip_work_tree_path(const char *prefix, int len, const char *path)
Style. "static" not on its own line.
> +{
> + const char *work_tree = get_git_work_tree();
> + int n = strlen(work_tree);
Preconditions.
* prefix could be NULL or path to the subdirectory the user's
non-absolute path should be relative to, expressed as a relative path
to the top of the work tree, including a trailing slash. len is the
length of the prefix string.
* path was determined by the caller to be absolute.
* It is assumed that get_git_work_tree() always gives absolute path,
and without trailing slash.
* Does prefix always NULL if we are at the top, and never "", I wonder.
But lets assume that, too.
> + if (strncmp(path, work_tree, n))
> + return path;
If the given path is outside the work tree, return absolute as-is.
After this point we know path matches the work tree
> + if (!prefix && !path[n])
> + return path + n;
If we are at the top of the work tree and path names the top of the work
tree, then we return "".
> + if (!prefix) {
> + if (path[n] == '/')
> + return path + n + 1;
If we are at the top of the work tree and the path names the top of the
work tree followed by a slash and then something, that is a path inside
the work tree. Return relative to the top of the work tree.
> + else
> + if (path[n])
> + return path;
> + else
> + return path + n;
> + }
Style. "else if" would give you shallower indentation. We know path[n]
was not slash, and if it is not NUL then path is not inside the work
tree but is a neighbour (e.g. worktree is /a/b and path is /a/bc).
Return absolute. Otherwise the path names the top of the work tree
itself so we return "".
Now at this point, we know we are in a subdirectory, because the above
if (!prefix) part always return. So the test for prefix here is
unnecessary.
> + if (prefix && !path[n])
> + return path;
If we are in a subdirectory, and path names the top of the work tree, we
return it as-is (i.e. absolute). This feels a bit inconsistent with the
part that follows, which tries to make things relative by using "../",
doesn't it?
> + if (strncmp(path + n + 1, prefix, len - 1)) {
For !prefix case we have determined path is not merely a neighbour, but
we haven't checked that in this codepath. If the parameters were like
this:
path = /axbc/e
work_tree = /a
n = 2
prefix = bc/
len = 3
this check says "fine, path is under prefix and we won't add ../
uplevels". You need to have
if (path[n] != '/')
return path;
before this strncmp() for it to work, don't you?
In addition, by comparing (len - 1) excluding the trailing slash of
prefix, I think you would let
path = /a/bcye
slip through as well. That is inside the work_tree but outside of your
prefix.
> + fprintf(stderr,"prefix mismatch\n");
Stray debugging fprintf.
> + char *np;
> + int i;
> + int d=0;
Style "d = 0" (and "decl after statement").
> + for (i = 0; i < len; ++i)
Style. Distracts the reader by forcing him to wonder needlessly if
there is a particular reason for pre-increment of i instead of the usual
post-increment.
> + if (prefix[i] == '/')
> + d++;
> + np = xmalloc(strlen(path + n) + d * 3 + 1);
At this point (assuming that the above if (strncmp()) rejected the path
outside the prefix correctly), we know that we would need to go d levels
up to reach the top of the work tree.
> + for (i=0; i < d * 3; i += 3)
Style. "i = 0".
> + strcpy(np + i, "../");
> + strcpy(np + i, path + n + 1);
As path+n+1 is relative to the work tree, this will make it relative,
which is good.
> + path = np;
> + return np;
> + }
Assuming the if (strncmp()) above correctly handled the path outside
prefix, we are dealing with the path that is inside prefix at this
point. (len+n) is the length of the prefix directory expressed as an
absolute path.
> + if (path[len + n] == '/')
> + return path + len + n + 1;
So strip the absolute prefix would make the result relative to the
prefix directory. Nice.
> + else
> + if (path[len + n])
> + return path;
The same comment on "else if" applies. path[len+n] was not slash so
path was not inside the prefix after all. Oops? The "if outside
prefix we uplevel with ../" logic above should have handled this case
and we should not be here.
> + else
> + return path + len + n;
> +}
path[len+n] was NUL, which means taht the user named the prefix
directory, and we return "".
Isn't this _overly_ complicated? I think what this function wants to do
is:
* See if path is outside the work tree, and return absolute if so.
* Come up with the absolute path for the prefix (if NULL then that is
the same as work tree) directory, without a trailing slash, and call
it X.
* Is path the same as the X? If so, "" is what you want.
* Is path a prefix of the "X/"? If so strip "X/" and return.
* Find the longuest common leading directory of path and "X/" and call
it "C/". Note that this is guaranteed to be inside work tree because
we rejected paths outside work tree upfront.
* Count slashes between "C/" and "X/" and come up with necessary
uplevel "../". Strip "C/" from path and prepend the uplevel.
next prev parent reply other threads:[~2007-12-03 23:03 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-12-03 0:52 Incorrect git-blame result if I use full path to file Anatol Pomozov
2007-12-03 2:19 ` Junio C Hamano
2007-12-03 2:28 ` Jeff King
2007-12-03 17:26 ` Linus Torvalds
2007-12-03 18:09 ` Johannes Schindelin
2007-12-03 18:13 ` Linus Torvalds
2007-12-03 18:19 ` Linus Torvalds
2007-12-03 2:27 ` Jeff King
2007-12-03 2:40 ` Junio C Hamano
2007-12-03 2:49 ` Jeff King
2007-12-03 6:55 ` Robin Rosenberg
2007-12-03 20:53 ` [PATCH] Make Git accept absolute path names for files within the work tree Robin Rosenberg
2007-12-03 23:03 ` Junio C Hamano [this message]
2007-12-04 1:43 ` Jeff King
2007-12-04 2:17 ` Johannes Schindelin
2007-12-04 6:42 ` Robin Rosenberg
2007-12-04 11:50 ` Johannes Schindelin
2007-12-04 15:59 ` Linus Torvalds
2007-12-04 22:08 ` Jeff King
2007-12-04 22:52 ` Linus Torvalds
2007-12-06 6:12 ` Jeff King
-- strict thread matches above, loose matches on Subject: below --
2007-11-26 23:18 Robin Rosenberg
2007-11-27 0:24 ` Junio C Hamano
2007-11-27 23:20 ` Robin Rosenberg
2007-11-27 23:24 ` Robin Rosenberg
2007-11-28 8:43 ` Junio C Hamano
2007-11-29 1:15 ` Robin Rosenberg
2007-11-29 2:05 ` Junio C Hamano
2007-11-29 0:37 ` Junio C Hamano
2007-11-27 8:45 ` Johannes Sixt
2007-11-27 23:14 ` Robin Rosenberg
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=7vr6i3e5zl.fsf@gitster.siamese.dyndns.org \
--to=gitster@pobox.com \
--cc=anatol.pomozov@gmail.com \
--cc=git@vger.kernel.org \
--cc=peff@peff.net \
--cc=robin.rosenberg.lists@dewire.com \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).