git-commit-vandalism/ls-tree.c
Junio C Hamano 84a9b58c42 sha1_name: warning ambiguous refs.
This makes sure that many commands that take refs on the command
line to honor core.warnambiguousrefs configuration.  Earlier,
the commands affected by this patch did not read the
configuration file.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-03-23 23:41:18 -08:00

141 lines
3.0 KiB
C

/*
* GIT - The information manager from hell
*
* Copyright (C) Linus Torvalds, 2005
*/
#include "cache.h"
#include "blob.h"
#include "tree.h"
#include "quote.h"
static int line_termination = '\n';
#define LS_RECURSIVE 1
#define LS_TREE_ONLY 2
#define LS_SHOW_TREES 4
#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] [--full-name] <tree-ish> [path...]";
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;
}
}
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";
if (S_ISDIR(mode)) {
if (show_recursive(base, baselen, pathname)) {
retval = READ_TREE_RECURSIVE;
if (!(ls_options & LS_SHOW_TREES))
return retval;
}
type = "tree";
}
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 + chomp_prefix, baselen - chomp_prefix,
pathname,
line_termination, stdout);
putchar(line_termination);
return retval;
}
int main(int argc, const char **argv)
{
unsigned char sha1[20];
struct tree *tree;
prefix = setup_git_directory();
git_config(git_default_config);
if (prefix && *prefix)
chomp_prefix = strlen(prefix);
while (1 < argc && argv[1][0] == '-') {
switch (argv[1][1]) {
case 'z':
line_termination = 0;
break;
case 'r':
ls_options |= LS_RECURSIVE;
break;
case 'd':
ls_options |= LS_TREE_ONLY;
break;
case 't':
ls_options |= LS_SHOW_TREES;
break;
case '-':
if (!strcmp(argv[1]+2, "name-only") ||
!strcmp(argv[1]+2, "name-status")) {
ls_options |= LS_NAME_ONLY;
break;
}
if (!strcmp(argv[1]+2, "full-name")) {
chomp_prefix = 0;
break;
}
/* otherwise fallthru */
default:
usage(ls_tree_usage);
}
argc--; argv++;
}
/* -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;
if (argc < 2)
usage(ls_tree_usage);
if (get_sha1(argv[1], sha1) < 0)
usage(ls_tree_usage);
pathspec = get_pathspec(prefix, argv + 2);
tree = parse_tree_indirect(sha1);
if (!tree)
die("not a tree object");
read_tree_recursive(tree, "", 0, 0, pathspec, show_tree);
return 0;
}