2005-04-13 17:02:34 +08:00
|
|
|
/*
|
|
|
|
* GIT - The information manager from hell
|
|
|
|
*
|
|
|
|
* Copyright (C) Linus Torvalds, 2005
|
|
|
|
*/
|
|
|
|
#include "cache.h"
|
[PATCH] Rewrite ls-tree to behave more like "/bin/ls -a"
This is a complete rewrite of ls-tree to make it behave more
like what "/bin/ls -a" does in the current working directory.
Namely, the changes are:
- Unlike the old ls-tree behaviour that used paths arguments to
restrict output (not that it worked as intended---as pointed
out in the mailing list discussion, it was quite incoherent),
this rewrite uses paths arguments to specify what to show.
- Without arguments, it implicitly uses the root level as its
sole argument ("/bin/ls -a" behaves as if "." is given
without argument).
- Without -r (recursive) flag, it shows the named blob (either
file or symlink), or the named tree and its immediate
children.
- With -r flag, it shows the named path, and recursively
descends into it if it is a tree.
- With -d flag, it shows the named path and does not show its
children even if the path is a tree, nor descends into it
recursively.
This is still request-for-comments patch. There is no mailing
list consensus that this proposed new behaviour is a good one.
The patch to t/t3100-ls-tree-restrict.sh illustrates
user-visible behaviour changes. Namely:
* "git-ls-tree $tree path1 path0" lists path1 first and then
path0. It used to use paths as an output restrictor and
showed output in cache entry order (i.e. path0 first and then
path1) regardless of the order of paths arguments.
* "git-ls-tree $tree path2" lists path2 and its immediate
children but having explicit paths argument does not imply
recursive behaviour anymore, hence paths/baz is shown but not
paths/baz/b.
Signed-off-by: Junio C Hamano <junkio@cox.net>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-05-28 15:05:38 +08:00
|
|
|
#include "blob.h"
|
|
|
|
#include "tree.h"
|
2007-04-10 12:20:29 +08:00
|
|
|
#include "commit.h"
|
2005-10-15 12:56:46 +08:00
|
|
|
#include "quote.h"
|
2006-05-23 20:15:30 +08:00
|
|
|
#include "builtin.h"
|
2005-04-13 17:02:34 +08:00
|
|
|
|
2005-05-21 02:46:10 +08:00
|
|
|
static int line_termination = '\n';
|
[PATCH] Rewrite ls-tree to behave more like "/bin/ls -a"
This is a complete rewrite of ls-tree to make it behave more
like what "/bin/ls -a" does in the current working directory.
Namely, the changes are:
- Unlike the old ls-tree behaviour that used paths arguments to
restrict output (not that it worked as intended---as pointed
out in the mailing list discussion, it was quite incoherent),
this rewrite uses paths arguments to specify what to show.
- Without arguments, it implicitly uses the root level as its
sole argument ("/bin/ls -a" behaves as if "." is given
without argument).
- Without -r (recursive) flag, it shows the named blob (either
file or symlink), or the named tree and its immediate
children.
- With -r flag, it shows the named path, and recursively
descends into it if it is a tree.
- With -d flag, it shows the named path and does not show its
children even if the path is a tree, nor descends into it
recursively.
This is still request-for-comments patch. There is no mailing
list consensus that this proposed new behaviour is a good one.
The patch to t/t3100-ls-tree-restrict.sh illustrates
user-visible behaviour changes. Namely:
* "git-ls-tree $tree path1 path0" lists path1 first and then
path0. It used to use paths as an output restrictor and
showed output in cache entry order (i.e. path0 first and then
path1) regardless of the order of paths arguments.
* "git-ls-tree $tree path2" lists path2 and its immediate
children but having explicit paths argument does not imply
recursive behaviour anymore, hence paths/baz is shown but not
paths/baz/b.
Signed-off-by: Junio C Hamano <junkio@cox.net>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-05-28 15:05:38 +08:00
|
|
|
#define LS_RECURSIVE 1
|
|
|
|
#define LS_TREE_ONLY 2
|
2005-12-02 02:35:51 +08:00
|
|
|
#define LS_SHOW_TREES 4
|
2005-12-02 06:54:00 +08:00
|
|
|
#define LS_NAME_ONLY 8
|
2007-05-20 04:08:11 +08:00
|
|
|
#define LS_SHOW_SIZE 16
|
2006-08-16 01:23:48 +08:00
|
|
|
static int abbrev;
|
|
|
|
static int ls_options;
|
2006-05-23 20:15:30 +08:00
|
|
|
static const char **pathspec;
|
2006-08-16 01:23:48 +08:00
|
|
|
static int chomp_prefix;
|
2006-07-29 13:44:25 +08:00
|
|
|
static const char *ls_tree_prefix;
|
2005-04-15 23:37:05 +08:00
|
|
|
|
2005-11-27 01:38:20 +08:00
|
|
|
static const char ls_tree_usage[] =
|
2007-05-20 04:08:11 +08:00
|
|
|
"git-ls-tree [-d] [-r] [-t] [-l] [-z] [--name-only] [--name-status] [--full-name] [--abbrev[=<n>]] <tree-ish> [path...]";
|
2005-12-02 02:35:51 +08:00
|
|
|
|
|
|
|
static int show_recursive(const char *base, int baselen, const char *pathname)
|
|
|
|
{
|
|
|
|
const char **s;
|
|
|
|
|
|
|
|
if (ls_options & LS_RECURSIVE)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
s = pathspec;
|
|
|
|
if (!s)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
const char *spec = *s++;
|
|
|
|
int len, speclen;
|
|
|
|
|
|
|
|
if (!spec)
|
|
|
|
return 0;
|
|
|
|
if (strncmp(base, spec, baselen))
|
|
|
|
continue;
|
|
|
|
len = strlen(pathname);
|
|
|
|
spec += baselen;
|
|
|
|
speclen = strlen(spec);
|
|
|
|
if (speclen <= len)
|
|
|
|
continue;
|
|
|
|
if (memcmp(pathname, spec, len))
|
|
|
|
continue;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
2005-04-15 23:37:05 +08:00
|
|
|
|
2006-05-29 06:13:53 +08:00
|
|
|
static int show_tree(const unsigned char *sha1, const char *base, int baselen,
|
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 <junkio@cox.net>
2005-12-24 05:39:30 +08:00
|
|
|
const char *pathname, unsigned mode, int stage)
|
[PATCH] Rewrite ls-tree to behave more like "/bin/ls -a"
This is a complete rewrite of ls-tree to make it behave more
like what "/bin/ls -a" does in the current working directory.
Namely, the changes are:
- Unlike the old ls-tree behaviour that used paths arguments to
restrict output (not that it worked as intended---as pointed
out in the mailing list discussion, it was quite incoherent),
this rewrite uses paths arguments to specify what to show.
- Without arguments, it implicitly uses the root level as its
sole argument ("/bin/ls -a" behaves as if "." is given
without argument).
- Without -r (recursive) flag, it shows the named blob (either
file or symlink), or the named tree and its immediate
children.
- With -r flag, it shows the named path, and recursively
descends into it if it is a tree.
- With -d flag, it shows the named path and does not show its
children even if the path is a tree, nor descends into it
recursively.
This is still request-for-comments patch. There is no mailing
list consensus that this proposed new behaviour is a good one.
The patch to t/t3100-ls-tree-restrict.sh illustrates
user-visible behaviour changes. Namely:
* "git-ls-tree $tree path1 path0" lists path1 first and then
path0. It used to use paths as an output restrictor and
showed output in cache entry order (i.e. path0 first and then
path1) regardless of the order of paths arguments.
* "git-ls-tree $tree path2" lists path2 and its immediate
children but having explicit paths argument does not imply
recursive behaviour anymore, hence paths/baz is shown but not
paths/baz/b.
Signed-off-by: Junio C Hamano <junkio@cox.net>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-05-28 15:05:38 +08:00
|
|
|
{
|
2005-12-02 02:35:51 +08:00
|
|
|
int retval = 0;
|
2006-04-02 20:44:09 +08:00
|
|
|
const char *type = blob_type;
|
2007-05-20 04:08:11 +08:00
|
|
|
unsigned long size;
|
2005-10-08 07:54:06 +08:00
|
|
|
|
2007-05-22 04:08:28 +08:00
|
|
|
if (S_ISGITLINK(mode)) {
|
2007-04-10 12:20:29 +08:00
|
|
|
/*
|
|
|
|
* Maybe we want to have some recursive version here?
|
|
|
|
*
|
|
|
|
* Something like:
|
|
|
|
*
|
|
|
|
if (show_subprojects(base, baselen, pathname)) {
|
|
|
|
if (fork()) {
|
|
|
|
chdir(base);
|
|
|
|
exec ls-tree;
|
|
|
|
}
|
|
|
|
waitpid();
|
|
|
|
}
|
|
|
|
*
|
|
|
|
* ..or similar..
|
|
|
|
*/
|
|
|
|
type = commit_type;
|
|
|
|
} else if (S_ISDIR(mode)) {
|
2005-12-02 02:35:51 +08:00
|
|
|
if (show_recursive(base, baselen, pathname)) {
|
|
|
|
retval = READ_TREE_RECURSIVE;
|
|
|
|
if (!(ls_options & LS_SHOW_TREES))
|
|
|
|
return retval;
|
ls-tree: further tweaks of the rewrite
It modifies the selection a bit, so that a pathspec that is a superset of
a particular tree path will always cause it to recurse into that tree.
As an example, let's say that we do
git-ls-tree HEAD drivers/char
_without_ the "-r". What will happen is that it will start out doing all
the base tree, and for "drivers" it will notice that it's a proper subset
of "drivers/char", so it will always recurse into _that_ tree (but not
into other trees).
Then, it will not match anything else than "char" in that subdirectory,
and because that's not a proper superset (it's an exact match), it will
_not_ recurse into it, so you get:
[torvalds@g5 linux]$ ~/git/git-ls-tree HEAD drivers/char
040000 tree 9568cda453aae205bb58983747fa73b9696d9d51 drivers/char
which is what you got with the old git-ls-tree too.
But interestingly, if you add the slash, it will become a proper superset
and it will recurse into _that_ subdirectory (but no deeper: so if you
want all subdirectories _below_ drivers/char/, you still need to give
"-r"):
[torvalds@g5 linux]$ ~/git/git-ls-tree HEAD drivers/char/
100644 blob 2b6b1d772ed776fff87927fc34adc2e40500218e drivers/char/.gitignore
100644 blob 56b8a2e76ab10a5c21787cb7068a846075cbaffd drivers/char/ChangeLog
100644 blob 970f70d498f4c814e1cf3362e33d7e23ac53c299 drivers/char/Kconfig
...
See? This is on top of the previous two diffs, holler if you want a whole
new "everything combined" version..
It hasn't gotten lots of testing, but it should work.
Linus
2005-11-28 14:48:08 +08:00
|
|
|
}
|
2006-04-02 20:44:09 +08:00
|
|
|
type = tree_type;
|
[PATCH] Rewrite ls-tree to behave more like "/bin/ls -a"
This is a complete rewrite of ls-tree to make it behave more
like what "/bin/ls -a" does in the current working directory.
Namely, the changes are:
- Unlike the old ls-tree behaviour that used paths arguments to
restrict output (not that it worked as intended---as pointed
out in the mailing list discussion, it was quite incoherent),
this rewrite uses paths arguments to specify what to show.
- Without arguments, it implicitly uses the root level as its
sole argument ("/bin/ls -a" behaves as if "." is given
without argument).
- Without -r (recursive) flag, it shows the named blob (either
file or symlink), or the named tree and its immediate
children.
- With -r flag, it shows the named path, and recursively
descends into it if it is a tree.
- With -d flag, it shows the named path and does not show its
children even if the path is a tree, nor descends into it
recursively.
This is still request-for-comments patch. There is no mailing
list consensus that this proposed new behaviour is a good one.
The patch to t/t3100-ls-tree-restrict.sh illustrates
user-visible behaviour changes. Namely:
* "git-ls-tree $tree path1 path0" lists path1 first and then
path0. It used to use paths as an output restrictor and
showed output in cache entry order (i.e. path0 first and then
path1) regardless of the order of paths arguments.
* "git-ls-tree $tree path2" lists path2 and its immediate
children but having explicit paths argument does not imply
recursive behaviour anymore, hence paths/baz is shown but not
paths/baz/b.
Signed-off-by: Junio C Hamano <junkio@cox.net>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-05-28 15:05:38 +08:00
|
|
|
}
|
2005-12-02 05:15:20 +08:00
|
|
|
else if (ls_options & LS_TREE_ONLY)
|
|
|
|
return 0;
|
2005-10-08 07:54:06 +08:00
|
|
|
|
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 <junkio@cox.net>
2005-12-24 05:39:30 +08:00
|
|
|
if (chomp_prefix &&
|
2006-07-29 13:44:25 +08:00
|
|
|
(baselen < chomp_prefix || memcmp(ls_tree_prefix, base, chomp_prefix)))
|
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 <junkio@cox.net>
2005-12-24 05:39:30 +08:00
|
|
|
return 0;
|
|
|
|
|
2007-05-20 04:08:11 +08:00
|
|
|
if (!(ls_options & LS_NAME_ONLY)) {
|
|
|
|
if (ls_options & LS_SHOW_SIZE) {
|
|
|
|
if (!strcmp(type, blob_type)) {
|
|
|
|
sha1_object_info(sha1, &size);
|
|
|
|
printf("%06o %s %s %7lu\t", mode, type,
|
|
|
|
abbrev ? find_unique_abbrev(sha1, abbrev)
|
|
|
|
: sha1_to_hex(sha1),
|
|
|
|
size);
|
|
|
|
} else
|
|
|
|
printf("%06o %s %s %7c\t", mode, type,
|
|
|
|
abbrev ? find_unique_abbrev(sha1, abbrev)
|
|
|
|
: sha1_to_hex(sha1),
|
|
|
|
'-');
|
|
|
|
} else
|
|
|
|
printf("%06o %s %s\t", mode, type,
|
|
|
|
abbrev ? find_unique_abbrev(sha1, abbrev)
|
|
|
|
: sha1_to_hex(sha1));
|
|
|
|
}
|
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 <junkio@cox.net>
2005-12-24 05:39:30 +08:00
|
|
|
write_name_quoted(base + chomp_prefix, baselen - chomp_prefix,
|
|
|
|
pathname,
|
|
|
|
line_termination, stdout);
|
2005-11-28 18:30:04 +08:00
|
|
|
putchar(line_termination);
|
2005-12-02 02:35:51 +08:00
|
|
|
return retval;
|
[PATCH] Rewrite ls-tree to behave more like "/bin/ls -a"
This is a complete rewrite of ls-tree to make it behave more
like what "/bin/ls -a" does in the current working directory.
Namely, the changes are:
- Unlike the old ls-tree behaviour that used paths arguments to
restrict output (not that it worked as intended---as pointed
out in the mailing list discussion, it was quite incoherent),
this rewrite uses paths arguments to specify what to show.
- Without arguments, it implicitly uses the root level as its
sole argument ("/bin/ls -a" behaves as if "." is given
without argument).
- Without -r (recursive) flag, it shows the named blob (either
file or symlink), or the named tree and its immediate
children.
- With -r flag, it shows the named path, and recursively
descends into it if it is a tree.
- With -d flag, it shows the named path and does not show its
children even if the path is a tree, nor descends into it
recursively.
This is still request-for-comments patch. There is no mailing
list consensus that this proposed new behaviour is a good one.
The patch to t/t3100-ls-tree-restrict.sh illustrates
user-visible behaviour changes. Namely:
* "git-ls-tree $tree path1 path0" lists path1 first and then
path0. It used to use paths as an output restrictor and
showed output in cache entry order (i.e. path0 first and then
path1) regardless of the order of paths arguments.
* "git-ls-tree $tree path2" lists path2 and its immediate
children but having explicit paths argument does not imply
recursive behaviour anymore, hence paths/baz is shown but not
paths/baz/b.
Signed-off-by: Junio C Hamano <junkio@cox.net>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-05-28 15:05:38 +08:00
|
|
|
}
|
2005-04-17 04:57:39 +08:00
|
|
|
|
2006-07-29 13:44:25 +08:00
|
|
|
int cmd_ls_tree(int argc, const char **argv, const char *prefix)
|
[PATCH] Rewrite ls-tree to behave more like "/bin/ls -a"
This is a complete rewrite of ls-tree to make it behave more
like what "/bin/ls -a" does in the current working directory.
Namely, the changes are:
- Unlike the old ls-tree behaviour that used paths arguments to
restrict output (not that it worked as intended---as pointed
out in the mailing list discussion, it was quite incoherent),
this rewrite uses paths arguments to specify what to show.
- Without arguments, it implicitly uses the root level as its
sole argument ("/bin/ls -a" behaves as if "." is given
without argument).
- Without -r (recursive) flag, it shows the named blob (either
file or symlink), or the named tree and its immediate
children.
- With -r flag, it shows the named path, and recursively
descends into it if it is a tree.
- With -d flag, it shows the named path and does not show its
children even if the path is a tree, nor descends into it
recursively.
This is still request-for-comments patch. There is no mailing
list consensus that this proposed new behaviour is a good one.
The patch to t/t3100-ls-tree-restrict.sh illustrates
user-visible behaviour changes. Namely:
* "git-ls-tree $tree path1 path0" lists path1 first and then
path0. It used to use paths as an output restrictor and
showed output in cache entry order (i.e. path0 first and then
path1) regardless of the order of paths arguments.
* "git-ls-tree $tree path2" lists path2 and its immediate
children but having explicit paths argument does not imply
recursive behaviour anymore, hence paths/baz is shown but not
paths/baz/b.
Signed-off-by: Junio C Hamano <junkio@cox.net>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-05-28 15:05:38 +08:00
|
|
|
{
|
2005-04-13 17:02:34 +08:00
|
|
|
unsigned char sha1[20];
|
2006-01-26 14:13:36 +08:00
|
|
|
struct tree *tree;
|
2005-04-13 17:02:34 +08:00
|
|
|
|
2006-03-24 15:41:18 +08:00
|
|
|
git_config(git_default_config);
|
2006-07-29 13:44:25 +08:00
|
|
|
ls_tree_prefix = prefix;
|
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 <junkio@cox.net>
2005-12-24 05:39:30 +08:00
|
|
|
if (prefix && *prefix)
|
|
|
|
chomp_prefix = strlen(prefix);
|
2005-04-15 23:37:05 +08:00
|
|
|
while (1 < argc && argv[1][0] == '-') {
|
|
|
|
switch (argv[1][1]) {
|
|
|
|
case 'z':
|
|
|
|
line_termination = 0;
|
|
|
|
break;
|
|
|
|
case 'r':
|
[PATCH] Rewrite ls-tree to behave more like "/bin/ls -a"
This is a complete rewrite of ls-tree to make it behave more
like what "/bin/ls -a" does in the current working directory.
Namely, the changes are:
- Unlike the old ls-tree behaviour that used paths arguments to
restrict output (not that it worked as intended---as pointed
out in the mailing list discussion, it was quite incoherent),
this rewrite uses paths arguments to specify what to show.
- Without arguments, it implicitly uses the root level as its
sole argument ("/bin/ls -a" behaves as if "." is given
without argument).
- Without -r (recursive) flag, it shows the named blob (either
file or symlink), or the named tree and its immediate
children.
- With -r flag, it shows the named path, and recursively
descends into it if it is a tree.
- With -d flag, it shows the named path and does not show its
children even if the path is a tree, nor descends into it
recursively.
This is still request-for-comments patch. There is no mailing
list consensus that this proposed new behaviour is a good one.
The patch to t/t3100-ls-tree-restrict.sh illustrates
user-visible behaviour changes. Namely:
* "git-ls-tree $tree path1 path0" lists path1 first and then
path0. It used to use paths as an output restrictor and
showed output in cache entry order (i.e. path0 first and then
path1) regardless of the order of paths arguments.
* "git-ls-tree $tree path2" lists path2 and its immediate
children but having explicit paths argument does not imply
recursive behaviour anymore, hence paths/baz is shown but not
paths/baz/b.
Signed-off-by: Junio C Hamano <junkio@cox.net>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-05-28 15:05:38 +08:00
|
|
|
ls_options |= LS_RECURSIVE;
|
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
ls_options |= LS_TREE_ONLY;
|
2005-04-15 23:37:05 +08:00
|
|
|
break;
|
2005-12-02 02:35:51 +08:00
|
|
|
case 't':
|
|
|
|
ls_options |= LS_SHOW_TREES;
|
|
|
|
break;
|
2007-05-20 04:08:11 +08:00
|
|
|
case 'l':
|
|
|
|
ls_options |= LS_SHOW_SIZE;
|
|
|
|
break;
|
2005-12-02 06:54:00 +08:00
|
|
|
case '-':
|
|
|
|
if (!strcmp(argv[1]+2, "name-only") ||
|
|
|
|
!strcmp(argv[1]+2, "name-status")) {
|
|
|
|
ls_options |= LS_NAME_ONLY;
|
|
|
|
break;
|
|
|
|
}
|
2007-05-20 04:08:11 +08:00
|
|
|
if (!strcmp(argv[1]+2, "long")) {
|
|
|
|
ls_options |= LS_SHOW_SIZE;
|
|
|
|
break;
|
|
|
|
}
|
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 <junkio@cox.net>
2005-12-24 05:39:30 +08:00
|
|
|
if (!strcmp(argv[1]+2, "full-name")) {
|
|
|
|
chomp_prefix = 0;
|
|
|
|
break;
|
|
|
|
}
|
2007-02-20 17:55:07 +08:00
|
|
|
if (!prefixcmp(argv[1]+2, "abbrev=")) {
|
2006-03-07 21:52:02 +08:00
|
|
|
abbrev = strtoul(argv[1]+9, NULL, 10);
|
|
|
|
if (abbrev && abbrev < MINIMUM_ABBREV)
|
|
|
|
abbrev = MINIMUM_ABBREV;
|
|
|
|
else if (abbrev > 40)
|
|
|
|
abbrev = 40;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!strcmp(argv[1]+2, "abbrev")) {
|
|
|
|
abbrev = DEFAULT_ABBREV;
|
|
|
|
break;
|
|
|
|
}
|
2005-12-02 06:54:00 +08:00
|
|
|
/* otherwise fallthru */
|
2005-04-15 23:37:05 +08:00
|
|
|
default:
|
2005-04-17 04:57:39 +08:00
|
|
|
usage(ls_tree_usage);
|
2005-04-15 23:37:05 +08:00
|
|
|
}
|
|
|
|
argc--; argv++;
|
|
|
|
}
|
2005-12-02 05:15:20 +08:00
|
|
|
/* -d -r should imply -t, but -d by itself should not have to. */
|
|
|
|
if ( (LS_TREE_ONLY|LS_RECURSIVE) ==
|
|
|
|
((LS_TREE_ONLY|LS_RECURSIVE) & ls_options))
|
|
|
|
ls_options |= LS_SHOW_TREES;
|
2005-04-15 23:37:05 +08:00
|
|
|
|
2005-05-27 01:52:50 +08:00
|
|
|
if (argc < 2)
|
2005-04-17 04:57:39 +08:00
|
|
|
usage(ls_tree_usage);
|
2006-05-09 05:43:38 +08:00
|
|
|
if (get_sha1(argv[1], sha1))
|
|
|
|
die("Not a valid object name %s", argv[1]);
|
[PATCH] Rewrite ls-tree to behave more like "/bin/ls -a"
This is a complete rewrite of ls-tree to make it behave more
like what "/bin/ls -a" does in the current working directory.
Namely, the changes are:
- Unlike the old ls-tree behaviour that used paths arguments to
restrict output (not that it worked as intended---as pointed
out in the mailing list discussion, it was quite incoherent),
this rewrite uses paths arguments to specify what to show.
- Without arguments, it implicitly uses the root level as its
sole argument ("/bin/ls -a" behaves as if "." is given
without argument).
- Without -r (recursive) flag, it shows the named blob (either
file or symlink), or the named tree and its immediate
children.
- With -r flag, it shows the named path, and recursively
descends into it if it is a tree.
- With -d flag, it shows the named path and does not show its
children even if the path is a tree, nor descends into it
recursively.
This is still request-for-comments patch. There is no mailing
list consensus that this proposed new behaviour is a good one.
The patch to t/t3100-ls-tree-restrict.sh illustrates
user-visible behaviour changes. Namely:
* "git-ls-tree $tree path1 path0" lists path1 first and then
path0. It used to use paths as an output restrictor and
showed output in cache entry order (i.e. path0 first and then
path1) regardless of the order of paths arguments.
* "git-ls-tree $tree path2" lists path2 and its immediate
children but having explicit paths argument does not imply
recursive behaviour anymore, hence paths/baz is shown but not
paths/baz/b.
Signed-off-by: Junio C Hamano <junkio@cox.net>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-05-28 15:05:38 +08:00
|
|
|
|
ls-tree: further tweaks of the rewrite
It modifies the selection a bit, so that a pathspec that is a superset of
a particular tree path will always cause it to recurse into that tree.
As an example, let's say that we do
git-ls-tree HEAD drivers/char
_without_ the "-r". What will happen is that it will start out doing all
the base tree, and for "drivers" it will notice that it's a proper subset
of "drivers/char", so it will always recurse into _that_ tree (but not
into other trees).
Then, it will not match anything else than "char" in that subdirectory,
and because that's not a proper superset (it's an exact match), it will
_not_ recurse into it, so you get:
[torvalds@g5 linux]$ ~/git/git-ls-tree HEAD drivers/char
040000 tree 9568cda453aae205bb58983747fa73b9696d9d51 drivers/char
which is what you got with the old git-ls-tree too.
But interestingly, if you add the slash, it will become a proper superset
and it will recurse into _that_ subdirectory (but no deeper: so if you
want all subdirectories _below_ drivers/char/, you still need to give
"-r"):
[torvalds@g5 linux]$ ~/git/git-ls-tree HEAD drivers/char/
100644 blob 2b6b1d772ed776fff87927fc34adc2e40500218e drivers/char/.gitignore
100644 blob 56b8a2e76ab10a5c21787cb7068a846075cbaffd drivers/char/ChangeLog
100644 blob 970f70d498f4c814e1cf3362e33d7e23ac53c299 drivers/char/Kconfig
...
See? This is on top of the previous two diffs, holler if you want a whole
new "everything combined" version..
It hasn't gotten lots of testing, but it should work.
Linus
2005-11-28 14:48:08 +08:00
|
|
|
pathspec = get_pathspec(prefix, argv + 2);
|
2006-01-26 14:13:36 +08:00
|
|
|
tree = parse_tree_indirect(sha1);
|
|
|
|
if (!tree)
|
2005-11-27 01:38:20 +08:00
|
|
|
die("not a tree object");
|
2006-01-26 14:13:36 +08:00
|
|
|
read_tree_recursive(tree, "", 0, 0, pathspec, show_tree);
|
2005-11-27 01:38:20 +08:00
|
|
|
|
2005-04-13 17:02:34 +08:00
|
|
|
return 0;
|
|
|
|
}
|