]>
Commit | Line | Data |
---|---|---|
5e3f94df | 1 | #include "git-compat-util.h" |
af3785dc | 2 | #include "cache-tree.h" |
41771fa4 | 3 | #include "hex.h" |
175785e5 | 4 | #include "tree.h" |
dabab1d6 | 5 | #include "object-name.h" |
a034e910 | 6 | #include "object-store-ll.h" |
175785e5 | 7 | #include "blob.h" |
77675e2a DB |
8 | #include "commit.h" |
9 | #include "tag.h" | |
14ba97f8 | 10 | #include "alloc.h" |
136f2e54 | 11 | #include "tree-walk.h" |
109cd76d | 12 | #include "repository.h" |
1ee7a5c3 | 13 | #include "environment.h" |
175785e5 DB |
14 | |
15 | const char *tree_type = "tree"; | |
16 | ||
6c9fc42e ÆAB |
17 | int read_tree_at(struct repository *r, |
18 | struct tree *tree, struct strbuf *base, | |
1ee7a5c3 | 19 | int depth, |
6c9fc42e ÆAB |
20 | const struct pathspec *pathspec, |
21 | read_tree_fn_t fn, void *context) | |
94537c78 | 22 | { |
0790a42a | 23 | struct tree_desc desc; |
4c068a98 | 24 | struct name_entry entry; |
f26efc58 | 25 | struct object_id oid; |
d688cf07 NTND |
26 | int len, oldlen = base->len; |
27 | enum interesting retval = entry_not_interesting; | |
0790a42a | 28 | |
1ee7a5c3 JK |
29 | if (depth > max_allowed_tree_depth) |
30 | return error("exceeded maximum allowed tree depth"); | |
31 | ||
521698b1 DB |
32 | if (parse_tree(tree)) |
33 | return -1; | |
0790a42a | 34 | |
6fda5e51 | 35 | init_tree_desc(&desc, tree->buffer, tree->size); |
0790a42a | 36 | |
4c068a98 | 37 | while (tree_entry(&desc, &entry)) { |
d688cf07 | 38 | if (retval != all_entries_interesting) { |
67022e02 | 39 | retval = tree_entry_interesting(r->index, &entry, |
0ad927e9 | 40 | base, pathspec); |
d688cf07 | 41 | if (retval == all_entries_not_interesting) |
ffd31f66 | 42 | break; |
d688cf07 | 43 | if (retval == entry_not_interesting) |
ffd31f66 NTND |
44 | continue; |
45 | } | |
0ca14a57 | 46 | |
ea82b2a0 | 47 | switch (fn(&entry.oid, base, |
47957485 | 48 | entry.path, entry.mode, context)) { |
3c5e8468 LT |
49 | case 0: |
50 | continue; | |
51 | case READ_TREE_RECURSIVE: | |
ba19a808 | 52 | break; |
3c5e8468 LT |
53 | default: |
54 | return -1; | |
55 | } | |
d3bee161 | 56 | |
ffd31f66 | 57 | if (S_ISDIR(entry.mode)) |
ea82b2a0 | 58 | oidcpy(&oid, &entry.oid); |
ffd31f66 NTND |
59 | else if (S_ISGITLINK(entry.mode)) { |
60 | struct commit *commit; | |
d3bee161 | 61 | |
371820d5 | 62 | commit = lookup_commit(r, &entry.oid); |
d3bee161 | 63 | if (!commit) |
ffd31f66 | 64 | die("Commit %s in submodule path %s%s not found", |
ea82b2a0 | 65 | oid_to_hex(&entry.oid), |
ffd31f66 | 66 | base->buf, entry.path); |
d3bee161 | 67 | |
4a93b899 | 68 | if (repo_parse_commit(r, commit)) |
ffd31f66 | 69 | die("Invalid commit %s in submodule path %s%s", |
ea82b2a0 | 70 | oid_to_hex(&entry.oid), |
ffd31f66 NTND |
71 | base->buf, entry.path); |
72 | ||
2e27bd77 | 73 | oidcpy(&oid, get_commit_tree_oid(commit)); |
94537c78 | 74 | } |
ffd31f66 NTND |
75 | else |
76 | continue; | |
77 | ||
0de16337 | 78 | len = tree_entry_len(&entry); |
ffd31f66 NTND |
79 | strbuf_add(base, entry.path, len); |
80 | strbuf_addch(base, '/'); | |
6c9fc42e | 81 | retval = read_tree_at(r, lookup_tree(r, &oid), |
1ee7a5c3 | 82 | base, depth + 1, pathspec, |
6c9fc42e | 83 | fn, context); |
ffd31f66 NTND |
84 | strbuf_setlen(base, oldlen); |
85 | if (retval) | |
86 | return -1; | |
94537c78 LT |
87 | } |
88 | return 0; | |
89 | } | |
90 | ||
47957485 ÆAB |
91 | int read_tree(struct repository *r, |
92 | struct tree *tree, | |
93 | const struct pathspec *pathspec, | |
94 | read_tree_fn_t fn, void *context) | |
ffd31f66 NTND |
95 | { |
96 | struct strbuf sb = STRBUF_INIT; | |
1ee7a5c3 | 97 | int ret = read_tree_at(r, tree, &sb, 0, pathspec, fn, context); |
ffd31f66 | 98 | strbuf_release(&sb); |
ffd31f66 NTND |
99 | return ret; |
100 | } | |
101 | ||
53dca334 EN |
102 | int base_name_compare(const char *name1, size_t len1, int mode1, |
103 | const char *name2, size_t len2, int mode2) | |
104 | { | |
105 | unsigned char c1, c2; | |
106 | size_t len = len1 < len2 ? len1 : len2; | |
107 | int cmp; | |
108 | ||
109 | cmp = memcmp(name1, name2, len); | |
110 | if (cmp) | |
111 | return cmp; | |
112 | c1 = name1[len]; | |
113 | c2 = name2[len]; | |
114 | if (!c1 && S_ISDIR(mode1)) | |
115 | c1 = '/'; | |
116 | if (!c2 && S_ISDIR(mode2)) | |
117 | c2 = '/'; | |
118 | return (c1 < c2) ? -1 : (c1 > c2) ? 1 : 0; | |
119 | } | |
120 | ||
121 | /* | |
122 | * df_name_compare() is identical to base_name_compare(), except it | |
123 | * compares conflicting directory/file entries as equal. Note that | |
124 | * while a directory name compares as equal to a regular file, they | |
125 | * then individually compare _differently_ to a filename that has | |
126 | * a dot after the basename (because '\0' < '.' < '/'). | |
127 | * | |
128 | * This is used by routines that want to traverse the git namespace | |
129 | * but then handle conflicting entries together when possible. | |
130 | */ | |
131 | int df_name_compare(const char *name1, size_t len1, int mode1, | |
132 | const char *name2, size_t len2, int mode2) | |
133 | { | |
134 | unsigned char c1, c2; | |
135 | size_t len = len1 < len2 ? len1 : len2; | |
136 | int cmp; | |
137 | ||
138 | cmp = memcmp(name1, name2, len); | |
139 | if (cmp) | |
140 | return cmp; | |
141 | /* Directories and files compare equal (same length, same name) */ | |
142 | if (len1 == len2) | |
143 | return 0; | |
144 | c1 = name1[len]; | |
145 | if (!c1 && S_ISDIR(mode1)) | |
146 | c1 = '/'; | |
147 | c2 = name2[len]; | |
148 | if (!c2 && S_ISDIR(mode2)) | |
149 | c2 = '/'; | |
150 | if (c1 == '/' && !c2) | |
151 | return 0; | |
152 | if (c2 == '/' && !c1) | |
153 | return 0; | |
154 | return c1 - c2; | |
155 | } | |
156 | ||
157 | int name_compare(const char *name1, size_t len1, const char *name2, size_t len2) | |
158 | { | |
159 | size_t min_len = (len1 < len2) ? len1 : len2; | |
160 | int cmp = memcmp(name1, name2, min_len); | |
161 | if (cmp) | |
162 | return cmp; | |
163 | if (len1 < len2) | |
164 | return -1; | |
165 | if (len1 > len2) | |
166 | return 1; | |
167 | return 0; | |
168 | } | |
169 | ||
f58a6cb6 | 170 | struct tree *lookup_tree(struct repository *r, const struct object_id *oid) |
175785e5 | 171 | { |
d0229abd | 172 | struct object *obj = lookup_object(r, oid); |
100c5f3b | 173 | if (!obj) |
a378509e | 174 | return create_object(r, oid, alloc_tree_node(r)); |
6da43d93 | 175 | return object_as_type(obj, OBJ_TREE, 0); |
175785e5 DB |
176 | } |
177 | ||
2d9c58c6 LT |
178 | int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size) |
179 | { | |
175785e5 DB |
180 | if (item->object.parsed) |
181 | return 0; | |
182 | item->object.parsed = 1; | |
136f2e54 LT |
183 | item->buffer = buffer; |
184 | item->size = size; | |
185 | ||
2d9c58c6 LT |
186 | return 0; |
187 | } | |
188 | ||
9cc2b07a | 189 | int parse_tree_gently(struct tree *item, int quiet_on_missing) |
bd2c39f5 | 190 | { |
21666f1a | 191 | enum object_type type; |
bd2c39f5 NP |
192 | void *buffer; |
193 | unsigned long size; | |
bd2c39f5 NP |
194 | |
195 | if (item->object.parsed) | |
196 | return 0; | |
bc726bd0 ÆAB |
197 | buffer = repo_read_object_file(the_repository, &item->object.oid, |
198 | &type, &size); | |
bd2c39f5 | 199 | if (!buffer) |
9cc2b07a JK |
200 | return quiet_on_missing ? -1 : |
201 | error("Could not read %s", | |
f2fd0760 | 202 | oid_to_hex(&item->object.oid)); |
21666f1a | 203 | if (type != OBJ_TREE) { |
bd2c39f5 NP |
204 | free(buffer); |
205 | return error("Object %s not a tree", | |
f2fd0760 | 206 | oid_to_hex(&item->object.oid)); |
bd2c39f5 | 207 | } |
136f2e54 | 208 | return parse_tree_buffer(item, buffer, size); |
bd2c39f5 | 209 | } |
77675e2a | 210 | |
6e454b9a JK |
211 | void free_tree_buffer(struct tree *tree) |
212 | { | |
6a83d902 | 213 | FREE_AND_NULL(tree->buffer); |
6e454b9a JK |
214 | tree->size = 0; |
215 | tree->object.parsed = 0; | |
216 | } | |
217 | ||
a9dbc179 | 218 | struct tree *parse_tree_indirect(const struct object_id *oid) |
77675e2a | 219 | { |
1577dc0f RS |
220 | struct repository *r = the_repository; |
221 | struct object *obj = parse_object(r, oid); | |
222 | return (struct tree *)repo_peel_to_type(r, NULL, 0, obj, OBJ_TREE); | |
77675e2a | 223 | } |