Petr Baudis | 7912c07 | 2005-04-13 02:02:34 -0700 | [diff] [blame] | 1 | /* |
| 2 | * GIT - The information manager from hell |
| 3 | * |
| 4 | * Copyright (C) Linus Torvalds, 2005 |
| 5 | */ |
| 6 | #include "cache.h" |
Junio C Hamano | 6af1f01 | 2005-05-28 00:05:38 -0700 | [diff] [blame] | 7 | #include "blob.h" |
| 8 | #include "tree.h" |
Linus Torvalds | f35a6d3 | 2007-04-09 21:20:29 -0700 | [diff] [blame] | 9 | #include "commit.h" |
Junio C Hamano | 22ddf71 | 2005-10-14 21:56:46 -0700 | [diff] [blame] | 10 | #include "quote.h" |
Peter Eriksen | aae01bd | 2006-05-23 14:15:30 +0200 | [diff] [blame] | 11 | #include "builtin.h" |
Petr Baudis | 7912c07 | 2005-04-13 02:02:34 -0700 | [diff] [blame] | 12 | |
Linus Torvalds | e99d59f | 2005-05-20 11:46:10 -0700 | [diff] [blame] | 13 | static int line_termination = '\n'; |
Junio C Hamano | 6af1f01 | 2005-05-28 00:05:38 -0700 | [diff] [blame] | 14 | #define LS_RECURSIVE 1 |
| 15 | #define LS_TREE_ONLY 2 |
Linus Torvalds | 0f8f45c | 2005-12-01 10:35:51 -0800 | [diff] [blame] | 16 | #define LS_SHOW_TREES 4 |
Junio C Hamano | c639a55 | 2005-12-01 14:54:00 -0800 | [diff] [blame] | 17 | #define LS_NAME_ONLY 8 |
Jakub Narebski | a5bbda8 | 2007-05-19 22:08:11 +0200 | [diff] [blame] | 18 | #define LS_SHOW_SIZE 16 |
David Rientjes | 96f1e58 | 2006-08-15 10:23:48 -0700 | [diff] [blame] | 19 | static int abbrev; |
| 20 | static int ls_options; |
Peter Eriksen | aae01bd | 2006-05-23 14:15:30 +0200 | [diff] [blame] | 21 | static const char **pathspec; |
David Rientjes | 96f1e58 | 2006-08-15 10:23:48 -0700 | [diff] [blame] | 22 | static int chomp_prefix; |
Linus Torvalds | a633fca | 2006-07-28 22:44:25 -0700 | [diff] [blame] | 23 | static const char *ls_tree_prefix; |
Junio C Hamano | aa1c48d | 2005-04-15 08:37:05 -0700 | [diff] [blame] | 24 | |
Petr Baudis | 4d1f119 | 2005-07-29 11:01:26 +0200 | [diff] [blame] | 25 | static const char ls_tree_usage[] = |
Jakub Narebski | a5bbda8 | 2007-05-19 22:08:11 +0200 | [diff] [blame] | 26 | "git-ls-tree [-d] [-r] [-t] [-l] [-z] [--name-only] [--name-status] [--full-name] [--abbrev[=<n>]] <tree-ish> [path...]"; |
Linus Torvalds | 0f8f45c | 2005-12-01 10:35:51 -0800 | [diff] [blame] | 27 | |
| 28 | static int show_recursive(const char *base, int baselen, const char *pathname) |
| 29 | { |
| 30 | const char **s; |
| 31 | |
| 32 | if (ls_options & LS_RECURSIVE) |
| 33 | return 1; |
| 34 | |
| 35 | s = pathspec; |
| 36 | if (!s) |
| 37 | return 0; |
| 38 | |
| 39 | for (;;) { |
| 40 | const char *spec = *s++; |
| 41 | int len, speclen; |
| 42 | |
| 43 | if (!spec) |
| 44 | return 0; |
| 45 | if (strncmp(base, spec, baselen)) |
| 46 | continue; |
| 47 | len = strlen(pathname); |
| 48 | spec += baselen; |
| 49 | speclen = strlen(spec); |
| 50 | if (speclen <= len) |
| 51 | continue; |
| 52 | if (memcmp(pathname, spec, len)) |
| 53 | continue; |
| 54 | return 1; |
| 55 | } |
| 56 | } |
Junio C Hamano | aa1c48d | 2005-04-15 08:37:05 -0700 | [diff] [blame] | 57 | |
Linus Torvalds | 097dc3d | 2006-05-28 15:13:53 -0700 | [diff] [blame] | 58 | static int show_tree(const unsigned char *sha1, const char *base, int baselen, |
Junio C Hamano | a69dd58 | 2005-12-23 13:39:30 -0800 | [diff] [blame] | 59 | const char *pathname, unsigned mode, int stage) |
Petr Baudis | 7912c07 | 2005-04-13 02:02:34 -0700 | [diff] [blame] | 60 | { |
Linus Torvalds | 0f8f45c | 2005-12-01 10:35:51 -0800 | [diff] [blame] | 61 | int retval = 0; |
Peter Eriksen | 8e44025 | 2006-04-02 14:44:09 +0200 | [diff] [blame] | 62 | const char *type = blob_type; |
Jakub Narebski | a5bbda8 | 2007-05-19 22:08:11 +0200 | [diff] [blame] | 63 | unsigned long size; |
Petr Baudis | 7912c07 | 2005-04-13 02:02:34 -0700 | [diff] [blame] | 64 | |
Martin Waitz | 302b928 | 2007-05-21 22:08:28 +0200 | [diff] [blame] | 65 | if (S_ISGITLINK(mode)) { |
Linus Torvalds | f35a6d3 | 2007-04-09 21:20:29 -0700 | [diff] [blame] | 66 | /* |
| 67 | * Maybe we want to have some recursive version here? |
| 68 | * |
| 69 | * Something like: |
| 70 | * |
| 71 | if (show_subprojects(base, baselen, pathname)) { |
| 72 | if (fork()) { |
| 73 | chdir(base); |
| 74 | exec ls-tree; |
| 75 | } |
| 76 | waitpid(); |
| 77 | } |
| 78 | * |
| 79 | * ..or similar.. |
| 80 | */ |
| 81 | type = commit_type; |
| 82 | } else if (S_ISDIR(mode)) { |
Linus Torvalds | 0f8f45c | 2005-12-01 10:35:51 -0800 | [diff] [blame] | 83 | if (show_recursive(base, baselen, pathname)) { |
| 84 | retval = READ_TREE_RECURSIVE; |
| 85 | if (!(ls_options & LS_SHOW_TREES)) |
| 86 | return retval; |
Linus Torvalds | e246637 | 2005-11-27 22:48:08 -0800 | [diff] [blame] | 87 | } |
Peter Eriksen | 8e44025 | 2006-04-02 14:44:09 +0200 | [diff] [blame] | 88 | type = tree_type; |
Linus Torvalds | 3c5e846 | 2005-11-26 09:38:20 -0800 | [diff] [blame] | 89 | } |
Junio C Hamano | f598467 | 2005-12-01 13:15:20 -0800 | [diff] [blame] | 90 | else if (ls_options & LS_TREE_ONLY) |
| 91 | return 0; |
Linus Torvalds | 3c5e846 | 2005-11-26 09:38:20 -0800 | [diff] [blame] | 92 | |
Junio C Hamano | a69dd58 | 2005-12-23 13:39:30 -0800 | [diff] [blame] | 93 | if (chomp_prefix && |
Linus Torvalds | a633fca | 2006-07-28 22:44:25 -0700 | [diff] [blame] | 94 | (baselen < chomp_prefix || memcmp(ls_tree_prefix, base, chomp_prefix))) |
Junio C Hamano | a69dd58 | 2005-12-23 13:39:30 -0800 | [diff] [blame] | 95 | return 0; |
| 96 | |
Jakub Narebski | a5bbda8 | 2007-05-19 22:08:11 +0200 | [diff] [blame] | 97 | if (!(ls_options & LS_NAME_ONLY)) { |
| 98 | if (ls_options & LS_SHOW_SIZE) { |
| 99 | if (!strcmp(type, blob_type)) { |
| 100 | sha1_object_info(sha1, &size); |
| 101 | printf("%06o %s %s %7lu\t", mode, type, |
| 102 | abbrev ? find_unique_abbrev(sha1, abbrev) |
| 103 | : sha1_to_hex(sha1), |
| 104 | size); |
| 105 | } else |
| 106 | printf("%06o %s %s %7c\t", mode, type, |
| 107 | abbrev ? find_unique_abbrev(sha1, abbrev) |
| 108 | : sha1_to_hex(sha1), |
| 109 | '-'); |
| 110 | } else |
| 111 | printf("%06o %s %s\t", mode, type, |
| 112 | abbrev ? find_unique_abbrev(sha1, abbrev) |
| 113 | : sha1_to_hex(sha1)); |
| 114 | } |
Pierre Habouzit | 663af34 | 2007-09-20 00:42:15 +0200 | [diff] [blame] | 115 | write_name_quotedpfx(base + chomp_prefix, baselen - chomp_prefix, |
| 116 | pathname, stdout, line_termination); |
Linus Torvalds | 0f8f45c | 2005-12-01 10:35:51 -0800 | [diff] [blame] | 117 | return retval; |
Linus Torvalds | 3c5e846 | 2005-11-26 09:38:20 -0800 | [diff] [blame] | 118 | } |
| 119 | |
Linus Torvalds | a633fca | 2006-07-28 22:44:25 -0700 | [diff] [blame] | 120 | int cmd_ls_tree(int argc, const char **argv, const char *prefix) |
Linus Torvalds | 3c5e846 | 2005-11-26 09:38:20 -0800 | [diff] [blame] | 121 | { |
Linus Torvalds | 3c5e846 | 2005-11-26 09:38:20 -0800 | [diff] [blame] | 122 | unsigned char sha1[20]; |
Daniel Barkalow | 521698b | 2006-01-26 01:13:36 -0500 | [diff] [blame] | 123 | struct tree *tree; |
Linus Torvalds | 3c5e846 | 2005-11-26 09:38:20 -0800 | [diff] [blame] | 124 | |
Junio C Hamano | 84a9b58 | 2006-03-23 23:41:18 -0800 | [diff] [blame] | 125 | git_config(git_default_config); |
Linus Torvalds | a633fca | 2006-07-28 22:44:25 -0700 | [diff] [blame] | 126 | ls_tree_prefix = prefix; |
Junio C Hamano | a69dd58 | 2005-12-23 13:39:30 -0800 | [diff] [blame] | 127 | if (prefix && *prefix) |
| 128 | chomp_prefix = strlen(prefix); |
Junio C Hamano | aa1c48d | 2005-04-15 08:37:05 -0700 | [diff] [blame] | 129 | while (1 < argc && argv[1][0] == '-') { |
| 130 | switch (argv[1][1]) { |
| 131 | case 'z': |
| 132 | line_termination = 0; |
| 133 | break; |
| 134 | case 'r': |
Junio C Hamano | 6af1f01 | 2005-05-28 00:05:38 -0700 | [diff] [blame] | 135 | ls_options |= LS_RECURSIVE; |
| 136 | break; |
| 137 | case 'd': |
| 138 | ls_options |= LS_TREE_ONLY; |
Junio C Hamano | aa1c48d | 2005-04-15 08:37:05 -0700 | [diff] [blame] | 139 | break; |
Linus Torvalds | 0f8f45c | 2005-12-01 10:35:51 -0800 | [diff] [blame] | 140 | case 't': |
| 141 | ls_options |= LS_SHOW_TREES; |
| 142 | break; |
Jakub Narebski | a5bbda8 | 2007-05-19 22:08:11 +0200 | [diff] [blame] | 143 | case 'l': |
| 144 | ls_options |= LS_SHOW_SIZE; |
| 145 | break; |
Junio C Hamano | c639a55 | 2005-12-01 14:54:00 -0800 | [diff] [blame] | 146 | case '-': |
| 147 | if (!strcmp(argv[1]+2, "name-only") || |
| 148 | !strcmp(argv[1]+2, "name-status")) { |
| 149 | ls_options |= LS_NAME_ONLY; |
| 150 | break; |
| 151 | } |
Jakub Narebski | a5bbda8 | 2007-05-19 22:08:11 +0200 | [diff] [blame] | 152 | if (!strcmp(argv[1]+2, "long")) { |
| 153 | ls_options |= LS_SHOW_SIZE; |
| 154 | break; |
| 155 | } |
Junio C Hamano | a69dd58 | 2005-12-23 13:39:30 -0800 | [diff] [blame] | 156 | if (!strcmp(argv[1]+2, "full-name")) { |
| 157 | chomp_prefix = 0; |
| 158 | break; |
| 159 | } |
Junio C Hamano | 1968d77 | 2007-02-20 01:55:07 -0800 | [diff] [blame] | 160 | if (!prefixcmp(argv[1]+2, "abbrev=")) { |
Eric Wong | cb85bfe | 2006-03-07 05:52:02 -0800 | [diff] [blame] | 161 | abbrev = strtoul(argv[1]+9, NULL, 10); |
| 162 | if (abbrev && abbrev < MINIMUM_ABBREV) |
| 163 | abbrev = MINIMUM_ABBREV; |
| 164 | else if (abbrev > 40) |
| 165 | abbrev = 40; |
| 166 | break; |
| 167 | } |
| 168 | if (!strcmp(argv[1]+2, "abbrev")) { |
| 169 | abbrev = DEFAULT_ABBREV; |
| 170 | break; |
| 171 | } |
Junio C Hamano | c639a55 | 2005-12-01 14:54:00 -0800 | [diff] [blame] | 172 | /* otherwise fallthru */ |
Junio C Hamano | aa1c48d | 2005-04-15 08:37:05 -0700 | [diff] [blame] | 173 | default: |
Junio C Hamano | 0f2303f | 2005-04-16 13:57:39 -0700 | [diff] [blame] | 174 | usage(ls_tree_usage); |
Junio C Hamano | aa1c48d | 2005-04-15 08:37:05 -0700 | [diff] [blame] | 175 | } |
| 176 | argc--; argv++; |
| 177 | } |
Junio C Hamano | f598467 | 2005-12-01 13:15:20 -0800 | [diff] [blame] | 178 | /* -d -r should imply -t, but -d by itself should not have to. */ |
| 179 | if ( (LS_TREE_ONLY|LS_RECURSIVE) == |
| 180 | ((LS_TREE_ONLY|LS_RECURSIVE) & ls_options)) |
| 181 | ls_options |= LS_SHOW_TREES; |
Junio C Hamano | aa1c48d | 2005-04-15 08:37:05 -0700 | [diff] [blame] | 182 | |
Jason McMullan | 6d3a507 | 2005-05-26 10:52:50 -0700 | [diff] [blame] | 183 | if (argc < 2) |
Junio C Hamano | 0f2303f | 2005-04-16 13:57:39 -0700 | [diff] [blame] | 184 | usage(ls_tree_usage); |
Dmitry V. Levin | 31fff30 | 2006-05-09 01:43:38 +0400 | [diff] [blame] | 185 | if (get_sha1(argv[1], sha1)) |
| 186 | die("Not a valid object name %s", argv[1]); |
Junio C Hamano | 6af1f01 | 2005-05-28 00:05:38 -0700 | [diff] [blame] | 187 | |
Linus Torvalds | e246637 | 2005-11-27 22:48:08 -0800 | [diff] [blame] | 188 | pathspec = get_pathspec(prefix, argv + 2); |
Daniel Barkalow | 521698b | 2006-01-26 01:13:36 -0500 | [diff] [blame] | 189 | tree = parse_tree_indirect(sha1); |
| 190 | if (!tree) |
Linus Torvalds | 3c5e846 | 2005-11-26 09:38:20 -0800 | [diff] [blame] | 191 | die("not a tree object"); |
Daniel Barkalow | 521698b | 2006-01-26 01:13:36 -0500 | [diff] [blame] | 192 | read_tree_recursive(tree, "", 0, 0, pathspec, show_tree); |
Linus Torvalds | 3c5e846 | 2005-11-26 09:38:20 -0800 | [diff] [blame] | 193 | |
Petr Baudis | 7912c07 | 2005-04-13 02:02:34 -0700 | [diff] [blame] | 194 | return 0; |
| 195 | } |