From 104f3e03c03a83617bac9d120b5e536c5f29d9ef Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 22 Dec 2005 22:37:50 -0800 Subject: [PATCH 1/2] checkout: sometimes work from a subdirectory. git-checkout does two very different things, and what they should do when run from subdirectory are quite different. It does not make any sense to run the one that switches the current head from anywhere other than the toplevel: git-checkout [-f] git-checkout [-b ] We could of course chdir to top and do the whole-tree checkout in git-checkout, but the point is the operation does not make sense on a partial tree. The whole tree is checked out. The other form is to update the index file and working tree file selectively: git-checkout ... ;# out of tree to index and file git-checkout -- ... ;# out of index to file This form _does_ make sense to run from subdirectory; and I myself often wish we supported this. So here is a patch to do both. Signed-off-by: Junio C Hamano --- git-checkout.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/git-checkout.sh b/git-checkout.sh index 36308d22c6..1219ea0b0e 100755 --- a/git-checkout.sh +++ b/git-checkout.sh @@ -1,6 +1,7 @@ #!/bin/sh USAGE='[-f] [-b ] [] [...]' +SUBDIRECTORY_OK=Sometimes . git-sh-setup old=$(git-rev-parse HEAD) @@ -95,6 +96,14 @@ else fi fi +# We are switching branches and checking out trees, so +# we *NEED* to be at the toplevel. +cdup=$(git-rev-parse --show-cdup) +if test ! -z "$cdup" +then + cd "$cdup" +fi + [ -z "$new" ] && new=$old # If we don't have an old branch that we're switching to, From a69dd585fca9ab7fc4a07f7563f6cdb106e3ffed Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 23 Dec 2005 13:39:30 -0800 Subject: [PATCH 2/2] ls-tree: chomp leading directories when run from a subdirectory When run from a subdirectory, even though we filtered the output based on where we were using pathspec, we wrote out the repository relative paths, not subtree relative paths. This changes things so that it shows only the current subdirectory relative paths. For example, in Documentation subdirectory of git itself, this used to be the case: $ git-ls-tree --name-only HEAD | grep how Documentation/git-show-branch.txt Documentation/git-show-index.txt Documentation/howto-index.sh Documentation/howto But now it does this instead: $ git-ls-tree --name-only HEAD | grep how git-show-branch.txt git-show-index.txt howto-index.sh howto There are two things to keep in mind. 1. This shows nothing. $ git-ls-tree --name-only HEAD ../ppc/ This is to make things consistent with ls-files, which refuses relative path that goes uplevel. 2. These show things in full repository relative paths. In this case, paths outside the current subdirectory are also shown. $ git-ls-tree --name-only --full-name HEAD | grep how Documentation/git-show-branch.txt Documentation/git-show-index.txt Documentation/howto-index.sh Documentation/howto $ git-ls-tree --name-only --full-name HEAD ../ppc/ ppc/sha1.c ppc/sha1.h ppc/sha1ppc.S The flag --full-name gives the same behaviour as 1.0, so it ought to be the default if we really care about the backward compatibility, but in practice no Porcelain runs ls-tree from a subdirectory yet, and without --full-name is more human friendly, so hopefully the default being not --full-name would be acceptable. Signed-off-by: Junio C Hamano --- ls-tree.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/ls-tree.c b/ls-tree.c index dae377d995..d585b6fc13 100644 --- a/ls-tree.c +++ b/ls-tree.c @@ -15,9 +15,11 @@ static int line_termination = '\n'; #define LS_NAME_ONLY 8 static int ls_options = 0; const char **pathspec; +static int chomp_prefix = 0; +static const char *prefix; static const char ls_tree_usage[] = - "git-ls-tree [-d] [-r] [-t] [-z] [--name-only] [--name-status] [path...]"; + "git-ls-tree [-d] [-r] [-t] [-z] [--name-only] [--name-status] [--full-name] [path...]"; static int show_recursive(const char *base, int baselen, const char *pathname) { @@ -49,7 +51,8 @@ static int show_recursive(const char *base, int baselen, const char *pathname) } } -static int show_tree(unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage) +static int show_tree(unsigned char *sha1, const char *base, int baselen, + const char *pathname, unsigned mode, int stage) { int retval = 0; const char *type = "blob"; @@ -65,21 +68,28 @@ static int show_tree(unsigned char *sha1, const char *base, int baselen, const c else if (ls_options & LS_TREE_ONLY) return 0; + if (chomp_prefix && + (baselen < chomp_prefix || memcmp(prefix, base, chomp_prefix))) + return 0; + if (!(ls_options & LS_NAME_ONLY)) printf("%06o %s %s\t", mode, type, sha1_to_hex(sha1)); - write_name_quoted(base, baselen, pathname, line_termination, stdout); + write_name_quoted(base + chomp_prefix, baselen - chomp_prefix, + pathname, + line_termination, stdout); putchar(line_termination); return retval; } int main(int argc, const char **argv) { - const char *prefix; unsigned char sha1[20]; char *buf; unsigned long size; prefix = setup_git_directory(); + if (prefix && *prefix) + chomp_prefix = strlen(prefix); while (1 < argc && argv[1][0] == '-') { switch (argv[1][1]) { case 'z': @@ -100,6 +110,10 @@ int main(int argc, const char **argv) ls_options |= LS_NAME_ONLY; break; } + if (!strcmp(argv[1]+2, "full-name")) { + chomp_prefix = 0; + break; + } /* otherwise fallthru */ default: usage(ls_tree_usage);