2005-04-13 11:02:34 +02: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 09:05:38 +02:00
|
|
|
#include "blob.h"
|
|
|
|
#include "tree.h"
|
2007-04-10 06:20:29 +02:00
|
|
|
#include "commit.h"
|
2005-10-15 06:56:46 +02:00
|
|
|
#include "quote.h"
|
2006-05-23 14:15:30 +02:00
|
|
|
#include "builtin.h"
|
2005-04-13 11:02:34 +02:00
|
|
|
|
2005-05-20 20:46:10 +02: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 09:05:38 +02:00
|
|
|
#define LS_RECURSIVE 1
|
|
|
|
#define LS_TREE_ONLY 2
|
2005-12-01 19:35:51 +01:00
|
|
|
#define LS_SHOW_TREES 4
|
2005-12-01 23:54:00 +01:00
|
|
|
#define LS_NAME_ONLY 8
|
2007-05-19 22:08:11 +02:00
|
|
|
#define LS_SHOW_SIZE 16
|
2006-08-15 19:23:48 +02:00
|
|
|
static int abbrev;
|
|
|
|
static int ls_options;
|
2006-05-23 14:15:30 +02:00
|
|
|
static const char **pathspec;
|
2006-08-15 19:23:48 +02:00
|
|
|
static int chomp_prefix;
|
2006-07-29 07:44:25 +02:00
|
|
|
static const char *ls_tree_prefix;
|
2005-04-15 17:37:05 +02:00
|
|
|
|
2005-11-26 18:38:20 +01:00
|
|
|
static const char ls_tree_usage[] =
|
2007-05-19 22:08:11 +02:00
|
|
|
"git-ls-tree [-d] [-r] [-t] [-l] [-z] [--name-only] [--name-status] [--full-name] [--abbrev[=<n>]] <tree-ish> [path...]";
|
2005-12-01 19:35:51 +01: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 17:37:05 +02:00
|
|
|
|
2006-05-29 00:13:53 +02:00
|
|
|
static int show_tree(const unsigned char *sha1, const char *base, int baselen,
|
2008-07-14 21:22:12 +02:00
|
|
|
const char *pathname, unsigned mode, int stage, void *context)
|
[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 09:05:38 +02:00
|
|
|
{
|
2005-12-01 19:35:51 +01:00
|
|
|
int retval = 0;
|
2006-04-02 14:44:09 +02:00
|
|
|
const char *type = blob_type;
|
2007-05-19 22:08:11 +02:00
|
|
|
unsigned long size;
|
2005-10-08 01:54:06 +02:00
|
|
|
|
2007-05-21 22:08:28 +02:00
|
|
|
if (S_ISGITLINK(mode)) {
|
2007-04-10 06:20:29 +02: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-01 19:35:51 +01: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 07:48:08 +01:00
|
|
|
}
|
2006-04-02 14:44:09 +02: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 09:05:38 +02:00
|
|
|
}
|
2005-12-01 22:15:20 +01:00
|
|
|
else if (ls_options & LS_TREE_ONLY)
|
|
|
|
return 0;
|
2005-10-08 01:54:06 +02: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-23 22:39:30 +01:00
|
|
|
if (chomp_prefix &&
|
2006-07-29 07:44:25 +02: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-23 22:39:30 +01:00
|
|
|
return 0;
|
|
|
|
|
2007-05-19 22:08:11 +02: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));
|
|
|
|
}
|
Full rework of quote_c_style and write_name_quoted.
* quote_c_style works on a strbuf instead of a wild buffer.
* quote_c_style is now clever enough to not add double quotes if not needed.
* write_name_quoted inherits those advantages, but also take a different
set of arguments. Now instead of asking for quotes or not, you pass a
"terminator". If it's \0 then we assume you don't want to escape, else C
escaping is performed. In any case, the terminator is also appended to the
stream. It also no longer takes the prefix/prefix_len arguments, as it's
seldomly used, and makes some optimizations harder.
* write_name_quotedpfx is created to work like write_name_quoted and take
the prefix/prefix_len arguments.
Thanks to those API changes, diff.c has somehow lost weight, thanks to the
removal of functions that were wrappers around the old write_name_quoted
trying to give it a semantics like the new one, but performing a lot of
allocations for this goal. Now we always write directly to the stream, no
intermediate allocation is performed.
As a side effect of the refactor in builtin-apply.c, the length of the bar
graphs in diffstats are not affected anymore by the fact that the path was
clipped.
Signed-off-by: Pierre Habouzit <madcoder@debian.org>
2007-09-20 00:42:15 +02:00
|
|
|
write_name_quotedpfx(base + chomp_prefix, baselen - chomp_prefix,
|
|
|
|
pathname, stdout, line_termination);
|
2005-12-01 19:35:51 +01: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 09:05:38 +02:00
|
|
|
}
|
2005-04-16 22:57:39 +02:00
|
|
|
|
2006-07-29 07:44:25 +02: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 09:05:38 +02:00
|
|
|
{
|
2005-04-13 11:02:34 +02:00
|
|
|
unsigned char sha1[20];
|
2006-01-26 07:13:36 +01:00
|
|
|
struct tree *tree;
|
2005-04-13 11:02:34 +02:00
|
|
|
|
2008-05-14 19:46:53 +02:00
|
|
|
git_config(git_default_config, NULL);
|
2006-07-29 07:44:25 +02: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-23 22:39:30 +01:00
|
|
|
if (prefix && *prefix)
|
|
|
|
chomp_prefix = strlen(prefix);
|
2005-04-15 17:37:05 +02: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 09:05:38 +02:00
|
|
|
ls_options |= LS_RECURSIVE;
|
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
ls_options |= LS_TREE_ONLY;
|
2005-04-15 17:37:05 +02:00
|
|
|
break;
|
2005-12-01 19:35:51 +01:00
|
|
|
case 't':
|
|
|
|
ls_options |= LS_SHOW_TREES;
|
|
|
|
break;
|
2007-05-19 22:08:11 +02:00
|
|
|
case 'l':
|
|
|
|
ls_options |= LS_SHOW_SIZE;
|
|
|
|
break;
|
2005-12-01 23:54:00 +01:00
|
|
|
case '-':
|
|
|
|
if (!strcmp(argv[1]+2, "name-only") ||
|
|
|
|
!strcmp(argv[1]+2, "name-status")) {
|
|
|
|
ls_options |= LS_NAME_ONLY;
|
|
|
|
break;
|
|
|
|
}
|
2007-05-19 22:08:11 +02: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-23 22:39:30 +01:00
|
|
|
if (!strcmp(argv[1]+2, "full-name")) {
|
|
|
|
chomp_prefix = 0;
|
|
|
|
break;
|
|
|
|
}
|
2007-02-20 10:55:07 +01:00
|
|
|
if (!prefixcmp(argv[1]+2, "abbrev=")) {
|
2006-03-07 14:52:02 +01: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-01 23:54:00 +01:00
|
|
|
/* otherwise fallthru */
|
2005-04-15 17:37:05 +02:00
|
|
|
default:
|
2005-04-16 22:57:39 +02:00
|
|
|
usage(ls_tree_usage);
|
2005-04-15 17:37:05 +02:00
|
|
|
}
|
|
|
|
argc--; argv++;
|
|
|
|
}
|
2005-12-01 22:15:20 +01: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 17:37:05 +02:00
|
|
|
|
2005-05-26 19:52:50 +02:00
|
|
|
if (argc < 2)
|
2005-04-16 22:57:39 +02:00
|
|
|
usage(ls_tree_usage);
|
2006-05-08 23:43:38 +02: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 09:05:38 +02: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 07:48:08 +01:00
|
|
|
pathspec = get_pathspec(prefix, argv + 2);
|
2006-01-26 07:13:36 +01:00
|
|
|
tree = parse_tree_indirect(sha1);
|
|
|
|
if (!tree)
|
2005-11-26 18:38:20 +01:00
|
|
|
die("not a tree object");
|
2008-07-14 21:22:12 +02:00
|
|
|
read_tree_recursive(tree, "", 0, 0, pathspec, show_tree, NULL);
|
2005-11-26 18:38:20 +01:00
|
|
|
|
2005-04-13 11:02:34 +02:00
|
|
|
return 0;
|
|
|
|
}
|