2 * GIT - The information manager from hell
4 * Copyright (C) Linus Torvalds, 2005
8 static int line_termination
= '\n';
9 static int recursive
= 0;
12 struct path_prefix
*prev
;
16 #define DEBUG(fmt, ...)
18 static int string_path_prefix(char *buff
, size_t blen
, struct path_prefix
*prefix
)
23 len
= string_path_prefix(buff
,blen
,prefix
->prev
);
33 strncpy(buff
,prefix
->name
,blen
);
34 return len
+ strlen(prefix
->name
);
40 static void print_path_prefix(struct path_prefix
*prefix
)
44 print_path_prefix(prefix
->prev
);
47 fputs(prefix
->name
, stdout
);
53 * -1 if prefix is *not* a subset of path
55 * 1 if prefix is a subset of path
57 static int pathcmp(const char *path
, struct path_prefix
*prefix
)
65 len
= string_path_prefix(buff
, sizeof buff
, prefix
);
71 if (strncmp(path
,buff
,len
) == 0) {
82 * match may be NULL, or a *sorted* list of paths
84 static void list_recursive(void *buffer
,
87 struct path_prefix
*prefix
,
88 char **match
, int matches
)
90 struct path_prefix this_prefix
;
91 this_prefix
.prev
= prefix
;
93 if (strcmp(type
, "tree"))
94 die("expected a 'tree' node");
100 int namelen
= strlen(buffer
)+1;
103 unsigned long eltsize
;
104 unsigned char *sha1
= buffer
+ namelen
;
105 char *path
= strchr(buffer
, ' ') + 1;
107 const char *matched
= NULL
;
111 if (size
< namelen
+ 20 || sscanf(buffer
, "%o", &mode
) != 1)
112 die("corrupt 'tree' file");
114 size
-= namelen
+ 20;
116 this_prefix
.name
= path
;
117 for ( mindex
= 0; mindex
< matches
; mindex
++) {
118 mtype
= pathcmp(match
[mindex
],&this_prefix
);
120 matched
= match
[mindex
];
126 * If we're not matching, or if this is an exact match,
129 if (!matches
|| (matched
!= NULL
&& mtype
== 0)) {
130 printf("%06o %s %s\t", mode
,
131 S_ISDIR(mode
) ? "tree" : "blob",
133 print_path_prefix(&this_prefix
);
134 putchar(line_termination
);
137 if (! recursive
|| ! S_ISDIR(mode
))
140 if (matches
&& ! matched
)
143 if (! (eltbuf
= read_sha1_file(sha1
, elttype
, &eltsize
)) ) {
144 error("cannot read %s", sha1_to_hex(sha1
));
148 /* If this is an exact directory match, we may have
149 * directory files following this path. Match on them.
150 * Otherwise, we're at a pach subcomponent, and we need
151 * to try to match again.
156 list_recursive(eltbuf
, elttype
, eltsize
, &this_prefix
, &match
[mindex
], matches
-mindex
);
161 static int qcmp(const void *a
, const void *b
)
163 return strcmp(*(char **)a
, *(char **)b
);
166 static int list(unsigned char *sha1
,char **path
)
172 for (npaths
= 0; path
[npaths
] != NULL
; npaths
++)
175 qsort(path
,npaths
,sizeof(char *),qcmp
);
177 buffer
= read_object_with_reference(sha1
, "tree", &size
, NULL
);
179 die("unable to read sha1 file");
180 list_recursive(buffer
, "tree", size
, NULL
, path
, npaths
);
185 static const char *ls_tree_usage
= "git-ls-tree [-r] [-z] <key> [paths...]";
187 int main(int argc
, char **argv
)
189 unsigned char sha1
[20];
191 while (1 < argc
&& argv
[1][0] == '-') {
192 switch (argv
[1][1]) {
194 line_termination
= 0;
200 usage(ls_tree_usage
);
206 usage(ls_tree_usage
);
207 if (get_sha1(argv
[1], sha1
) < 0)
208 usage(ls_tree_usage
);
209 if (list(sha1
, &argv
[2]) < 0)