🌐 AI搜索 & 代理 主页
blob: 0b23b86ceb4433ece828e780be180579a77f3fe8 [file] [log] [blame]
Junio C Hamano9938af62005-08-04 05:15:491#include "cache.h"
Brandon Williamsb2141fc2017-06-14 18:07:362#include "config.h"
Junio C Hamano5385f522005-10-14 01:57:403#include "tag.h"
Junio C Hamano9938af62005-08-04 05:15:494#include "commit.h"
Junio C Hamano5385f522005-10-14 01:57:405#include "tree.h"
6#include "blob.h"
Junio C Hamanof3ab49d2006-04-19 18:56:537#include "tree-walk.h"
Shawn Pearced556fae2006-05-17 09:56:098#include "refs.h"
Johannes Schindelin28fb8432009-09-10 15:25:579#include "remote.h"
René Scharfedbe44fa2015-05-19 21:44:2310#include "dir.h"
Jeff Kingfe299ec2020-03-30 14:03:4611#include "oid-array.h"
Jonathan Tan0317f452017-08-18 22:20:1912#include "packfile.h"
Stefan Beller0d4a1322018-03-23 17:20:5613#include "object-store.h"
Stefan Beller031dc922018-03-23 17:20:5714#include "repository.h"
Nguyễn Thái Ngọc Duyefe461b2019-04-16 09:33:3615#include "submodule.h"
Derrick Stolee8aac67a2018-07-12 19:39:3516#include "midx.h"
Derrick Stolee64043552018-07-20 16:33:0417#include "commit-reach.h"
Junio C Hamano9938af62005-08-04 05:15:4918
Nguyễn Thái Ngọc Duy0bb41a12019-04-16 09:33:2919static int get_oid_oneline(struct repository *r, const char *, struct object_id *, struct commit_list *);
Nguyễn Thái Ngọc Duy32574b62010-12-13 03:01:1520
Nguyễn Thái Ngọc Duyef9b0372019-04-16 09:33:2321typedef int (*disambiguate_hint_fn)(struct repository *, const struct object_id *, void *);
Junio C Hamanoa78fafe2012-06-21 05:07:3622
23struct disambiguate_state {
Jeff King00160432016-09-26 12:00:0424 int len; /* length of prefix in hex chars */
brian m. carlsondc015052017-03-26 16:01:2425 char hex_pfx[GIT_MAX_HEXSZ + 1];
brian m. carlsond2ee1182017-03-26 16:01:3326 struct object_id bin_pfx;
Jeff King00160432016-09-26 12:00:0427
Nguyễn Thái Ngọc Duyef9b0372019-04-16 09:33:2328 struct repository *repo;
Junio C Hamanoa78fafe2012-06-21 05:07:3629 disambiguate_hint_fn fn;
30 void *cb_data;
brian m. carlsond2ee1182017-03-26 16:01:3331 struct object_id candidate;
Junio C Hamanoa78fafe2012-06-21 05:07:3632 unsigned candidate_exists:1;
33 unsigned candidate_checked:1;
34 unsigned candidate_ok:1;
35 unsigned disambiguate_fn_used:1;
36 unsigned ambiguous:1;
Junio C Hamano957d7402012-07-03 21:21:5937 unsigned always_call_fn:1;
Junio C Hamanoa78fafe2012-06-21 05:07:3638};
39
brian m. carlsond2b7d9c2017-03-26 16:01:3440static void update_candidates(struct disambiguate_state *ds, const struct object_id *current)
Junio C Hamanoa78fafe2012-06-21 05:07:3641{
Junio C Hamano957d7402012-07-03 21:21:5942 if (ds->always_call_fn) {
Nguyễn Thái Ngọc Duyef9b0372019-04-16 09:33:2343 ds->ambiguous = ds->fn(ds->repo, current, ds->cb_data) ? 1 : 0;
Junio C Hamano957d7402012-07-03 21:21:5944 return;
45 }
Junio C Hamanoa78fafe2012-06-21 05:07:3646 if (!ds->candidate_exists) {
47 /* this is the first candidate */
brian m. carlsond2b7d9c2017-03-26 16:01:3448 oidcpy(&ds->candidate, current);
Junio C Hamanoa78fafe2012-06-21 05:07:3649 ds->candidate_exists = 1;
50 return;
Jeff King4a7e27e2018-08-28 21:22:4051 } else if (oideq(&ds->candidate, current)) {
Junio C Hamanoa78fafe2012-06-21 05:07:3652 /* the same as what we already have seen */
53 return;
54 }
55
56 if (!ds->fn) {
57 /* cannot disambiguate between ds->candidate and current */
58 ds->ambiguous = 1;
59 return;
60 }
61
62 if (!ds->candidate_checked) {
Nguyễn Thái Ngọc Duyef9b0372019-04-16 09:33:2363 ds->candidate_ok = ds->fn(ds->repo, &ds->candidate, ds->cb_data);
Junio C Hamanoa78fafe2012-06-21 05:07:3664 ds->disambiguate_fn_used = 1;
65 ds->candidate_checked = 1;
66 }
67
68 if (!ds->candidate_ok) {
Ondřej Bílka749f7632013-07-22 21:02:2369 /* discard the candidate; we know it does not satisfy fn */
brian m. carlsond2b7d9c2017-03-26 16:01:3470 oidcpy(&ds->candidate, current);
Junio C Hamanoa78fafe2012-06-21 05:07:3671 ds->candidate_checked = 0;
72 return;
73 }
74
75 /* if we reach this point, we know ds->candidate satisfies fn */
Nguyễn Thái Ngọc Duyef9b0372019-04-16 09:33:2376 if (ds->fn(ds->repo, current, ds->cb_data)) {
Junio C Hamanoa78fafe2012-06-21 05:07:3677 /*
78 * if both current and candidate satisfy fn, we cannot
79 * disambiguate.
80 */
81 ds->candidate_ok = 0;
82 ds->ambiguous = 1;
83 }
84
85 /* otherwise, current can be discarded and candidate is still good */
86}
87
René Scharfecc817ca2017-06-22 18:19:4888static int match_sha(unsigned, const unsigned char *, const unsigned char *);
89
Jeff King00160432016-09-26 12:00:0490static void find_short_object_filename(struct disambiguate_state *ds)
Junio C Hamano9938af62005-08-04 05:15:4991{
Jeff King263db402018-11-12 14:48:4792 struct object_directory *odb;
Junio C Hamano9938af62005-08-04 05:15:4993
Nguyễn Thái Ngọc Duyef9b0372019-04-16 09:33:2394 for (odb = ds->repo->objects->odb; odb && !ds->ambiguous; odb = odb->next) {
René Scharfecc817ca2017-06-22 18:19:4895 int pos;
René Scharfe0000d652019-01-06 16:45:3096 struct oid_array *loose_objects;
Jeff King597f9132016-10-03 20:35:5197
René Scharfe0000d652019-01-06 16:45:3098 loose_objects = odb_loose_cache(odb, &ds->bin_pfx);
99 pos = oid_array_lookup(loose_objects, &ds->bin_pfx);
René Scharfecc817ca2017-06-22 18:19:48100 if (pos < 0)
101 pos = -1 - pos;
René Scharfe0000d652019-01-06 16:45:30102 while (!ds->ambiguous && pos < loose_objects->nr) {
René Scharfecc817ca2017-06-22 18:19:48103 const struct object_id *oid;
René Scharfe0000d652019-01-06 16:45:30104 oid = loose_objects->oid + pos;
René Scharfecc817ca2017-06-22 18:19:48105 if (!match_sha(ds->len, ds->bin_pfx.hash, oid->hash))
106 break;
107 update_candidates(ds, oid);
108 pos++;
109 }
Junio C Hamano9938af62005-08-04 05:15:49110 }
Junio C Hamano9938af62005-08-04 05:15:49111}
112
113static int match_sha(unsigned len, const unsigned char *a, const unsigned char *b)
114{
115 do {
116 if (*a != *b)
117 return 0;
118 a++;
119 b++;
120 len -= 2;
121 } while (len > 1);
122 if (len)
123 if ((*a ^ *b) & 0xf0)
124 return 0;
125 return 1;
126}
127
Derrick Stolee8aac67a2018-07-12 19:39:35128static void unique_in_midx(struct multi_pack_index *m,
129 struct disambiguate_state *ds)
130{
131 uint32_t num, i, first = 0;
132 const struct object_id *current = NULL;
133 num = m->num_objects;
134
135 if (!num)
136 return;
137
138 bsearch_midx(&ds->bin_pfx, m, &first);
139
140 /*
141 * At this point, "first" is the location of the lowest object
142 * with an object name that could match "bin_pfx". See if we have
143 * 0, 1 or more objects that actually match(es).
144 */
145 for (i = first; i < num && !ds->ambiguous; i++) {
146 struct object_id oid;
147 current = nth_midxed_object_oid(&oid, m, i);
148 if (!match_sha(ds->len, ds->bin_pfx.hash, current->hash))
149 break;
150 update_candidates(ds, current);
151 }
152}
153
Jeff King00160432016-09-26 12:00:04154static void unique_in_pack(struct packed_git *p,
Junio C Hamanoa78fafe2012-06-21 05:07:36155 struct disambiguate_state *ds)
Junio C Hamanof703e6e2012-06-18 20:10:38156{
René Scharfe902f5a22018-03-24 16:41:08157 uint32_t num, i, first = 0;
Junio C Hamanof703e6e2012-06-18 20:10:38158
Derrick Stoleeaf96fe32019-04-29 16:18:56159 if (p->multi_pack_index)
160 return;
161
Derrick Stolee0e87b852017-10-12 12:02:20162 if (open_pack_index(p) || !p->num_objects)
163 return;
164
Junio C Hamanof703e6e2012-06-18 20:10:38165 num = p->num_objects;
René Scharfe902f5a22018-03-24 16:41:08166 bsearch_pack(&ds->bin_pfx, p, &first);
Junio C Hamanof703e6e2012-06-18 20:10:38167
168 /*
169 * At this point, "first" is the location of the lowest object
Junio C Hamano1703f9a2012-06-21 05:35:43170 * with an object name that could match "bin_pfx". See if we have
Junio C Hamanof703e6e2012-06-18 20:10:38171 * 0, 1 or more objects that actually match(es).
172 */
Junio C Hamanoa78fafe2012-06-21 05:07:36173 for (i = first; i < num && !ds->ambiguous; i++) {
brian m. carlsond2b7d9c2017-03-26 16:01:34174 struct object_id oid;
Jeff King07636712020-02-24 04:27:36175 nth_packed_object_id(&oid, p, i);
176 if (!match_sha(ds->len, ds->bin_pfx.hash, oid.hash))
Junio C Hamanof703e6e2012-06-18 20:10:38177 break;
Jeff King07636712020-02-24 04:27:36178 update_candidates(ds, &oid);
Junio C Hamanof703e6e2012-06-18 20:10:38179 }
Junio C Hamanof703e6e2012-06-18 20:10:38180}
181
Jeff King00160432016-09-26 12:00:04182static void find_short_packed_object(struct disambiguate_state *ds)
Junio C Hamano9938af62005-08-04 05:15:49183{
Derrick Stolee8aac67a2018-07-12 19:39:35184 struct multi_pack_index *m;
Junio C Hamano9938af62005-08-04 05:15:49185 struct packed_git *p;
Junio C Hamano9938af62005-08-04 05:15:49186
Nguyễn Thái Ngọc Duyef9b0372019-04-16 09:33:23187 for (m = get_multi_pack_index(ds->repo); m && !ds->ambiguous;
Derrick Stolee8aac67a2018-07-12 19:39:35188 m = m->next)
189 unique_in_midx(m, ds);
Nguyễn Thái Ngọc Duyef9b0372019-04-16 09:33:23190 for (p = get_packed_git(ds->repo); p && !ds->ambiguous;
Stefan Bellera80d72d2018-03-23 17:20:59191 p = p->next)
Jeff King00160432016-09-26 12:00:04192 unique_in_pack(p, ds);
Junio C Hamano99a19b42005-10-03 04:40:51193}
194
Junio C Hamanoa78fafe2012-06-21 05:07:36195static int finish_object_disambiguation(struct disambiguate_state *ds,
brian m. carlsone82caf32017-07-13 23:49:28196 struct object_id *oid)
Junio C Hamano99a19b42005-10-03 04:40:51197{
Junio C Hamanoa78fafe2012-06-21 05:07:36198 if (ds->ambiguous)
199 return SHORT_NAME_AMBIGUOUS;
Junio C Hamano99a19b42005-10-03 04:40:51200
Junio C Hamanoa78fafe2012-06-21 05:07:36201 if (!ds->candidate_exists)
David Turnerd1dd94b2019-01-18 04:19:43202 return MISSING_OBJECT;
Junio C Hamanoa78fafe2012-06-21 05:07:36203
204 if (!ds->candidate_checked)
205 /*
206 * If this is the only candidate, there is no point
207 * calling the disambiguation hint callback.
208 *
209 * On the other hand, if the current candidate
210 * replaced an earlier candidate that did _not_ pass
211 * the disambiguation hint callback, then we do have
212 * more than one objects that match the short name
213 * given, so we should make sure this one matches;
214 * otherwise, if we discovered this one and the one
215 * that we previously discarded in the reverse order,
216 * we would end up showing different results in the
217 * same repository!
218 */
219 ds->candidate_ok = (!ds->disambiguate_fn_used ||
Nguyễn Thái Ngọc Duyef9b0372019-04-16 09:33:23220 ds->fn(ds->repo, &ds->candidate, ds->cb_data));
Junio C Hamanoa78fafe2012-06-21 05:07:36221
222 if (!ds->candidate_ok)
Junio C Hamano013f2762005-10-11 22:22:48223 return SHORT_NAME_AMBIGUOUS;
Junio C Hamanoa78fafe2012-06-21 05:07:36224
brian m. carlsone82caf32017-07-13 23:49:28225 oidcpy(oid, &ds->candidate);
Junio C Hamano9938af62005-08-04 05:15:49226 return 0;
227}
228
Nguyễn Thái Ngọc Duyef9b0372019-04-16 09:33:23229static int disambiguate_commit_only(struct repository *r,
230 const struct object_id *oid,
231 void *cb_data_unused)
Junio C Hamano9938af62005-08-04 05:15:49232{
Nguyễn Thái Ngọc Duyef9b0372019-04-16 09:33:23233 int kind = oid_object_info(r, oid, NULL);
Junio C Hamanoaa1dec92012-06-21 06:03:09234 return kind == OBJ_COMMIT;
235}
Junio C Hamano9938af62005-08-04 05:15:49236
Nguyễn Thái Ngọc Duyef9b0372019-04-16 09:33:23237static int disambiguate_committish_only(struct repository *r,
238 const struct object_id *oid,
239 void *cb_data_unused)
Junio C Hamanoe2643612012-07-02 17:00:40240{
241 struct object *obj;
242 int kind;
243
Nguyễn Thái Ngọc Duyef9b0372019-04-16 09:33:23244 kind = oid_object_info(r, oid, NULL);
Junio C Hamanoe2643612012-07-02 17:00:40245 if (kind == OBJ_COMMIT)
246 return 1;
247 if (kind != OBJ_TAG)
248 return 0;
249
250 /* We need to do this the hard way... */
Nguyễn Thái Ngọc Duyef9b0372019-04-16 09:33:23251 obj = deref_tag(r, parse_object(r, oid), NULL, 0);
Junio C Hamanoe2643612012-07-02 17:00:40252 if (obj && obj->type == OBJ_COMMIT)
253 return 1;
254 return 0;
255}
256
Nguyễn Thái Ngọc Duyef9b0372019-04-16 09:33:23257static int disambiguate_tree_only(struct repository *r,
258 const struct object_id *oid,
259 void *cb_data_unused)
Junio C Hamanodaba53a2012-07-03 06:35:05260{
Nguyễn Thái Ngọc Duyef9b0372019-04-16 09:33:23261 int kind = oid_object_info(r, oid, NULL);
Junio C Hamanodaba53a2012-07-03 06:35:05262 return kind == OBJ_TREE;
263}
264
Nguyễn Thái Ngọc Duyef9b0372019-04-16 09:33:23265static int disambiguate_treeish_only(struct repository *r,
266 const struct object_id *oid,
267 void *cb_data_unused)
Junio C Hamanodaba53a2012-07-03 06:35:05268{
269 struct object *obj;
270 int kind;
271
Nguyễn Thái Ngọc Duyef9b0372019-04-16 09:33:23272 kind = oid_object_info(r, oid, NULL);
Junio C Hamanodaba53a2012-07-03 06:35:05273 if (kind == OBJ_TREE || kind == OBJ_COMMIT)
274 return 1;
275 if (kind != OBJ_TAG)
276 return 0;
277
278 /* We need to do this the hard way... */
Nguyễn Thái Ngọc Duyef9b0372019-04-16 09:33:23279 obj = deref_tag(r, parse_object(r, oid), NULL, 0);
Junio C Hamanodaba53a2012-07-03 06:35:05280 if (obj && (obj->type == OBJ_TREE || obj->type == OBJ_COMMIT))
281 return 1;
282 return 0;
283}
284
Nguyễn Thái Ngọc Duyef9b0372019-04-16 09:33:23285static int disambiguate_blob_only(struct repository *r,
286 const struct object_id *oid,
287 void *cb_data_unused)
Junio C Hamanodaba53a2012-07-03 06:35:05288{
Nguyễn Thái Ngọc Duyef9b0372019-04-16 09:33:23289 int kind = oid_object_info(r, oid, NULL);
Junio C Hamanodaba53a2012-07-03 06:35:05290 return kind == OBJ_BLOB;
291}
292
Jeff King5b33cb12016-09-27 12:38:01293static disambiguate_hint_fn default_disambiguate_hint;
294
295int set_disambiguate_hint_config(const char *var, const char *value)
296{
297 static const struct {
298 const char *name;
299 disambiguate_hint_fn fn;
300 } hints[] = {
301 { "none", NULL },
302 { "commit", disambiguate_commit_only },
303 { "committish", disambiguate_committish_only },
304 { "tree", disambiguate_tree_only },
305 { "treeish", disambiguate_treeish_only },
306 { "blob", disambiguate_blob_only }
307 };
308 int i;
309
310 if (!value)
311 return config_error_nonbool(var);
312
313 for (i = 0; i < ARRAY_SIZE(hints); i++) {
314 if (!strcasecmp(value, hints[i].name)) {
315 default_disambiguate_hint = hints[i].fn;
316 return 0;
317 }
318 }
319
320 return error("unknown hint type for '%s': %s", var, value);
321}
322
Nguyễn Thái Ngọc Duyef9b0372019-04-16 09:33:23323static int init_object_disambiguation(struct repository *r,
324 const char *name, int len,
Jeff King00160432016-09-26 12:00:04325 struct disambiguate_state *ds)
Junio C Hamano9938af62005-08-04 05:15:49326{
Junio C Hamano957d7402012-07-03 21:21:59327 int i;
Junio C Hamano9938af62005-08-04 05:15:49328
brian m. carlson7b38efa2018-07-16 01:27:58329 if (len < MINIMUM_ABBREV || len > the_hash_algo->hexsz)
Jeff King00160432016-09-26 12:00:04330 return -1;
331
332 memset(ds, 0, sizeof(*ds));
Jeff King00160432016-09-26 12:00:04333
Linus Torvaldsaf61c6e2005-09-19 22:16:03334 for (i = 0; i < len ;i++) {
Junio C Hamano9938af62005-08-04 05:15:49335 unsigned char c = name[i];
336 unsigned char val;
Junio C Hamano9938af62005-08-04 05:15:49337 if (c >= '0' && c <= '9')
338 val = c - '0';
339 else if (c >= 'a' && c <= 'f')
340 val = c - 'a' + 10;
341 else if (c >= 'A' && c <='F') {
342 val = c - 'A' + 10;
343 c -= 'A' - 'a';
344 }
345 else
346 return -1;
Jeff King00160432016-09-26 12:00:04347 ds->hex_pfx[i] = c;
Junio C Hamano9938af62005-08-04 05:15:49348 if (!(i & 1))
349 val <<= 4;
brian m. carlsond2ee1182017-03-26 16:01:33350 ds->bin_pfx.hash[i >> 1] |= val;
Junio C Hamano9938af62005-08-04 05:15:49351 }
Jeff King00160432016-09-26 12:00:04352
353 ds->len = len;
Jeff King59e4e342016-09-26 12:00:07354 ds->hex_pfx[len] = '\0';
Nguyễn Thái Ngọc Duyef9b0372019-04-16 09:33:23355 ds->repo = r;
356 prepare_alt_odb(r);
Junio C Hamano957d7402012-07-03 21:21:59357 return 0;
358}
Junio C Hamano99a19b42005-10-03 04:40:51359
brian m. carlson1b7ba792017-03-31 01:39:59360static int show_ambiguous_object(const struct object_id *oid, void *data)
Jeff King1ffa26c2016-09-26 12:00:36361{
362 const struct disambiguate_state *ds = data;
363 struct strbuf desc = STRBUF_INIT;
364 int type;
365
Nguyễn Thái Ngọc Duyef9b0372019-04-16 09:33:23366 if (ds->fn && !ds->fn(ds->repo, oid, ds->cb_data))
Jeff King1ffa26c2016-09-26 12:00:36367 return 0;
368
Nguyễn Thái Ngọc Duyef9b0372019-04-16 09:33:23369 type = oid_object_info(ds->repo, oid, NULL);
Jeff King1ffa26c2016-09-26 12:00:36370 if (type == OBJ_COMMIT) {
Nguyễn Thái Ngọc Duyef9b0372019-04-16 09:33:23371 struct commit *commit = lookup_commit(ds->repo, oid);
Jeff King1ffa26c2016-09-26 12:00:36372 if (commit) {
373 struct pretty_print_context pp = {0};
374 pp.date_mode.type = DATE_SHORT;
375 format_commit_message(commit, " %ad - %s", &desc, &pp);
376 }
377 } else if (type == OBJ_TAG) {
Nguyễn Thái Ngọc Duyef9b0372019-04-16 09:33:23378 struct tag *tag = lookup_tag(ds->repo, oid);
Jeff King1ffa26c2016-09-26 12:00:36379 if (!parse_tag(tag) && tag->tag)
380 strbuf_addf(&desc, " %s", tag->tag);
381 }
382
383 advise(" %s %s%s",
Nguyễn Thái Ngọc Duyef9b0372019-04-16 09:33:23384 repo_find_unique_abbrev(ds->repo, oid, DEFAULT_ABBREV),
Brandon Williamsdebca9d2018-02-14 18:59:24385 type_name(type) ? type_name(type) : "unknown type",
Jeff King1ffa26c2016-09-26 12:00:36386 desc.buf);
387
388 strbuf_release(&desc);
389 return 0;
390}
391
Ævar Arnfjörð Bjarmasona885c932018-05-10 12:43:01392static int collect_ambiguous(const struct object_id *oid, void *data)
393{
394 oid_array_append(data, oid);
395 return 0;
396}
397
Nguyễn Thái Ngọc Duyef9b0372019-04-16 09:33:23398static int repo_collect_ambiguous(struct repository *r,
399 const struct object_id *oid,
400 void *data)
401{
402 return collect_ambiguous(oid, data);
403}
404
René Scharfe7cfcb162019-08-20 18:49:12405static int sort_ambiguous(const void *a, const void *b, void *ctx)
Ævar Arnfjörð Bjarmason5cc044e2018-05-10 12:43:02406{
René Scharfe7cfcb162019-08-20 18:49:12407 struct repository *sort_ambiguous_repo = ctx;
Nguyễn Thái Ngọc Duyfae2ae42019-04-16 09:33:20408 int a_type = oid_object_info(sort_ambiguous_repo, a, NULL);
409 int b_type = oid_object_info(sort_ambiguous_repo, b, NULL);
Ævar Arnfjörð Bjarmason5cc044e2018-05-10 12:43:02410 int a_type_sort;
411 int b_type_sort;
412
413 /*
414 * Sorts by hash within the same object type, just as
415 * oid_array_for_each_unique() would do.
416 */
417 if (a_type == b_type)
418 return oidcmp(a, b);
419
420 /*
421 * Between object types show tags, then commits, and finally
422 * trees and blobs.
423 *
424 * The object_type enum is commit, tree, blob, tag, but we
425 * want tag, commit, tree blob. Cleverly (perhaps too
426 * cleverly) do that with modulus, since the enum assigns 1 to
427 * commit, so tag becomes 0.
428 */
429 a_type_sort = a_type % 4;
430 b_type_sort = b_type % 4;
431 return a_type_sort > b_type_sort ? 1 : -1;
432}
433
Nguyễn Thái Ngọc Duyfae2ae42019-04-16 09:33:20434static void sort_ambiguous_oid_array(struct repository *r, struct oid_array *a)
435{
René Scharfe7cfcb162019-08-20 18:49:12436 QSORT_S(a->oid, a->nr, sort_ambiguous, r);
Nguyễn Thái Ngọc Duyfae2ae42019-04-16 09:33:20437}
438
Nguyễn Thái Ngọc Duyc6c02352019-04-16 09:33:25439static enum get_oid_result get_short_oid(struct repository *r,
440 const char *name, int len,
David Turnerd1dd94b2019-01-18 04:19:43441 struct object_id *oid,
442 unsigned flags)
Junio C Hamano957d7402012-07-03 21:21:59443{
444 int status;
Junio C Hamano957d7402012-07-03 21:21:59445 struct disambiguate_state ds;
brian m. carlson321c89b2017-07-13 23:49:29446 int quietly = !!(flags & GET_OID_QUIETLY);
Junio C Hamano957d7402012-07-03 21:21:59447
Nguyễn Thái Ngọc Duyc6c02352019-04-16 09:33:25448 if (init_object_disambiguation(r, name, len, &ds) < 0)
Junio C Hamano957d7402012-07-03 21:21:59449 return -1;
Jeff King259942f2016-09-26 11:59:01450
brian m. carlson321c89b2017-07-13 23:49:29451 if (HAS_MULTI_BITS(flags & GET_OID_DISAMBIGUATORS))
Johannes Schindelin033abf92018-05-02 09:38:39452 BUG("multiple get_short_oid disambiguator flags");
Jeff King259942f2016-09-26 11:59:01453
brian m. carlson321c89b2017-07-13 23:49:29454 if (flags & GET_OID_COMMIT)
Junio C Hamanoaa1dec92012-06-21 06:03:09455 ds.fn = disambiguate_commit_only;
brian m. carlson321c89b2017-07-13 23:49:29456 else if (flags & GET_OID_COMMITTISH)
Junio C Hamanoe2643612012-07-02 17:00:40457 ds.fn = disambiguate_committish_only;
brian m. carlson321c89b2017-07-13 23:49:29458 else if (flags & GET_OID_TREE)
Junio C Hamanodaba53a2012-07-03 06:35:05459 ds.fn = disambiguate_tree_only;
brian m. carlson321c89b2017-07-13 23:49:29460 else if (flags & GET_OID_TREEISH)
Junio C Hamanodaba53a2012-07-03 06:35:05461 ds.fn = disambiguate_treeish_only;
brian m. carlson321c89b2017-07-13 23:49:29462 else if (flags & GET_OID_BLOB)
Junio C Hamanodaba53a2012-07-03 06:35:05463 ds.fn = disambiguate_blob_only;
Jeff King5b33cb12016-09-27 12:38:01464 else
465 ds.fn = default_disambiguate_hint;
Junio C Hamanoaa1dec92012-06-21 06:03:09466
Jeff King00160432016-09-26 12:00:04467 find_short_object_filename(&ds);
468 find_short_packed_object(&ds);
brian m. carlsone82caf32017-07-13 23:49:28469 status = finish_object_disambiguation(&ds, oid);
Junio C Hamanoa78fafe2012-06-21 05:07:36470
Johannes Schindelin6d67a992019-03-13 10:16:34471 /*
472 * If we didn't find it, do the usual reprepare() slow-path,
473 * since the object may have recently been added to the repository
474 * or migrated from loose to packed.
475 */
476 if (status == MISSING_OBJECT) {
Nguyễn Thái Ngọc Duy34e77712019-06-27 09:28:52477 reprepare_packed_git(r);
Johannes Schindelin6d67a992019-03-13 10:16:34478 find_short_object_filename(&ds);
479 find_short_packed_object(&ds);
480 status = finish_object_disambiguation(&ds, oid);
481 }
482
Jeff King1ffa26c2016-09-26 12:00:36483 if (!quietly && (status == SHORT_NAME_AMBIGUOUS)) {
Ævar Arnfjörð Bjarmason5cc044e2018-05-10 12:43:02484 struct oid_array collect = OID_ARRAY_INIT;
485
Jeff King1ffa26c2016-09-26 12:00:36486 error(_("short SHA1 %s is ambiguous"), ds.hex_pfx);
487
488 /*
489 * We may still have ambiguity if we simply saw a series of
490 * candidates that did not satisfy our hint function. In
491 * that case, we still want to show them, so disable the hint
492 * function entirely.
493 */
494 if (!ds.ambiguous)
495 ds.fn = NULL;
496
497 advise(_("The candidates are:"));
Nguyễn Thái Ngọc Duyc6c02352019-04-16 09:33:25498 repo_for_each_abbrev(r, ds.hex_pfx, collect_ambiguous, &collect);
499 sort_ambiguous_oid_array(r, &collect);
Ævar Arnfjörð Bjarmason5cc044e2018-05-10 12:43:02500
501 if (oid_array_for_each(&collect, show_ambiguous_object, &ds))
502 BUG("show_ambiguous_object shouldn't return non-zero");
503 oid_array_clear(&collect);
Jeff King1ffa26c2016-09-26 12:00:36504 }
505
Junio C Hamano013f2762005-10-11 22:22:48506 return status;
507}
508
Nguyễn Thái Ngọc Duy4e99f2d2019-04-16 09:33:24509int repo_for_each_abbrev(struct repository *r, const char *prefix,
510 each_abbrev_fn fn, void *cb_data)
Junio C Hamano957d7402012-07-03 21:21:59511{
brian m. carlson910650d2017-03-31 01:40:00512 struct oid_array collect = OID_ARRAY_INIT;
Junio C Hamano957d7402012-07-03 21:21:59513 struct disambiguate_state ds;
Jeff Kingfad6b9e2016-09-26 12:00:33514 int ret;
Junio C Hamano957d7402012-07-03 21:21:59515
Nguyễn Thái Ngọc Duy4e99f2d2019-04-16 09:33:24516 if (init_object_disambiguation(r, prefix, strlen(prefix), &ds) < 0)
Junio C Hamano957d7402012-07-03 21:21:59517 return -1;
518
Junio C Hamano957d7402012-07-03 21:21:59519 ds.always_call_fn = 1;
Nguyễn Thái Ngọc Duyef9b0372019-04-16 09:33:23520 ds.fn = repo_collect_ambiguous;
Jeff Kingfad6b9e2016-09-26 12:00:33521 ds.cb_data = &collect;
Jeff King00160432016-09-26 12:00:04522 find_short_object_filename(&ds);
523 find_short_packed_object(&ds);
Jeff Kingfad6b9e2016-09-26 12:00:33524
brian m. carlson910650d2017-03-31 01:40:00525 ret = oid_array_for_each_unique(&collect, fn, cb_data);
526 oid_array_clear(&collect);
Jeff Kingfad6b9e2016-09-26 12:00:33527 return ret;
Junio C Hamano957d7402012-07-03 21:21:59528}
529
Jeff King8e3f52d2016-10-03 23:47:28530/*
531 * Return the slot of the most-significant bit set in "val". There are various
532 * ways to do this quickly with fls() or __builtin_clzl(), but speed is
533 * probably not a big deal here.
534 */
535static unsigned msb(unsigned long val)
536{
537 unsigned r = 0;
538 while (val >>= 1)
539 r++;
540 return r;
541}
542
Derrick Stolee5b20ace2017-10-08 18:49:40543struct min_abbrev_data {
544 unsigned int init_len;
545 unsigned int cur_len;
546 char *hex;
Nguyễn Thái Ngọc Duy7f07c032019-04-16 09:33:21547 struct repository *repo;
brian m. carlson626fd982018-03-22 17:40:08548 const struct object_id *oid;
Derrick Stolee5b20ace2017-10-08 18:49:40549};
550
Derrick Stoleea42d6fd2017-10-12 12:02:19551static inline char get_hex_char_from_oid(const struct object_id *oid,
552 unsigned int pos)
553{
554 static const char hex[] = "0123456789abcdef";
555
556 if ((pos & 1) == 0)
557 return hex[oid->hash[pos >> 1] >> 4];
558 else
559 return hex[oid->hash[pos >> 1] & 0xf];
560}
561
Derrick Stolee5b20ace2017-10-08 18:49:40562static int extend_abbrev_len(const struct object_id *oid, void *cb_data)
563{
564 struct min_abbrev_data *mad = cb_data;
565
Derrick Stolee5b20ace2017-10-08 18:49:40566 unsigned int i = mad->init_len;
Derrick Stoleea42d6fd2017-10-12 12:02:19567 while (mad->hex[i] && mad->hex[i] == get_hex_char_from_oid(oid, i))
Derrick Stolee5b20ace2017-10-08 18:49:40568 i++;
569
570 if (i < GIT_MAX_RAWSZ && i >= mad->cur_len)
571 mad->cur_len = i + 1;
572
573 return 0;
574}
575
Nguyễn Thái Ngọc Duyef9b0372019-04-16 09:33:23576static int repo_extend_abbrev_len(struct repository *r,
577 const struct object_id *oid,
578 void *cb_data)
579{
580 return extend_abbrev_len(oid, cb_data);
581}
582
Derrick Stolee8aac67a2018-07-12 19:39:35583static void find_abbrev_len_for_midx(struct multi_pack_index *m,
584 struct min_abbrev_data *mad)
585{
586 int match = 0;
587 uint32_t num, first = 0;
588 struct object_id oid;
589 const struct object_id *mad_oid;
590
591 if (!m->num_objects)
592 return;
593
594 num = m->num_objects;
595 mad_oid = mad->oid;
596 match = bsearch_midx(mad_oid, m, &first);
597
598 /*
599 * first is now the position in the packfile where we would insert
600 * mad->hash if it does not exist (or the position of mad->hash if
601 * it does exist). Hence, we consider a maximum of two objects
602 * nearby for the abbreviation length.
603 */
604 mad->init_len = 0;
605 if (!match) {
606 if (nth_midxed_object_oid(&oid, m, first))
607 extend_abbrev_len(&oid, mad);
608 } else if (first < num - 1) {
609 if (nth_midxed_object_oid(&oid, m, first + 1))
610 extend_abbrev_len(&oid, mad);
611 }
612 if (first > 0) {
613 if (nth_midxed_object_oid(&oid, m, first - 1))
614 extend_abbrev_len(&oid, mad);
615 }
616 mad->init_len = mad->cur_len;
617}
618
Derrick Stolee0e87b852017-10-12 12:02:20619static void find_abbrev_len_for_pack(struct packed_git *p,
620 struct min_abbrev_data *mad)
621{
622 int match = 0;
Derrick Stolee0aaf05b2018-03-22 17:40:10623 uint32_t num, first = 0;
Derrick Stolee0e87b852017-10-12 12:02:20624 struct object_id oid;
Derrick Stolee0aaf05b2018-03-22 17:40:10625 const struct object_id *mad_oid;
Derrick Stolee0e87b852017-10-12 12:02:20626
Derrick Stoleeaf96fe32019-04-29 16:18:56627 if (p->multi_pack_index)
628 return;
629
Derrick Stolee0e87b852017-10-12 12:02:20630 if (open_pack_index(p) || !p->num_objects)
631 return;
632
633 num = p->num_objects;
Derrick Stolee0aaf05b2018-03-22 17:40:10634 mad_oid = mad->oid;
635 match = bsearch_pack(mad_oid, p, &first);
Derrick Stolee0e87b852017-10-12 12:02:20636
637 /*
638 * first is now the position in the packfile where we would insert
639 * mad->hash if it does not exist (or the position of mad->hash if
Derrick Stolee21abed52018-02-27 11:47:04640 * it does exist). Hence, we consider a maximum of two objects
Derrick Stolee0e87b852017-10-12 12:02:20641 * nearby for the abbreviation length.
642 */
643 mad->init_len = 0;
644 if (!match) {
Jeff King07636712020-02-24 04:27:36645 if (!nth_packed_object_id(&oid, p, first))
Derrick Stolee21abed52018-02-27 11:47:04646 extend_abbrev_len(&oid, mad);
Derrick Stolee0e87b852017-10-12 12:02:20647 } else if (first < num - 1) {
Jeff King07636712020-02-24 04:27:36648 if (!nth_packed_object_id(&oid, p, first + 1))
Derrick Stolee21abed52018-02-27 11:47:04649 extend_abbrev_len(&oid, mad);
Derrick Stolee0e87b852017-10-12 12:02:20650 }
651 if (first > 0) {
Jeff King07636712020-02-24 04:27:36652 if (!nth_packed_object_id(&oid, p, first - 1))
Derrick Stolee21abed52018-02-27 11:47:04653 extend_abbrev_len(&oid, mad);
Derrick Stolee0e87b852017-10-12 12:02:20654 }
655 mad->init_len = mad->cur_len;
656}
657
658static void find_abbrev_len_packed(struct min_abbrev_data *mad)
659{
Derrick Stolee8aac67a2018-07-12 19:39:35660 struct multi_pack_index *m;
Derrick Stolee0e87b852017-10-12 12:02:20661 struct packed_git *p;
662
Nguyễn Thái Ngọc Duy7f07c032019-04-16 09:33:21663 for (m = get_multi_pack_index(mad->repo); m; m = m->next)
Derrick Stolee8aac67a2018-07-12 19:39:35664 find_abbrev_len_for_midx(m, mad);
Nguyễn Thái Ngọc Duy7f07c032019-04-16 09:33:21665 for (p = get_packed_git(mad->repo); p; p = p->next)
Derrick Stolee0e87b852017-10-12 12:02:20666 find_abbrev_len_for_pack(p, mad);
667}
668
Nguyễn Thái Ngọc Duy8bb95572019-04-16 09:33:22669int repo_find_unique_abbrev_r(struct repository *r, char *hex,
670 const struct object_id *oid, int len)
Junio C Hamano013f2762005-10-11 22:22:48671{
Derrick Stolee5b20ace2017-10-08 18:49:40672 struct disambiguate_state ds;
673 struct min_abbrev_data mad;
674 struct object_id oid_ret;
Nguyễn Thái Ngọc Duy8bb95572019-04-16 09:33:22675 const unsigned hexsz = r->hash_algo->hexsz;
brian m. carlson7b38efa2018-07-16 01:27:58676
Linus Torvaldse6c587c2016-10-01 00:19:37677 if (len < 0) {
Nguyễn Thái Ngọc Duy8bb95572019-04-16 09:33:22678 unsigned long count = repo_approximate_object_count(r);
Jeff King8e3f52d2016-10-03 23:47:28679 /*
680 * Add one because the MSB only tells us the highest bit set,
681 * not including the value of all the _other_ bits (so "15"
682 * is only one off of 2^4, but the MSB is the 3rd bit.
683 */
684 len = msb(count) + 1;
685 /*
686 * We now know we have on the order of 2^len objects, which
687 * expects a collision at 2^(len/2). But we also care about hex
688 * chars, not bits, and there are 4 bits per hex. So all
René Scharfe42c78a22017-07-08 10:35:35689 * together we need to divide by 2 and round up.
Jeff King8e3f52d2016-10-03 23:47:28690 */
René Scharfe42c78a22017-07-08 10:35:35691 len = DIV_ROUND_UP(len, 2);
Jeff King8e3f52d2016-10-03 23:47:28692 /*
693 * For very small repos, we stick with our regular fallback.
694 */
695 if (len < FALLBACK_DEFAULT_ABBREV)
696 len = FALLBACK_DEFAULT_ABBREV;
Linus Torvaldse6c587c2016-10-01 00:19:37697 }
Jeff King8e3f52d2016-10-03 23:47:28698
brian m. carlsonaab95832018-03-12 02:27:30699 oid_to_hex_r(hex, oid);
brian m. carlson7b38efa2018-07-16 01:27:58700 if (len == hexsz || !len)
701 return hexsz;
Derrick Stolee5b20ace2017-10-08 18:49:40702
Nguyễn Thái Ngọc Duy8bb95572019-04-16 09:33:22703 mad.repo = r;
Derrick Stolee5b20ace2017-10-08 18:49:40704 mad.init_len = len;
705 mad.cur_len = len;
706 mad.hex = hex;
brian m. carlson626fd982018-03-22 17:40:08707 mad.oid = oid;
Derrick Stolee0e87b852017-10-12 12:02:20708
709 find_abbrev_len_packed(&mad);
710
Nguyễn Thái Ngọc Duyef9b0372019-04-16 09:33:23711 if (init_object_disambiguation(r, hex, mad.cur_len, &ds) < 0)
Derrick Stolee0e87b852017-10-12 12:02:20712 return -1;
Derrick Stolee5b20ace2017-10-08 18:49:40713
Nguyễn Thái Ngọc Duyef9b0372019-04-16 09:33:23714 ds.fn = repo_extend_abbrev_len;
Derrick Stolee5b20ace2017-10-08 18:49:40715 ds.always_call_fn = 1;
716 ds.cb_data = (void *)&mad;
717
718 find_short_object_filename(&ds);
Derrick Stolee5b20ace2017-10-08 18:49:40719 (void)finish_object_disambiguation(&ds, &oid_ret);
720
721 hex[mad.cur_len] = 0;
722 return mad.cur_len;
Jeff Kingaf49c6d2015-09-24 21:05:45723}
724
Nguyễn Thái Ngọc Duy8bb95572019-04-16 09:33:22725const char *repo_find_unique_abbrev(struct repository *r,
726 const struct object_id *oid,
727 int len)
Jeff Kingaf49c6d2015-09-24 21:05:45728{
Jeff Kingef2ed502016-10-20 06:19:19729 static int bufno;
brian m. carlsondc015052017-03-26 16:01:24730 static char hexbuffer[4][GIT_MAX_HEXSZ + 1];
René Scharfe3e989192016-11-01 08:49:07731 char *hex = hexbuffer[bufno];
732 bufno = (bufno + 1) % ARRAY_SIZE(hexbuffer);
Nguyễn Thái Ngọc Duy8bb95572019-04-16 09:33:22733 repo_find_unique_abbrev_r(r, hex, oid, len);
Junio C Hamanob66fde92008-03-02 07:35:32734 return hex;
Junio C Hamano9938af62005-08-04 05:15:49735}
736
Junio C Hamano6677c462005-12-15 20:54:00737static int ambiguous_path(const char *path, int len)
Linus Torvaldsaf13cdf2005-10-28 19:41:49738{
739 int slash = 1;
Junio C Hamano6677c462005-12-15 20:54:00740 int cnt;
Linus Torvaldsaf13cdf2005-10-28 19:41:49741
Junio C Hamano6677c462005-12-15 20:54:00742 for (cnt = 0; cnt < len; cnt++) {
Linus Torvaldsaf13cdf2005-10-28 19:41:49743 switch (*path++) {
744 case '\0':
745 break;
746 case '/':
747 if (slash)
748 break;
749 slash = 1;
750 continue;
751 case '.':
752 continue;
753 default:
754 slash = 0;
755 continue;
756 }
Junio C Hamanoc054d642005-12-17 08:00:50757 break;
Linus Torvaldsaf13cdf2005-10-28 19:41:49758 }
Junio C Hamano6677c462005-12-15 20:54:00759 return slash;
Linus Torvaldsaf13cdf2005-10-28 19:41:49760}
761
Jeff Kinga1ad0eb2015-05-21 04:45:39762static inline int at_mark(const char *string, int len,
763 const char **suffix, int nr)
Junio C Hamanoae0ba8e2010-01-20 07:17:11764{
Junio C Hamanoae0ba8e2010-01-20 07:17:11765 int i;
766
Jeff Kinga1ad0eb2015-05-21 04:45:39767 for (i = 0; i < nr; i++) {
Junio C Hamanoae0ba8e2010-01-20 07:17:11768 int suffix_len = strlen(suffix[i]);
769 if (suffix_len <= len
Ævar Arnfjörð Bjarmason244ea1b2017-03-27 11:16:55770 && !strncasecmp(string, suffix[i], suffix_len))
Junio C Hamanoae0ba8e2010-01-20 07:17:11771 return suffix_len;
772 }
773 return 0;
774}
775
Jeff Kinga1ad0eb2015-05-21 04:45:39776static inline int upstream_mark(const char *string, int len)
777{
778 const char *suffix[] = { "@{upstream}", "@{u}" };
779 return at_mark(string, len, suffix, ARRAY_SIZE(suffix));
780}
781
Jeff Kingadfe5d02015-05-21 04:45:47782static inline int push_mark(const char *string, int len)
783{
784 const char *suffix[] = { "@{push}" };
785 return at_mark(string, len, suffix, ARRAY_SIZE(suffix));
786}
787
Nguyễn Thái Ngọc Duy2b1790f2019-04-16 09:33:32788static enum get_oid_result get_oid_1(struct repository *r, const char *name, int len, struct object_id *oid, unsigned lookup_flags);
Nguyễn Thái Ngọc Duy23a57122019-04-16 09:33:26789static int interpret_nth_prior_checkout(struct repository *r, const char *name, int namelen, struct strbuf *buf);
Thomas Rastd18ba222009-01-17 16:09:55790
Nguyễn Thái Ngọc Duy49281cf2019-04-16 09:33:31791static int get_oid_basic(struct repository *r, const char *str, int len,
792 struct object_id *oid, unsigned int flags)
Junio C Hamanoe86eb662007-01-19 09:15:15793{
Jon Seymoureedce782010-08-24 04:52:43794 static const char *warn_msg = "refname '%.*s' is ambiguous.";
Nguyễn Thái Ngọc Duy798c35f2013-05-29 12:12:42795 static const char *object_name_msg = N_(
796 "Git normally never creates a ref that ends with 40 hex characters\n"
797 "because it will be ignored when you just specify 40-hex. These refs\n"
798 "may be created by mistake. For example,\n"
799 "\n"
Nguyễn Thái Ngọc Duy328c6cb2019-03-29 10:39:19800 " git switch -c $br $(git rev-parse ...)\n"
Nguyễn Thái Ngọc Duy798c35f2013-05-29 12:12:42801 "\n"
802 "where \"$br\" is somehow empty and a 40-hex ref is created. Please\n"
803 "examine these refs and maybe delete them. Turn this message off by\n"
Thomas Rast8dc84fd2013-07-31 20:23:31804 "running \"git config advice.objectNameWarning false\"");
brian m. carlsone82caf32017-07-13 23:49:28805 struct object_id tmp_oid;
Linus Torvaldsed378ec2006-09-12 03:17:35806 char *real_ref = NULL;
Junio C Hamanoab2a1a32006-10-06 06:16:15807 int refs_found = 0;
Felipe Contreras128fd542013-05-07 21:55:10808 int at, reflog_len, nth_prior = 0;
Junio C Hamano9938af62005-08-04 05:15:49809
Nguyễn Thái Ngọc Duy49281cf2019-04-16 09:33:31810 if (len == r->hash_algo->hexsz && !get_oid_hex(str, oid)) {
Brodie Rao832cf742014-01-07 03:32:01811 if (warn_ambiguous_refs && warn_on_object_refname_ambiguity) {
Jonathan Tanf24c30e2020-09-01 22:28:09812 refs_found = repo_dwim_ref(r, str, len, &tmp_oid, &real_ref, 0);
Brodie Rao832cf742014-01-07 03:32:01813 if (refs_found > 0) {
Jeff King25fba782013-07-12 06:20:05814 warning(warn_msg, len, str);
815 if (advice_object_name_warning)
816 fprintf(stderr, "%s\n", _(object_name_msg));
817 }
818 free(real_ref);
Nguyễn Thái Ngọc Duy798c35f2013-05-29 12:12:42819 }
Junio C Hamano9938af62005-08-04 05:15:49820 return 0;
Nguyễn Thái Ngọc Duy798c35f2013-05-29 12:12:42821 }
Junio C Hamano9938af62005-08-04 05:15:49822
Thomas Rastd18ba222009-01-17 16:09:55823 /* basic@{time or number or -number} format to query ref-log */
Junio C Hamano694500e2006-10-24 04:15:34824 reflog_len = at = 0;
Johannes Schindelinf2654582009-01-27 23:07:46825 if (len && str[len-1] == '}') {
Ramkumar Ramachandrae883a052013-05-07 21:55:09826 for (at = len-4; at >= 0; at--) {
Junio C Hamanoab2a1a32006-10-06 06:16:15827 if (str[at] == '@' && str[at+1] == '{') {
Ramkumar Ramachandra83d16bc2013-05-07 21:55:11828 if (str[at+2] == '-') {
829 if (at != 0)
830 /* @{-N} not at start */
831 return -1;
Felipe Contreras128fd542013-05-07 21:55:10832 nth_prior = 1;
833 continue;
834 }
Jeff Kingadfe5d02015-05-21 04:45:47835 if (!upstream_mark(str + at, len - at) &&
836 !push_mark(str + at, len - at)) {
Johannes Schindelin28fb8432009-09-10 15:25:57837 reflog_len = (len-1) - (at+2);
838 len = at;
839 }
Junio C Hamanoab2a1a32006-10-06 06:16:15840 break;
841 }
Shawn Pearced556fae2006-05-17 09:56:09842 }
843 }
844
Linus Torvaldsaf13cdf2005-10-28 19:41:49845 /* Accept only unambiguous ref paths. */
Nicolas Pitre11cf8802007-02-01 22:29:33846 if (len && ambiguous_path(str, len))
Linus Torvaldsaf13cdf2005-10-28 19:41:49847 return -1;
848
Felipe Contreras128fd542013-05-07 21:55:10849 if (nth_prior) {
Thomas Rastd18ba222009-01-17 16:09:55850 struct strbuf buf = STRBUF_INIT;
Felipe Contreras128fd542013-05-07 21:55:10851 int detached;
852
Nguyễn Thái Ngọc Duy49281cf2019-04-16 09:33:31853 if (interpret_nth_prior_checkout(r, str, len, &buf) > 0) {
854 detached = (buf.len == r->hash_algo->hexsz && !get_oid_hex(buf.buf, oid));
Felipe Contreras128fd542013-05-07 21:55:10855 strbuf_release(&buf);
856 if (detached)
857 return 0;
Thomas Rastd18ba222009-01-17 16:09:55858 }
Felipe Contreras128fd542013-05-07 21:55:10859 }
860
861 if (!len && reflog_len)
Nicolas Pitre11cf8802007-02-01 22:29:33862 /* allow "@{...}" to mean the current branch reflog */
Jonathan Tanf24c30e2020-09-01 22:28:09863 refs_found = repo_dwim_ref(r, "HEAD", 4, oid, &real_ref, 0);
Felipe Contreras128fd542013-05-07 21:55:10864 else if (reflog_len)
Nguyễn Thái Ngọc Duy49281cf2019-04-16 09:33:31865 refs_found = repo_dwim_log(r, str, len, oid, &real_ref);
Nicolas Pitref2eba662007-02-04 02:49:16866 else
Jonathan Tanf24c30e2020-09-01 22:28:09867 refs_found = repo_dwim_ref(r, str, len, oid, &real_ref, 0);
Shawn Pearced556fae2006-05-17 09:56:09868
869 if (!refs_found)
870 return -1;
871
brian m. carlson321c89b2017-07-13 23:49:29872 if (warn_ambiguous_refs && !(flags & GET_OID_QUIETLY) &&
Nguyễn Thái Ngọc Duy798c35f2013-05-29 12:12:42873 (refs_found > 1 ||
Nguyễn Thái Ngọc Duy49281cf2019-04-16 09:33:31874 !get_short_oid(r, str, len, &tmp_oid, GET_OID_QUIETLY)))
Jon Seymoureedce782010-08-24 04:52:43875 warning(warn_msg, len, str);
Shawn Pearced556fae2006-05-17 09:56:09876
Junio C Hamanoab2a1a32006-10-06 06:16:15877 if (reflog_len) {
Junio C Hamanoab2a1a32006-10-06 06:16:15878 int nth, i;
Johannes Schindelindddbad72017-04-26 19:29:31879 timestamp_t at_time;
880 timestamp_t co_time;
Junio C Hamano16d7cc92007-01-19 09:19:05881 int co_tz, co_cnt;
882
Nicolas Pitrefe558512007-02-01 17:33:23883 /* Is it asking for N-th entry, or approxidate? */
Junio C Hamanoab2a1a32006-10-06 06:16:15884 for (i = nth = 0; 0 <= nth && i < reflog_len; i++) {
885 char ch = str[at+2+i];
886 if ('0' <= ch && ch <= '9')
887 nth = nth * 10 + ch - '0';
888 else
889 nth = -1;
890 }
Shawn O. Pearceea360dd2008-08-21 15:40:44891 if (100000000 <= nth) {
892 at_time = nth;
893 nth = -1;
894 } else if (0 <= nth)
Junio C Hamanoab2a1a32006-10-06 06:16:15895 at_time = 0;
Jeff King861f00e2008-04-30 04:13:58896 else {
Junio C Hamano93cfa7c2010-01-26 19:58:00897 int errors = 0;
Jeff King861f00e2008-04-30 04:13:58898 char *tmp = xstrndup(str + at + 2, reflog_len);
Junio C Hamano93cfa7c2010-01-26 19:58:00899 at_time = approxidate_careful(tmp, &errors);
Jeff King861f00e2008-04-30 04:13:58900 free(tmp);
Jeff King28b35632014-07-24 04:41:11901 if (errors) {
902 free(real_ref);
Junio C Hamanoa5e10ac2010-01-27 18:53:09903 return -1;
Jeff King28b35632014-07-24 04:41:11904 }
Jeff King861f00e2008-04-30 04:13:58905 }
Nguyễn Thái Ngọc Duy49281cf2019-04-16 09:33:31906 if (read_ref_at(get_main_ref_store(r),
Nguyễn Thái Ngọc Duy7fdff472019-04-06 11:34:30907 real_ref, flags, at_time, nth, oid, NULL,
Junio C Hamano16d7cc92007-01-19 09:19:05908 &co_time, &co_tz, &co_cnt)) {
Ramkumar Ramachandra305ebea2013-05-22 10:39:55909 if (!len) {
Junio C Hamano145136a2020-01-30 19:35:46910 if (!skip_prefix(real_ref, "refs/heads/", &str))
Ramkumar Ramachandra305ebea2013-05-22 10:39:55911 str = "HEAD";
Junio C Hamano145136a2020-01-30 19:35:46912 len = strlen(str);
Ramkumar Ramachandra305ebea2013-05-22 10:39:55913 }
David Aguilarc41a87d2014-09-19 03:45:37914 if (at_time) {
brian m. carlson321c89b2017-07-13 23:49:29915 if (!(flags & GET_OID_QUIETLY)) {
Jeff Kingb0418302020-01-25 00:13:01916 warning(_("log for '%.*s' only goes back to %s"),
917 len, str,
Jeff Kinga5481a62015-06-25 16:55:02918 show_date(co_time, co_tz, DATE_MODE(RFC2822)));
David Aguilarc41a87d2014-09-19 03:45:37919 }
920 } else {
brian m. carlson321c89b2017-07-13 23:49:29921 if (flags & GET_OID_QUIETLY) {
David Aguilarc41a87d2014-09-19 03:45:37922 exit(128);
923 }
Jeff Kingb0418302020-01-25 00:13:01924 die(_("log for '%.*s' only has %d entries"),
Jon Seymoure6eedc32010-08-24 04:52:42925 len, str, co_cnt);
926 }
Junio C Hamano16d7cc92007-01-19 09:19:05927 }
Shawn Pearced556fae2006-05-17 09:56:09928 }
929
Linus Torvaldsed378ec2006-09-12 03:17:35930 free(real_ref);
Shawn Pearced556fae2006-05-17 09:56:09931 return 0;
Junio C Hamano9938af62005-08-04 05:15:49932}
933
Nguyễn Thái Ngọc Duy2b1790f2019-04-16 09:33:32934static enum get_oid_result get_parent(struct repository *r,
935 const char *name, int len,
David Turnerd1dd94b2019-01-18 04:19:43936 struct object_id *result, int idx)
Junio C Hamano9938af62005-08-04 05:15:49937{
brian m. carlson1e43ed92017-05-06 22:10:09938 struct object_id oid;
Nguyễn Thái Ngọc Duy2b1790f2019-04-16 09:33:32939 enum get_oid_result ret = get_oid_1(r, name, len, &oid,
David Turnerd1dd94b2019-01-18 04:19:43940 GET_OID_COMMITTISH);
Junio C Hamano9938af62005-08-04 05:15:49941 struct commit *commit;
942 struct commit_list *p;
943
944 if (ret)
945 return ret;
Nguyễn Thái Ngọc Duy2b1790f2019-04-16 09:33:32946 commit = lookup_commit_reference(r, &oid);
Junio C Hamano9938af62005-08-04 05:15:49947 if (parse_commit(commit))
David Turnerd1dd94b2019-01-18 04:19:43948 return MISSING_OBJECT;
Junio C Hamano9938af62005-08-04 05:15:49949 if (!idx) {
brian m. carlsone82caf32017-07-13 23:49:28950 oidcpy(result, &commit->object.oid);
David Turnerd1dd94b2019-01-18 04:19:43951 return FOUND;
Junio C Hamano9938af62005-08-04 05:15:49952 }
953 p = commit->parents;
954 while (p) {
955 if (!--idx) {
brian m. carlsone82caf32017-07-13 23:49:28956 oidcpy(result, &p->item->object.oid);
David Turnerd1dd94b2019-01-18 04:19:43957 return FOUND;
Junio C Hamano9938af62005-08-04 05:15:49958 }
959 p = p->next;
960 }
David Turnerd1dd94b2019-01-18 04:19:43961 return MISSING_OBJECT;
Junio C Hamano9938af62005-08-04 05:15:49962}
963
Nguyễn Thái Ngọc Duy2b1790f2019-04-16 09:33:32964static enum get_oid_result get_nth_ancestor(struct repository *r,
965 const char *name, int len,
David Turnerd1dd94b2019-01-18 04:19:43966 struct object_id *result,
967 int generation)
Junio C Hamano4f7599a2005-08-21 09:43:54968{
brian m. carlson1e43ed92017-05-06 22:10:09969 struct object_id oid;
Linus Torvalds621ff672008-03-14 18:49:40970 struct commit *commit;
971 int ret;
972
Nguyễn Thái Ngọc Duy2b1790f2019-04-16 09:33:32973 ret = get_oid_1(r, name, len, &oid, GET_OID_COMMITTISH);
Junio C Hamano4f7599a2005-08-21 09:43:54974 if (ret)
975 return ret;
Nguyễn Thái Ngọc Duy2b1790f2019-04-16 09:33:32976 commit = lookup_commit_reference(r, &oid);
Linus Torvalds621ff672008-03-14 18:49:40977 if (!commit)
David Turnerd1dd94b2019-01-18 04:19:43978 return MISSING_OBJECT;
Junio C Hamano4f7599a2005-08-21 09:43:54979
980 while (generation--) {
Linus Torvalds621ff672008-03-14 18:49:40981 if (parse_commit(commit) || !commit->parents)
David Turnerd1dd94b2019-01-18 04:19:43982 return MISSING_OBJECT;
Linus Torvalds621ff672008-03-14 18:49:40983 commit = commit->parents->item;
Junio C Hamano4f7599a2005-08-21 09:43:54984 }
brian m. carlsone82caf32017-07-13 23:49:28985 oidcpy(result, &commit->object.oid);
David Turnerd1dd94b2019-01-18 04:19:43986 return FOUND;
Junio C Hamano4f7599a2005-08-21 09:43:54987}
988
Nguyễn Thái Ngọc Duy2b1790f2019-04-16 09:33:32989struct object *repo_peel_to_type(struct repository *r, const char *name, int namelen,
990 struct object *o, enum object_type expected_type)
Junio C Hamano81776312007-12-24 08:51:01991{
992 if (name && !namelen)
993 namelen = strlen(name);
Junio C Hamano81776312007-12-24 08:51:01994 while (1) {
Nguyễn Thái Ngọc Duy2b1790f2019-04-16 09:33:32995 if (!o || (!o->parsed && !parse_object(r, &o->oid)))
Junio C Hamano81776312007-12-24 08:51:01996 return NULL;
Junio C Hamanoa6a3f2c2013-03-31 22:24:12997 if (expected_type == OBJ_ANY || o->type == expected_type)
Junio C Hamano81776312007-12-24 08:51:01998 return o;
999 if (o->type == OBJ_TAG)
1000 o = ((struct tag*) o)->tagged;
1001 else if (o->type == OBJ_COMMIT)
Nguyễn Thái Ngọc Duy2b1790f2019-04-16 09:33:321002 o = &(repo_get_commit_tree(r, ((struct commit *)o))->object);
Junio C Hamano81776312007-12-24 08:51:011003 else {
1004 if (name)
1005 error("%.*s: expected %s type, but the object "
1006 "dereferences to %s type",
Brandon Williamsdebca9d2018-02-14 18:59:241007 namelen, name, type_name(expected_type),
1008 type_name(o->type));
Junio C Hamano81776312007-12-24 08:51:011009 return NULL;
1010 }
1011 }
1012}
1013
Nguyễn Thái Ngọc Duy2b1790f2019-04-16 09:33:321014static int peel_onion(struct repository *r, const char *name, int len,
1015 struct object_id *oid, unsigned lookup_flags)
Junio C Hamano5385f522005-10-14 01:57:401016{
brian m. carlsonde37d502017-05-06 22:10:291017 struct object_id outer;
Junio C Hamano5385f522005-10-14 01:57:401018 const char *sp;
Linus Torvalds885a86a2006-06-14 23:45:131019 unsigned int expected_type = 0;
Junio C Hamano5385f522005-10-14 01:57:401020 struct object *o;
1021
1022 /*
1023 * "ref^{type}" dereferences ref repeatedly until you cannot
1024 * dereference anymore, or you get an object of given type,
1025 * whichever comes first. "ref^{}" means just dereference
1026 * tags until you get a non-tag. "ref^0" is a shorthand for
1027 * "ref^{commit}". "commit^{tree}" could be used to find the
1028 * top-level tree of the given commit.
1029 */
1030 if (len < 4 || name[len-1] != '}')
1031 return -1;
1032
1033 for (sp = name + len - 1; name <= sp; sp--) {
1034 int ch = *sp;
1035 if (ch == '{' && name < sp && sp[-1] == '^')
1036 break;
1037 }
1038 if (sp <= name)
1039 return -1;
1040
1041 sp++; /* beginning of type name, or closing brace for empty */
Christian Couder59556542013-11-30 20:55:401042 if (starts_with(sp, "commit}"))
Linus Torvalds19746322006-07-12 03:45:311043 expected_type = OBJ_COMMIT;
Christian Couder59556542013-11-30 20:55:401044 else if (starts_with(sp, "tag}"))
Richard Hansen75aa26d2013-09-03 19:50:161045 expected_type = OBJ_TAG;
Christian Couder59556542013-11-30 20:55:401046 else if (starts_with(sp, "tree}"))
Linus Torvalds19746322006-07-12 03:45:311047 expected_type = OBJ_TREE;
Christian Couder59556542013-11-30 20:55:401048 else if (starts_with(sp, "blob}"))
Linus Torvalds19746322006-07-12 03:45:311049 expected_type = OBJ_BLOB;
Christian Couder59556542013-11-30 20:55:401050 else if (starts_with(sp, "object}"))
Junio C Hamanoa6a3f2c2013-03-31 22:24:121051 expected_type = OBJ_ANY;
Junio C Hamano5385f522005-10-14 01:57:401052 else if (sp[0] == '}')
Linus Torvalds19746322006-07-12 03:45:311053 expected_type = OBJ_NONE;
Nguyễn Thái Ngọc Duy32574b62010-12-13 03:01:151054 else if (sp[0] == '/')
1055 expected_type = OBJ_COMMIT;
Junio C Hamano5385f522005-10-14 01:57:401056 else
1057 return -1;
1058
brian m. carlson321c89b2017-07-13 23:49:291059 lookup_flags &= ~GET_OID_DISAMBIGUATORS;
Junio C Hamanoe2643612012-07-02 17:00:401060 if (expected_type == OBJ_COMMIT)
brian m. carlson321c89b2017-07-13 23:49:291061 lookup_flags |= GET_OID_COMMITTISH;
Junio C Hamanoed1ca602013-03-31 22:19:521062 else if (expected_type == OBJ_TREE)
brian m. carlson321c89b2017-07-13 23:49:291063 lookup_flags |= GET_OID_TREEISH;
Junio C Hamanoe2643612012-07-02 17:00:401064
Nguyễn Thái Ngọc Duy2b1790f2019-04-16 09:33:321065 if (get_oid_1(r, name, sp - name - 2, &outer, lookup_flags))
Junio C Hamano5385f522005-10-14 01:57:401066 return -1;
1067
Nguyễn Thái Ngọc Duy2b1790f2019-04-16 09:33:321068 o = parse_object(r, &outer);
Junio C Hamano5385f522005-10-14 01:57:401069 if (!o)
1070 return -1;
Linus Torvalds885a86a2006-06-14 23:45:131071 if (!expected_type) {
Nguyễn Thái Ngọc Duy2b1790f2019-04-16 09:33:321072 o = deref_tag(r, o, name, sp - name - 2);
1073 if (!o || (!o->parsed && !parse_object(r, &o->oid)))
Junio C Hamano6e1c6c12005-10-20 05:48:161074 return -1;
brian m. carlsone82caf32017-07-13 23:49:281075 oidcpy(oid, &o->oid);
Nguyễn Thái Ngọc Duy32574b62010-12-13 03:01:151076 return 0;
Junio C Hamano5385f522005-10-14 01:57:401077 }
Nguyễn Thái Ngọc Duy32574b62010-12-13 03:01:151078
1079 /*
1080 * At this point, the syntax look correct, so
1081 * if we do not get the needed object, we should
1082 * barf.
1083 */
Nguyễn Thái Ngọc Duy2b1790f2019-04-16 09:33:321084 o = repo_peel_to_type(r, name, len, o, expected_type);
Nguyễn Thái Ngọc Duy32574b62010-12-13 03:01:151085 if (!o)
Junio C Hamano81776312007-12-24 08:51:011086 return -1;
Nguyễn Thái Ngọc Duy32574b62010-12-13 03:01:151087
brian m. carlsone82caf32017-07-13 23:49:281088 oidcpy(oid, &o->oid);
Nguyễn Thái Ngọc Duy32574b62010-12-13 03:01:151089 if (sp[0] == '/') {
1090 /* "$commit^{/foo}" */
1091 char *prefix;
1092 int ret;
1093 struct commit_list *list = NULL;
1094
Nguyễn Thái Ngọc Duy43228422010-12-15 09:02:541095 /*
1096 * $commit^{/}. Some regex implementation may reject.
1097 * We don't need regex anyway. '' pattern always matches.
1098 */
1099 if (sp[1] == '}')
1100 return 0;
1101
Nguyễn Thái Ngọc Duy32574b62010-12-13 03:01:151102 prefix = xstrndup(sp + 1, name + len - 1 - (sp + 1));
1103 commit_list_insert((struct commit *)o, &list);
Nguyễn Thái Ngọc Duy2b1790f2019-04-16 09:33:321104 ret = get_oid_oneline(r, prefix, oid, list);
Nguyễn Thái Ngọc Duy32574b62010-12-13 03:01:151105 free(prefix);
1106 return ret;
Junio C Hamano5385f522005-10-14 01:57:401107 }
1108 return 0;
1109}
1110
Nguyễn Thái Ngọc Duy0c6b5ba2019-04-16 09:33:301111static int get_describe_name(struct repository *r,
1112 const char *name, int len,
1113 struct object_id *oid)
Junio C Hamano7dd45e12006-09-20 23:11:081114{
1115 const char *cp;
brian m. carlson321c89b2017-07-13 23:49:291116 unsigned flags = GET_OID_QUIETLY | GET_OID_COMMIT;
Junio C Hamano7dd45e12006-09-20 23:11:081117
1118 for (cp = name + len - 1; name + 2 <= cp; cp--) {
1119 char ch = *cp;
René Scharfe6f75d452015-03-09 22:46:541120 if (!isxdigit(ch)) {
Junio C Hamano7dd45e12006-09-20 23:11:081121 /* We must be looking at g in "SOMETHING-g"
1122 * for it to be describe output.
1123 */
1124 if (ch == 'g' && cp[-1] == '-') {
1125 cp++;
1126 len -= cp - name;
Nguyễn Thái Ngọc Duy0c6b5ba2019-04-16 09:33:301127 return get_short_oid(r,
Nguyễn Thái Ngọc Duyc6c02352019-04-16 09:33:251128 cp, len, oid, flags);
Junio C Hamano7dd45e12006-09-20 23:11:081129 }
1130 }
1131 }
1132 return -1;
1133}
1134
Nguyễn Thái Ngọc Duy2b1790f2019-04-16 09:33:321135static enum get_oid_result get_oid_1(struct repository *r,
1136 const char *name, int len,
David Turnerd1dd94b2019-01-18 04:19:431137 struct object_id *oid,
1138 unsigned lookup_flags)
Junio C Hamano9938af62005-08-04 05:15:491139{
Junio C Hamano0601dbe2006-02-03 07:48:361140 int ret, has_suffix;
Junio C Hamano4f7599a2005-08-21 09:43:541141 const char *cp;
Junio C Hamano9938af62005-08-04 05:15:491142
Linus Torvalds621ff672008-03-14 18:49:401143 /*
1144 * "name~3" is "name^^^", "name~" is "name~1", and "name^" is "name^1".
Junio C Hamano4f7599a2005-08-21 09:43:541145 */
Junio C Hamano0601dbe2006-02-03 07:48:361146 has_suffix = 0;
Junio C Hamano4f7599a2005-08-21 09:43:541147 for (cp = name + len - 1; name <= cp; cp--) {
1148 int ch = *cp;
1149 if ('0' <= ch && ch <= '9')
1150 continue;
Junio C Hamano0601dbe2006-02-03 07:48:361151 if (ch == '~' || ch == '^')
1152 has_suffix = ch;
Junio C Hamano4f7599a2005-08-21 09:43:541153 break;
1154 }
Junio C Hamano0601dbe2006-02-03 07:48:361155
1156 if (has_suffix) {
René Scharfe59fa5f52019-09-15 12:10:281157 unsigned int num = 0;
Junio C Hamano4f7599a2005-08-21 09:43:541158 int len1 = cp - name;
1159 cp++;
René Scharfe59fa5f52019-09-15 12:10:281160 while (cp < name + len) {
1161 unsigned int digit = *cp++ - '0';
1162 if (unsigned_mult_overflows(num, 10))
1163 return MISSING_OBJECT;
1164 num *= 10;
1165 if (unsigned_add_overflows(num, digit))
1166 return MISSING_OBJECT;
1167 num += digit;
1168 }
Linus Torvalds621ff672008-03-14 18:49:401169 if (!num && len1 == len - 1)
1170 num = 1;
René Scharfe59fa5f52019-09-15 12:10:281171 else if (num > INT_MAX)
1172 return MISSING_OBJECT;
Linus Torvalds621ff672008-03-14 18:49:401173 if (has_suffix == '^')
Nguyễn Thái Ngọc Duy2b1790f2019-04-16 09:33:321174 return get_parent(r, name, len1, oid, num);
Junio C Hamano0601dbe2006-02-03 07:48:361175 /* else if (has_suffix == '~') -- goes without saying */
Nguyễn Thái Ngọc Duy2b1790f2019-04-16 09:33:321176 return get_nth_ancestor(r, name, len1, oid, num);
Junio C Hamano4f7599a2005-08-21 09:43:541177 }
1178
Nguyễn Thái Ngọc Duy2b1790f2019-04-16 09:33:321179 ret = peel_onion(r, name, len, oid, lookup_flags);
Junio C Hamano5385f522005-10-14 01:57:401180 if (!ret)
David Turnerd1dd94b2019-01-18 04:19:431181 return FOUND;
Junio C Hamano5385f522005-10-14 01:57:401182
Nguyễn Thái Ngọc Duy2b1790f2019-04-16 09:33:321183 ret = get_oid_basic(r, name, len, oid, lookup_flags);
Junio C Hamano9938af62005-08-04 05:15:491184 if (!ret)
David Turnerd1dd94b2019-01-18 04:19:431185 return FOUND;
Junio C Hamano7dd45e12006-09-20 23:11:081186
1187 /* It could be describe output that is "SOMETHING-gXXXX" */
Nguyễn Thái Ngọc Duy2b1790f2019-04-16 09:33:321188 ret = get_describe_name(r, name, len, oid);
Junio C Hamano7dd45e12006-09-20 23:11:081189 if (!ret)
David Turnerd1dd94b2019-01-18 04:19:431190 return FOUND;
Junio C Hamano7dd45e12006-09-20 23:11:081191
Nguyễn Thái Ngọc Duy2b1790f2019-04-16 09:33:321192 return get_short_oid(r, name, len, oid, lookup_flags);
Junio C Hamano9938af62005-08-04 05:15:491193}
1194
Junio C Hamanof7bff002010-08-02 21:37:061195/*
1196 * This interprets names like ':/Initial revision of "git"' by searching
1197 * through history and returning the first commit whose message starts
Junio C Hamano3d045892010-08-13 01:32:491198 * the given regular expression.
Junio C Hamanof7bff002010-08-02 21:37:061199 *
Will Palmer07698542016-01-31 00:06:011200 * For negative-matching, prefix the pattern-part with '!-', like: ':/!-WIP'.
1201 *
1202 * For a literal '!' character at the beginning of a pattern, you have to repeat
1203 * that, like: ':/!!foo'
1204 *
1205 * For future extension, all other sequences beginning with ':/!' are reserved.
Junio C Hamanof7bff002010-08-02 21:37:061206 */
Nguyễn Thái Ngọc Duy208acbf2014-03-25 13:23:261207
1208/* Remember to update object flag allocation in object.h */
Junio C Hamanof7bff002010-08-02 21:37:061209#define ONELINE_SEEN (1u<<20)
1210
Nguyễn Thái Ngọc Duyc931ba42019-04-16 09:33:331211struct handle_one_ref_cb {
1212 struct repository *repo;
1213 struct commit_list **list;
1214};
1215
Michael Haggerty9c5fe0b2015-05-25 18:39:051216static int handle_one_ref(const char *path, const struct object_id *oid,
1217 int flag, void *cb_data)
Johannes Schindelin28a4d942007-02-24 02:08:201218{
Nguyễn Thái Ngọc Duyc931ba42019-04-16 09:33:331219 struct handle_one_ref_cb *cb = cb_data;
1220 struct commit_list **list = cb->list;
1221 struct object *object = parse_object(cb->repo, oid);
Johannes Schindelin28a4d942007-02-24 02:08:201222 if (!object)
1223 return 0;
Martin Koegleraffeef12008-02-18 07:31:541224 if (object->type == OBJ_TAG) {
Nguyễn Thái Ngọc Duyc931ba42019-04-16 09:33:331225 object = deref_tag(cb->repo, object, path,
Stefan Bellera74093d2018-06-29 01:22:051226 strlen(path));
Martin Koegleraffeef12008-02-18 07:31:541227 if (!object)
1228 return 0;
1229 }
Johannes Schindelin28a4d942007-02-24 02:08:201230 if (object->type != OBJ_COMMIT)
1231 return 0;
René Scharfee8d1dfe2014-08-21 18:30:291232 commit_list_insert((struct commit *)object, list);
Johannes Schindelin28a4d942007-02-24 02:08:201233 return 0;
1234}
1235
Nguyễn Thái Ngọc Duy0bb41a12019-04-16 09:33:291236static int get_oid_oneline(struct repository *r,
1237 const char *prefix, struct object_id *oid,
1238 struct commit_list *list)
Johannes Schindelin28a4d942007-02-24 02:08:201239{
Nguyễn Thái Ngọc Duy84baa312010-12-13 03:01:141240 struct commit_list *backup = NULL, *l;
Junio C Hamano28042db2010-12-13 06:19:001241 int found = 0;
Will Palmer07698542016-01-31 00:06:011242 int negative = 0;
Linus Torvalds57895102010-04-23 15:20:201243 regex_t regex;
Johannes Schindelin28a4d942007-02-24 02:08:201244
1245 if (prefix[0] == '!') {
Johannes Schindelin28a4d942007-02-24 02:08:201246 prefix++;
Will Palmer07698542016-01-31 00:06:011247
1248 if (prefix[0] == '-') {
1249 prefix++;
1250 negative = 1;
1251 } else if (prefix[0] != '!') {
Junio C Hamanoe6a6a762016-02-24 21:25:521252 return -1;
Will Palmer07698542016-01-31 00:06:011253 }
Johannes Schindelin28a4d942007-02-24 02:08:201254 }
Linus Torvalds57895102010-04-23 15:20:201255
1256 if (regcomp(&regex, prefix, REG_EXTENDED))
Jeff Kingaac4fac2016-02-10 21:19:251257 return -1;
Linus Torvalds57895102010-04-23 15:20:201258
Nguyễn Thái Ngọc Duy84baa312010-12-13 03:01:141259 for (l = list; l; l = l->next) {
1260 l->item->object.flags |= ONELINE_SEEN;
Johannes Schindelin28a4d942007-02-24 02:08:201261 commit_list_insert(l->item, &backup);
Nguyễn Thái Ngọc Duy84baa312010-12-13 03:01:141262 }
Jim Meyeringed8ad7e2007-03-11 18:49:081263 while (list) {
Jeff Kingba41c1c2014-06-10 21:41:021264 const char *p, *buf;
Linus Torvalds1358e7d2007-03-12 18:30:381265 struct commit *commit;
Junio C Hamano28042db2010-12-13 06:19:001266 int matches;
Jim Meyeringed8ad7e2007-03-11 18:49:081267
1268 commit = pop_most_recent_commit(&list, ONELINE_SEEN);
Nguyễn Thái Ngọc Duy0bb41a12019-04-16 09:33:291269 if (!parse_object(r, &commit->object.oid))
Martin Koegler283cdbc2008-02-18 20:47:531270 continue;
Jeff King8597ea32014-06-10 21:44:131271 buf = get_commit_buffer(commit, NULL);
Jeff Kingba41c1c2014-06-10 21:41:021272 p = strstr(buf, "\n\n");
Will Palmer07698542016-01-31 00:06:011273 matches = negative ^ (p && !regexec(&regex, p + 2, 0, NULL, 0));
Jeff Kingba41c1c2014-06-10 21:41:021274 unuse_commit_buffer(commit, buf);
Junio C Hamano28042db2010-12-13 06:19:001275
1276 if (matches) {
brian m. carlsone82caf32017-07-13 23:49:281277 oidcpy(oid, &commit->object.oid);
Junio C Hamano28042db2010-12-13 06:19:001278 found = 1;
Johannes Schindelin28a4d942007-02-24 02:08:201279 break;
1280 }
1281 }
Linus Torvalds57895102010-04-23 15:20:201282 regfree(&regex);
Johannes Schindelin28a4d942007-02-24 02:08:201283 free_commit_list(list);
1284 for (l = backup; l; l = l->next)
1285 clear_commit_marks(l->item, ONELINE_SEEN);
Junio C Hamano28042db2010-12-13 06:19:001286 free_commit_list(backup);
1287 return found ? 0 : -1;
Johannes Schindelin28a4d942007-02-24 02:08:201288}
1289
Junio C Hamanoae5a6c32009-01-17 16:09:531290struct grab_nth_branch_switch_cbdata {
Junio C Hamano98f85ff2013-03-08 21:27:371291 int remaining;
René Scharfe4b3aa172019-09-18 16:35:381292 struct strbuf *sb;
Junio C Hamanoae5a6c32009-01-17 16:09:531293};
1294
brian m. carlson9461d272017-02-21 23:47:321295static int grab_nth_branch_switch(struct object_id *ooid, struct object_id *noid,
Johannes Schindelindddbad72017-04-26 19:29:311296 const char *email, timestamp_t timestamp, int tz,
Junio C Hamanoae5a6c32009-01-17 16:09:531297 const char *message, void *cb_data)
1298{
1299 struct grab_nth_branch_switch_cbdata *cb = cb_data;
Thomas Rasta884d0c2009-01-17 16:09:541300 const char *match = NULL, *target = NULL;
1301 size_t len;
Junio C Hamanoae5a6c32009-01-17 16:09:531302
Jeff King95b567c2014-06-18 19:48:291303 if (skip_prefix(message, "checkout: moving from ", &match))
Junio C Hamanod7c03c12009-01-21 08:37:381304 target = strstr(match, " to ");
Junio C Hamanoae5a6c32009-01-17 16:09:531305
Junio C Hamanoc8297742009-01-20 00:44:081306 if (!match || !target)
Junio C Hamanoae5a6c32009-01-17 16:09:531307 return 0;
Junio C Hamano98f85ff2013-03-08 21:27:371308 if (--(cb->remaining) == 0) {
1309 len = target - match;
René Scharfe4b3aa172019-09-18 16:35:381310 strbuf_reset(cb->sb);
1311 strbuf_add(cb->sb, match, len);
Junio C Hamano98f85ff2013-03-08 21:27:371312 return 1; /* we are done */
1313 }
Junio C Hamanoae5a6c32009-01-17 16:09:531314 return 0;
1315}
1316
1317/*
Junio C Hamanoae0ba8e2010-01-20 07:17:111318 * Parse @{-N} syntax, return the number of characters parsed
1319 * if successful; otherwise signal an error with negative value.
Junio C Hamanoae5a6c32009-01-17 16:09:531320 */
Nguyễn Thái Ngọc Duy23a57122019-04-16 09:33:261321static int interpret_nth_prior_checkout(struct repository *r,
1322 const char *name, int namelen,
Jeff King8cd42492014-01-15 08:31:571323 struct strbuf *buf)
Junio C Hamanoae5a6c32009-01-17 16:09:531324{
Junio C Hamanoc2883e62009-01-19 08:04:251325 long nth;
Junio C Hamano98f85ff2013-03-08 21:27:371326 int retval;
Junio C Hamanoae5a6c32009-01-17 16:09:531327 struct grab_nth_branch_switch_cbdata cb;
Thomas Rasta884d0c2009-01-17 16:09:541328 const char *brace;
1329 char *num_end;
Junio C Hamanoae5a6c32009-01-17 16:09:531330
Jeff King8cd42492014-01-15 08:31:571331 if (namelen < 4)
1332 return -1;
Junio C Hamanoae5a6c32009-01-17 16:09:531333 if (name[0] != '@' || name[1] != '{' || name[2] != '-')
1334 return -1;
Jeff King8cd42492014-01-15 08:31:571335 brace = memchr(name, '}', namelen);
Thomas Rasta884d0c2009-01-17 16:09:541336 if (!brace)
1337 return -1;
Junio C Hamano98f85ff2013-03-08 21:27:371338 nth = strtol(name + 3, &num_end, 10);
Thomas Rasta884d0c2009-01-17 16:09:541339 if (num_end != brace)
Junio C Hamanoae5a6c32009-01-17 16:09:531340 return -1;
Junio C Hamanoc2883e62009-01-19 08:04:251341 if (nth <= 0)
1342 return -1;
Junio C Hamano98f85ff2013-03-08 21:27:371343 cb.remaining = nth;
René Scharfe4b3aa172019-09-18 16:35:381344 cb.sb = buf;
Junio C Hamano98f85ff2013-03-08 21:27:371345
Nguyễn Thái Ngọc Duy23a57122019-04-16 09:33:261346 retval = refs_for_each_reflog_ent_reverse(get_main_ref_store(r),
1347 "HEAD", grab_nth_branch_switch, &cb);
1348 if (0 < retval) {
Junio C Hamano98f85ff2013-03-08 21:27:371349 retval = brace - name + 1;
Nguyễn Thái Ngọc Duy23a57122019-04-16 09:33:261350 } else
1351 retval = 0;
Junio C Hamano39765e52009-01-20 05:58:311352
Junio C Hamano39765e52009-01-20 05:58:311353 return retval;
Junio C Hamanoae5a6c32009-01-17 16:09:531354}
1355
Nguyễn Thái Ngọc Duy0daf7ff2019-04-16 09:33:411356int repo_get_oid_mb(struct repository *r,
1357 const char *name,
1358 struct object_id *oid)
Junio C Hamano619a6442009-10-18 19:34:561359{
1360 struct commit *one, *two;
1361 struct commit_list *mbs;
brian m. carlson151b2912016-09-05 20:08:071362 struct object_id oid_tmp;
Junio C Hamano619a6442009-10-18 19:34:561363 const char *dots;
1364 int st;
1365
1366 dots = strstr(name, "...");
1367 if (!dots)
Nguyễn Thái Ngọc Duy0daf7ff2019-04-16 09:33:411368 return repo_get_oid(r, name, oid);
Junio C Hamano619a6442009-10-18 19:34:561369 if (dots == name)
Nguyễn Thái Ngọc Duy0daf7ff2019-04-16 09:33:411370 st = repo_get_oid(r, "HEAD", &oid_tmp);
Junio C Hamano619a6442009-10-18 19:34:561371 else {
1372 struct strbuf sb;
1373 strbuf_init(&sb, dots - name);
1374 strbuf_add(&sb, name, dots - name);
Nguyễn Thái Ngọc Duy0daf7ff2019-04-16 09:33:411375 st = repo_get_oid_committish(r, sb.buf, &oid_tmp);
Junio C Hamano619a6442009-10-18 19:34:561376 strbuf_release(&sb);
1377 }
1378 if (st)
1379 return st;
Nguyễn Thái Ngọc Duy0daf7ff2019-04-16 09:33:411380 one = lookup_commit_reference_gently(r, &oid_tmp, 0);
Junio C Hamano619a6442009-10-18 19:34:561381 if (!one)
1382 return -1;
1383
Nguyễn Thái Ngọc Duy0daf7ff2019-04-16 09:33:411384 if (repo_get_oid_committish(r, dots[3] ? (dots + 3) : "HEAD", &oid_tmp))
Junio C Hamano619a6442009-10-18 19:34:561385 return -1;
Nguyễn Thái Ngọc Duy0daf7ff2019-04-16 09:33:411386 two = lookup_commit_reference_gently(r, &oid_tmp, 0);
Junio C Hamano619a6442009-10-18 19:34:561387 if (!two)
1388 return -1;
Nguyễn Thái Ngọc Duy34e77712019-06-27 09:28:521389 mbs = repo_get_merge_bases(r, one, two);
Junio C Hamano619a6442009-10-18 19:34:561390 if (!mbs || mbs->next)
1391 st = -1;
1392 else {
1393 st = 0;
brian m. carlson151b2912016-09-05 20:08:071394 oidcpy(oid, &mbs->item->object.oid);
Junio C Hamano619a6442009-10-18 19:34:561395 }
1396 free_commit_list(mbs);
1397 return st;
1398}
1399
Felipe Contreras9ba89f42013-09-02 06:34:301400/* parse @something syntax, when 'something' is not {.*} */
1401static int interpret_empty_at(const char *name, int namelen, int len, struct strbuf *buf)
1402{
1403 const char *next;
1404
1405 if (len || name[1] == '{')
1406 return -1;
1407
1408 /* make sure it's a single @, or @@{.*}, not @foo */
Jeff King8cd42492014-01-15 08:31:571409 next = memchr(name + len + 1, '@', namelen - len - 1);
Felipe Contreras9ba89f42013-09-02 06:34:301410 if (next && next[1] != '{')
1411 return -1;
1412 if (!next)
1413 next = name + namelen;
1414 if (next != name + 1)
1415 return -1;
1416
1417 strbuf_reset(buf);
1418 strbuf_add(buf, "HEAD", 4);
1419 return 1;
1420}
1421
Nguyễn Thái Ngọc Duy71588ed2019-04-16 09:33:281422static int reinterpret(struct repository *r,
1423 const char *name, int namelen, int len,
Jeff King0e9f62d2017-03-02 08:23:011424 struct strbuf *buf, unsigned allowed)
Felipe Contreras7a0a49a2013-05-07 22:04:301425{
1426 /* we have extra data, which might need further processing */
1427 struct strbuf tmp = STRBUF_INIT;
1428 int used = buf->len;
1429 int ret;
Jonathan Tana4f66a72020-09-01 22:28:071430 struct interpret_branch_name_options options = {
1431 .allowed = allowed
1432 };
Felipe Contreras7a0a49a2013-05-07 22:04:301433
1434 strbuf_add(buf, name + len, namelen - len);
Jonathan Tana4f66a72020-09-01 22:28:071435 ret = repo_interpret_branch_name(r, buf->buf, buf->len, &tmp, &options);
Felipe Contreras7a0a49a2013-05-07 22:04:301436 /* that data was not interpreted, remove our cruft */
1437 if (ret < 0) {
1438 strbuf_setlen(buf, used);
1439 return len;
1440 }
1441 strbuf_reset(buf);
1442 strbuf_addbuf(buf, &tmp);
1443 strbuf_release(&tmp);
1444 /* tweak for size of {-N} versus expanded ref name */
1445 return ret - used + len;
1446}
1447
Nguyễn Thái Ngọc Duyea1c8732019-04-16 09:33:271448static void set_shortened_ref(struct repository *r, struct strbuf *buf, const char *ref)
Jeff Kinga39c14a2014-01-15 08:26:331449{
Nguyễn Thái Ngọc Duyea1c8732019-04-16 09:33:271450 char *s = refs_shorten_unambiguous_ref(get_main_ref_store(r), ref, 0);
Jeff Kinga39c14a2014-01-15 08:26:331451 strbuf_reset(buf);
1452 strbuf_addstr(buf, s);
1453 free(s);
1454}
1455
Jeff King0e9f62d2017-03-02 08:23:011456static int branch_interpret_allowed(const char *refname, unsigned allowed)
1457{
1458 if (!allowed)
1459 return 1;
1460
1461 if ((allowed & INTERPRET_BRANCH_LOCAL) &&
1462 starts_with(refname, "refs/heads/"))
1463 return 1;
1464 if ((allowed & INTERPRET_BRANCH_REMOTE) &&
1465 starts_with(refname, "refs/remotes/"))
1466 return 1;
1467
1468 return 0;
1469}
1470
Nguyễn Thái Ngọc Duyea1c8732019-04-16 09:33:271471static int interpret_branch_mark(struct repository *r,
1472 const char *name, int namelen,
Jeff King48c58472015-05-21 04:45:431473 int at, struct strbuf *buf,
1474 int (*get_mark)(const char *, int),
1475 const char *(*get_data)(struct branch *,
Jeff King0e9f62d2017-03-02 08:23:011476 struct strbuf *),
Jonathan Tana4f66a72020-09-01 22:28:071477 const struct interpret_branch_name_options *options)
Jeff Kinga39c14a2014-01-15 08:26:331478{
1479 int len;
Jeff King48c58472015-05-21 04:45:431480 struct branch *branch;
1481 struct strbuf err = STRBUF_INIT;
1482 const char *value;
Jeff Kinga39c14a2014-01-15 08:26:331483
Jeff King48c58472015-05-21 04:45:431484 len = get_mark(name + at, namelen - at);
Jeff Kinga39c14a2014-01-15 08:26:331485 if (!len)
1486 return -1;
1487
Jeff King3f6eb302014-01-15 08:37:231488 if (memchr(name, ':', at))
1489 return -1;
1490
Jeff King48c58472015-05-21 04:45:431491 if (at) {
1492 char *name_str = xmemdupz(name, at);
1493 branch = branch_get(name_str);
1494 free(name_str);
1495 } else
1496 branch = branch_get(NULL);
1497
1498 value = get_data(branch, &err);
Jonathan Tanf24c30e2020-09-01 22:28:091499 if (!value) {
1500 if (options->nonfatal_dangling_mark) {
1501 strbuf_release(&err);
1502 return -1;
1503 } else {
1504 die("%s", err.buf);
1505 }
1506 }
Jeff King48c58472015-05-21 04:45:431507
Jonathan Tana4f66a72020-09-01 22:28:071508 if (!branch_interpret_allowed(value, options->allowed))
Jeff King0e9f62d2017-03-02 08:23:011509 return -1;
1510
Nguyễn Thái Ngọc Duyea1c8732019-04-16 09:33:271511 set_shortened_ref(r, buf, value);
Jeff Kinga39c14a2014-01-15 08:26:331512 return len + at;
1513}
1514
Nguyễn Thái Ngọc Duy8f56e9d2019-04-06 11:34:261515int repo_interpret_branch_name(struct repository *r,
1516 const char *name, int namelen,
1517 struct strbuf *buf,
Jonathan Tana4f66a72020-09-01 22:28:071518 const struct interpret_branch_name_options *options)
Junio C Hamanoae0ba8e2010-01-20 07:17:111519{
Jeff Kingf278f402014-01-15 08:27:321520 char *at;
Jeff King9892d5d2014-01-15 08:40:461521 const char *start;
Jeff King13228c32017-02-27 09:25:401522 int len;
Junio C Hamanoae0ba8e2010-01-20 07:17:111523
Felipe Contrerascf99a762013-09-02 06:34:291524 if (!namelen)
1525 namelen = strlen(name);
1526
Jonathan Tana4f66a72020-09-01 22:28:071527 if (!options->allowed || (options->allowed & INTERPRET_BRANCH_LOCAL)) {
Nguyễn Thái Ngọc Duy71588ed2019-04-16 09:33:281528 len = interpret_nth_prior_checkout(r, name, namelen, buf);
Jeff King0e9f62d2017-03-02 08:23:011529 if (!len) {
1530 return len; /* syntax Ok, not enough switches */
1531 } else if (len > 0) {
1532 if (len == namelen)
1533 return len; /* consumed all */
1534 else
Jonathan Tana4f66a72020-09-01 22:28:071535 return reinterpret(r, name, namelen, len, buf,
1536 options->allowed);
Jeff King0e9f62d2017-03-02 08:23:011537 }
Jeff Kingd46a8302010-01-28 09:52:221538 }
1539
Jeff King9892d5d2014-01-15 08:40:461540 for (start = name;
1541 (at = memchr(start, '@', namelen - (start - name)));
1542 start = at + 1) {
Felipe Contreras9ba89f42013-09-02 06:34:301543
Jonathan Tana4f66a72020-09-01 22:28:071544 if (!options->allowed || (options->allowed & INTERPRET_BRANCH_HEAD)) {
Jeff King0e9f62d2017-03-02 08:23:011545 len = interpret_empty_at(name, namelen, at - name, buf);
1546 if (len > 0)
Nguyễn Thái Ngọc Duy71588ed2019-04-16 09:33:281547 return reinterpret(r, name, namelen, len, buf,
Jonathan Tana4f66a72020-09-01 22:28:071548 options->allowed);
Jeff King0e9f62d2017-03-02 08:23:011549 }
Felipe Contreras9ba89f42013-09-02 06:34:301550
Nguyễn Thái Ngọc Duy71588ed2019-04-16 09:33:281551 len = interpret_branch_mark(r, name, namelen, at - name, buf,
Jeff King0e9f62d2017-03-02 08:23:011552 upstream_mark, branch_get_upstream,
Jonathan Tana4f66a72020-09-01 22:28:071553 options);
Jeff King9892d5d2014-01-15 08:40:461554 if (len > 0)
1555 return len;
Jeff Kingadfe5d02015-05-21 04:45:471556
Nguyễn Thái Ngọc Duy71588ed2019-04-16 09:33:281557 len = interpret_branch_mark(r, name, namelen, at - name, buf,
Jeff King0e9f62d2017-03-02 08:23:011558 push_mark, branch_get_push,
Jonathan Tana4f66a72020-09-01 22:28:071559 options);
Jeff King9892d5d2014-01-15 08:40:461560 if (len > 0)
1561 return len;
Zbigniew Jędrzejewski-Szmekbb0dab52012-04-14 07:54:331562 }
Felipe Contreras9ba89f42013-09-02 06:34:301563
Jeff Kinga39c14a2014-01-15 08:26:331564 return -1;
Junio C Hamanoae0ba8e2010-01-20 07:17:111565}
1566
Jeff King0e9f62d2017-03-02 08:23:011567void strbuf_branchname(struct strbuf *sb, const char *name, unsigned allowed)
Jonathan Nieder6bab74e2010-11-06 11:46:521568{
1569 int len = strlen(name);
Jonathan Tana4f66a72020-09-01 22:28:071570 struct interpret_branch_name_options options = {
1571 .allowed = allowed
1572 };
1573 int used = interpret_branch_name(name, len, sb, &options);
Junio C Hamano84cf2462013-05-15 21:32:301574
Junio C Hamano84cf2462013-05-15 21:32:301575 if (used < 0)
1576 used = 0;
1577 strbuf_add(sb, name + used, len - used);
Jonathan Nieder6bab74e2010-11-06 11:46:521578}
1579
1580int strbuf_check_branch_ref(struct strbuf *sb, const char *name)
1581{
Junio C Hamano7c3f8472017-10-17 07:08:081582 if (startup_info->have_repository)
1583 strbuf_branchname(sb, name, INTERPRET_BRANCH_LOCAL);
1584 else
1585 strbuf_addstr(sb, name);
Junio C Hamanoa625b092017-11-14 11:42:581586
1587 /*
1588 * This splice must be done even if we end up rejecting the
1589 * name; builtin/branch.c::copy_or_rename_branch() still wants
1590 * to see what the name expanded to so that "branch -m" can be
1591 * used as a tool to correct earlier mistakes.
1592 */
Jonathan Nieder6bab74e2010-11-06 11:46:521593 strbuf_splice(sb, 0, 0, "refs/heads/", 11);
Junio C Hamanoa625b092017-11-14 11:42:581594
1595 if (*name == '-' ||
1596 !strcmp(sb->buf, "refs/heads/HEAD"))
1597 return -1;
1598
Michael Haggerty8d9c5012011-09-15 21:10:251599 return check_refname_format(sb->buf, 0);
Jonathan Nieder6bab74e2010-11-06 11:46:521600}
1601
Junio C Hamanoae0ba8e2010-01-20 07:17:111602/*
brian m. carlsone82caf32017-07-13 23:49:281603 * This is like "get_oid_basic()", except it allows "object ID expressions",
Junio C Hamano9938af62005-08-04 05:15:491604 * notably "xyz^" for "parent of xyz"
1605 */
Nguyễn Thái Ngọc Duyec580ea2019-04-16 09:33:371606int repo_get_oid(struct repository *r, const char *name, struct object_id *oid)
brian m. carlson2764fd92016-04-17 23:10:361607{
brian m. carlsone82caf32017-07-13 23:49:281608 struct object_context unused;
Nguyễn Thái Ngọc Duyec580ea2019-04-16 09:33:371609 return get_oid_with_context(r, name, 0, oid, &unused);
brian m. carlson2764fd92016-04-17 23:10:361610}
1611
Paul-Sebastian Ungureanuf5116f42019-02-25 23:16:051612/*
1613 * This returns a non-zero value if the string (built using printf
1614 * format and the given arguments) is not a valid object.
1615 */
1616int get_oidf(struct object_id *oid, const char *fmt, ...)
1617{
1618 va_list ap;
1619 int ret;
1620 struct strbuf sb = STRBUF_INIT;
1621
1622 va_start(ap, fmt);
1623 strbuf_vaddf(&sb, fmt, ap);
1624 va_end(ap);
1625
1626 ret = get_oid(sb.buf, oid);
1627 strbuf_release(&sb);
1628
1629 return ret;
1630}
brian m. carlson2764fd92016-04-17 23:10:361631
1632/*
Richard Hansena8a54062013-09-04 19:04:311633 * Many callers know that the user meant to name a commit-ish by
Junio C Hamanocd74e472012-07-02 19:04:521634 * syntactical positions where the object name appears. Calling this
1635 * function allows the machinery to disambiguate shorter-than-unique
Richard Hansena8a54062013-09-04 19:04:311636 * abbreviated object names between commit-ish and others.
Junio C Hamanocd74e472012-07-02 19:04:521637 *
1638 * Note that this does NOT error out when the named object is not a
Richard Hansena8a54062013-09-04 19:04:311639 * commit-ish. It is merely to give a hint to the disambiguation
Junio C Hamanocd74e472012-07-02 19:04:521640 * machinery.
1641 */
Nguyễn Thái Ngọc Duy65e50462019-04-16 09:33:401642int repo_get_oid_committish(struct repository *r,
1643 const char *name,
1644 struct object_id *oid)
Junio C Hamanocd74e472012-07-02 19:04:521645{
1646 struct object_context unused;
Nguyễn Thái Ngọc Duy65e50462019-04-16 09:33:401647 return get_oid_with_context(r, name, GET_OID_COMMITTISH,
brian m. carlsone82caf32017-07-13 23:49:281648 oid, &unused);
Junio C Hamanocd74e472012-07-02 19:04:521649}
1650
Nguyễn Thái Ngọc Duy65e50462019-04-16 09:33:401651int repo_get_oid_treeish(struct repository *r,
1652 const char *name,
1653 struct object_id *oid)
Junio C Hamanodaba53a2012-07-03 06:35:051654{
1655 struct object_context unused;
Nguyễn Thái Ngọc Duy65e50462019-04-16 09:33:401656 return get_oid_with_context(r, name, GET_OID_TREEISH,
brian m. carlsone82caf32017-07-13 23:49:281657 oid, &unused);
Junio C Hamanodaba53a2012-07-03 06:35:051658}
1659
Nguyễn Thái Ngọc Duy65e50462019-04-16 09:33:401660int repo_get_oid_commit(struct repository *r,
1661 const char *name,
1662 struct object_id *oid)
Junio C Hamanodaba53a2012-07-03 06:35:051663{
1664 struct object_context unused;
Nguyễn Thái Ngọc Duy65e50462019-04-16 09:33:401665 return get_oid_with_context(r, name, GET_OID_COMMIT,
brian m. carlsone82caf32017-07-13 23:49:281666 oid, &unused);
Junio C Hamanodaba53a2012-07-03 06:35:051667}
1668
Nguyễn Thái Ngọc Duy65e50462019-04-16 09:33:401669int repo_get_oid_tree(struct repository *r,
1670 const char *name,
1671 struct object_id *oid)
Junio C Hamanodaba53a2012-07-03 06:35:051672{
1673 struct object_context unused;
Nguyễn Thái Ngọc Duy65e50462019-04-16 09:33:401674 return get_oid_with_context(r, name, GET_OID_TREE,
brian m. carlsone82caf32017-07-13 23:49:281675 oid, &unused);
Junio C Hamanodaba53a2012-07-03 06:35:051676}
1677
Nguyễn Thái Ngọc Duy65e50462019-04-16 09:33:401678int repo_get_oid_blob(struct repository *r,
1679 const char *name,
1680 struct object_id *oid)
Junio C Hamanodaba53a2012-07-03 06:35:051681{
1682 struct object_context unused;
Nguyễn Thái Ngọc Duy65e50462019-04-16 09:33:401683 return get_oid_with_context(r, name, GET_OID_BLOB,
brian m. carlsone82caf32017-07-13 23:49:281684 oid, &unused);
Martin Koeglera0cd87a2007-04-23 20:55:051685}
1686
Matthieu Moy009fee42009-12-07 10:10:501687/* Must be called only when object_name:filename doesn't exist. */
Nguyễn Thái Ngọc Duy50ddb082019-06-27 09:28:491688static void diagnose_invalid_oid_path(struct repository *r,
1689 const char *prefix,
brian m. carlsone82caf32017-07-13 23:49:281690 const char *filename,
1691 const struct object_id *tree_oid,
1692 const char *object_name,
1693 int object_name_len)
Matthieu Moy009fee42009-12-07 10:10:501694{
brian m. carlsone82caf32017-07-13 23:49:281695 struct object_id oid;
Elijah Newren5ec1e722019-04-05 15:00:121696 unsigned short mode;
Matthieu Moy009fee42009-12-07 10:10:501697
1698 if (!prefix)
1699 prefix = "";
1700
René Scharfedbe44fa2015-05-19 21:44:231701 if (file_exists(filename))
Jeff Kingb0418302020-01-25 00:13:011702 die(_("path '%s' exists on disk, but not in '%.*s'"),
René Scharfeb2981d02013-03-16 18:29:311703 filename, object_name_len, object_name);
Junio C Hamanoc7054202017-05-30 00:23:331704 if (is_missing_file_error(errno)) {
Jeff Kingb2724c82014-06-19 21:26:561705 char *fullname = xstrfmt("%s%s", prefix, filename);
Matthieu Moy009fee42009-12-07 10:10:501706
Nguyễn Thái Ngọc Duy50ddb082019-06-27 09:28:491707 if (!get_tree_entry(r, tree_oid, fullname, &oid, &mode)) {
Jeff Kingb0418302020-01-25 00:13:011708 die(_("path '%s' exists, but not '%s'\n"
1709 "hint: Did you mean '%.*s:%s' aka '%.*s:./%s'?"),
Matthieu Moy009fee42009-12-07 10:10:501710 fullname,
1711 filename,
René Scharfeb2981d02013-03-16 18:29:311712 object_name_len, object_name,
Michael J Grubere41d7182011-03-31 09:17:341713 fullname,
René Scharfeb2981d02013-03-16 18:29:311714 object_name_len, object_name,
Michael J Grubere41d7182011-03-31 09:17:341715 filename);
Matthieu Moy009fee42009-12-07 10:10:501716 }
Jeff Kingb0418302020-01-25 00:13:011717 die(_("path '%s' does not exist in '%.*s'"),
René Scharfeb2981d02013-03-16 18:29:311718 filename, object_name_len, object_name);
Matthieu Moy009fee42009-12-07 10:10:501719 }
1720}
1721
1722/* Must be called only when :stage:filename doesn't exist. */
Nguyễn Thái Ngọc Duy04884812019-04-16 09:33:341723static void diagnose_invalid_index_path(struct repository *r,
Nguyễn Thái Ngọc Duy3a7a6982019-01-12 02:13:281724 int stage,
Matthieu Moy009fee42009-12-07 10:10:501725 const char *prefix,
1726 const char *filename)
1727{
Nguyễn Thái Ngọc Duy04884812019-04-16 09:33:341728 struct index_state *istate = r->index;
Nguyễn Thái Ngọc Duy9c5e6c82013-07-09 15:29:001729 const struct cache_entry *ce;
Matthieu Moy009fee42009-12-07 10:10:501730 int pos;
1731 unsigned namelen = strlen(filename);
Jeff King43bb66a2015-09-24 21:07:521732 struct strbuf fullname = STRBUF_INIT;
Matthieu Moy009fee42009-12-07 10:10:501733
1734 if (!prefix)
1735 prefix = "";
1736
1737 /* Wrong stage number? */
Nguyễn Thái Ngọc Duy3a7a6982019-01-12 02:13:281738 pos = index_name_pos(istate, filename, namelen);
Matthieu Moy009fee42009-12-07 10:10:501739 if (pos < 0)
1740 pos = -pos - 1;
Nguyễn Thái Ngọc Duy3a7a6982019-01-12 02:13:281741 if (pos < istate->cache_nr) {
1742 ce = istate->cache[pos];
Markus Heidelberg77e84662010-02-28 15:49:151743 if (ce_namelen(ce) == namelen &&
1744 !memcmp(ce->name, filename, namelen))
Jeff Kingb0418302020-01-25 00:13:011745 die(_("path '%s' is in the index, but not at stage %d\n"
1746 "hint: Did you mean ':%d:%s'?"),
Markus Heidelberg77e84662010-02-28 15:49:151747 filename, stage,
1748 ce_stage(ce), filename);
1749 }
Matthieu Moy009fee42009-12-07 10:10:501750
1751 /* Confusion between relative and absolute filenames? */
Jeff King43bb66a2015-09-24 21:07:521752 strbuf_addstr(&fullname, prefix);
1753 strbuf_addstr(&fullname, filename);
Nguyễn Thái Ngọc Duy3a7a6982019-01-12 02:13:281754 pos = index_name_pos(istate, fullname.buf, fullname.len);
Matthieu Moy009fee42009-12-07 10:10:501755 if (pos < 0)
1756 pos = -pos - 1;
Nguyễn Thái Ngọc Duy3a7a6982019-01-12 02:13:281757 if (pos < istate->cache_nr) {
1758 ce = istate->cache[pos];
Jeff King43bb66a2015-09-24 21:07:521759 if (ce_namelen(ce) == fullname.len &&
1760 !memcmp(ce->name, fullname.buf, fullname.len))
Jeff Kingb0418302020-01-25 00:13:011761 die(_("path '%s' is in the index, but not '%s'\n"
1762 "hint: Did you mean ':%d:%s' aka ':%d:./%s'?"),
Jeff King43bb66a2015-09-24 21:07:521763 fullname.buf, filename,
1764 ce_stage(ce), fullname.buf,
Michael J Grubere41d7182011-03-31 09:17:341765 ce_stage(ce), filename);
Markus Heidelberg77e84662010-02-28 15:49:151766 }
Matthieu Moy009fee42009-12-07 10:10:501767
Nguyễn Thái Ngọc Duy04884812019-04-16 09:33:341768 if (repo_file_exists(r, filename))
Jeff Kingb0418302020-01-25 00:13:011769 die(_("path '%s' exists on disk, but not in the index"), filename);
Junio C Hamanoc7054202017-05-30 00:23:331770 if (is_missing_file_error(errno))
Jeff Kingb0418302020-01-25 00:13:011771 die(_("path '%s' does not exist (neither on disk nor in the index)"),
Matthieu Moy009fee42009-12-07 10:10:501772 filename);
1773
Jeff King43bb66a2015-09-24 21:07:521774 strbuf_release(&fullname);
Matthieu Moy009fee42009-12-07 10:10:501775}
1776
1777
Nguyễn Thái Ngọc Duy0381f7f2019-04-16 09:33:351778static char *resolve_relative_path(struct repository *r, const char *rel)
Nguyễn Thái Ngọc Duy979f79292010-11-28 03:37:321779{
Christian Couder59556542013-11-30 20:55:401780 if (!starts_with(rel, "./") && !starts_with(rel, "../"))
Nguyễn Thái Ngọc Duy979f79292010-11-28 03:37:321781 return NULL;
1782
Nguyễn Thái Ngọc Duy0381f7f2019-04-16 09:33:351783 if (r != the_repository || !is_inside_work_tree())
Jeff Kingb0418302020-01-25 00:13:011784 die(_("relative path syntax can't be used outside working tree"));
Nguyễn Thái Ngọc Duy979f79292010-11-28 03:37:321785
1786 /* die() inside prefix_path() if resolved path is outside worktree */
1787 return prefix_path(startup_info->prefix,
1788 startup_info->prefix ? strlen(startup_info->prefix) : 0,
1789 rel);
1790}
1791
Junio C Hamano7589e632019-02-07 06:05:221792static enum get_oid_result get_oid_with_context_1(struct repository *repo,
Nguyễn Thái Ngọc Duy3a7a6982019-01-12 02:13:281793 const char *name,
brian m. carlsone82caf32017-07-13 23:49:281794 unsigned flags,
1795 const char *prefix,
1796 struct object_id *oid,
1797 struct object_context *oc)
Clément Poulain573285e2010-06-09 17:02:061798{
Martin Koeglera0cd87a2007-04-23 20:55:051799 int ret, bracket_depth;
Junio C Hamano73b0e5a2006-04-22 00:31:041800 int namelen = strlen(name);
1801 const char *cp;
brian m. carlson321c89b2017-07-13 23:49:291802 int only_to_die = flags & GET_OID_ONLY_TO_DIE;
Linus Torvalds51196022006-04-18 23:45:161803
Jeff King7243ffd2016-09-26 11:59:151804 if (only_to_die)
brian m. carlson321c89b2017-07-13 23:49:291805 flags |= GET_OID_QUIETLY;
Jeff King7243ffd2016-09-26 11:59:151806
Clément Poulain573285e2010-06-09 17:02:061807 memset(oc, 0, sizeof(*oc));
1808 oc->mode = S_IFINVALID;
Jeff Kingd72cae12017-05-19 12:52:251809 strbuf_init(&oc->symlink_path, 0);
Nguyễn Thái Ngọc Duy2b1790f2019-04-16 09:33:321810 ret = get_oid_1(repo, name, namelen, oid, flags);
Junio C Hamano73b0e5a2006-04-22 00:31:041811 if (!ret)
1812 return ret;
Junio C Hamano33bd5982012-07-02 17:32:111813 /*
1814 * sha1:path --> object name of path in ent sha1
Nguyễn Thái Ngọc Duy979f79292010-11-28 03:37:321815 * :path -> object name of absolute path in index
1816 * :./path -> object name of path relative to cwd in index
Junio C Hamano73b0e5a2006-04-22 00:31:041817 * :[0-3]:path -> object name of path in index at stage
Matthieu Moy95ad6d22010-09-24 16:43:591818 * :/foo -> recent commit matching foo
Junio C Hamano73b0e5a2006-04-22 00:31:041819 */
1820 if (name[0] == ':') {
1821 int stage = 0;
Nguyễn Thái Ngọc Duy9c5e6c82013-07-09 15:29:001822 const struct cache_entry *ce;
Nguyễn Thái Ngọc Duy979f79292010-11-28 03:37:321823 char *new_path = NULL;
Junio C Hamano73b0e5a2006-04-22 00:31:041824 int pos;
Junio C Hamano2e83b662011-05-10 19:02:541825 if (!only_to_die && namelen > 2 && name[1] == '/') {
Nguyễn Thái Ngọc Duyc931ba42019-04-16 09:33:331826 struct handle_one_ref_cb cb;
Nguyễn Thái Ngọc Duy84baa312010-12-13 03:01:141827 struct commit_list *list = NULL;
Michael Haggerty2b2a5be2015-05-25 18:38:281828
Nguyễn Thái Ngọc Duyc931ba42019-04-16 09:33:331829 cb.repo = repo;
1830 cb.list = &list;
Junio C Hamano5ff4b922020-04-10 00:03:451831 refs_for_each_ref(get_main_ref_store(repo), handle_one_ref, &cb);
Jeff King02204612020-04-10 03:04:111832 refs_head_ref(get_main_ref_store(repo), handle_one_ref, &cb);
René Scharfee8d1dfe2014-08-21 18:30:291833 commit_list_sort_by_date(&list);
Nguyễn Thái Ngọc Duy0bb41a12019-04-16 09:33:291834 return get_oid_oneline(repo, name + 2, oid, list);
Nguyễn Thái Ngọc Duy84baa312010-12-13 03:01:141835 }
Junio C Hamano73b0e5a2006-04-22 00:31:041836 if (namelen < 3 ||
1837 name[2] != ':' ||
1838 name[1] < '0' || '3' < name[1])
1839 cp = name + 1;
1840 else {
1841 stage = name[1] - '0';
1842 cp = name + 3;
Linus Torvalds51196022006-04-18 23:45:161843 }
Nguyễn Thái Ngọc Duy0381f7f2019-04-16 09:33:351844 new_path = resolve_relative_path(repo, cp);
Junio C Hamano3d6e0f72010-12-09 21:38:051845 if (!new_path) {
1846 namelen = namelen - (cp - name);
1847 } else {
1848 cp = new_path;
1849 namelen = strlen(cp);
1850 }
Clément Poulain573285e2010-06-09 17:02:061851
brian m. carlson321c89b2017-07-13 23:49:291852 if (flags & GET_OID_RECORD_PATH)
Jeff Kingdc944b62017-05-19 12:54:431853 oc->path = xstrdup(cp);
Clément Poulain573285e2010-06-09 17:02:061854
Jeff King581d2fd2019-05-14 13:54:551855 if (!repo->index || !repo->index->cache)
Nguyễn Thái Ngọc Duyefe461b2019-04-16 09:33:361856 repo_read_index(repo);
Nguyễn Thái Ngọc Duy3a7a6982019-01-12 02:13:281857 pos = index_name_pos(repo->index, cp, namelen);
Junio C Hamano73b0e5a2006-04-22 00:31:041858 if (pos < 0)
1859 pos = -pos - 1;
Nguyễn Thái Ngọc Duy3a7a6982019-01-12 02:13:281860 while (pos < repo->index->cache_nr) {
1861 ce = repo->index->cache[pos];
Junio C Hamano73b0e5a2006-04-22 00:31:041862 if (ce_namelen(ce) != namelen ||
1863 memcmp(ce->name, cp, namelen))
1864 break;
1865 if (ce_stage(ce) == stage) {
brian m. carlsone82caf32017-07-13 23:49:281866 oidcpy(oid, &ce->oid);
Kirill Smelkov90064712010-09-29 11:35:241867 oc->mode = ce->ce_mode;
Nguyễn Thái Ngọc Duy979f79292010-11-28 03:37:321868 free(new_path);
Junio C Hamano73b0e5a2006-04-22 00:31:041869 return 0;
1870 }
Junio C Hamanoe7cef452006-05-08 22:44:061871 pos++;
Junio C Hamano73b0e5a2006-04-22 00:31:041872 }
Junio C Hamano2e83b662011-05-10 19:02:541873 if (only_to_die && name[1] && name[1] != '/')
Nguyễn Thái Ngọc Duy04884812019-04-16 09:33:341874 diagnose_invalid_index_path(repo, stage, prefix, cp);
Nguyễn Thái Ngọc Duy979f79292010-11-28 03:37:321875 free(new_path);
Junio C Hamano73b0e5a2006-04-22 00:31:041876 return -1;
1877 }
Shawn Pearcecce91a22006-05-19 07:29:431878 for (cp = name, bracket_depth = 0; *cp; cp++) {
1879 if (*cp == '{')
1880 bracket_depth++;
1881 else if (bracket_depth && *cp == '}')
1882 bracket_depth--;
1883 else if (!bracket_depth && *cp == ':')
1884 break;
1885 }
1886 if (*cp == ':') {
brian m. carlsone82caf32017-07-13 23:49:281887 struct object_id tree_oid;
René Scharfeb2981d02013-03-16 18:29:311888 int len = cp - name;
Jeff King8a10fea2016-09-26 11:59:411889 unsigned sub_flags = flags;
1890
brian m. carlson321c89b2017-07-13 23:49:291891 sub_flags &= ~GET_OID_DISAMBIGUATORS;
1892 sub_flags |= GET_OID_TREEISH;
Jeff King8a10fea2016-09-26 11:59:411893
Nguyễn Thái Ngọc Duy2b1790f2019-04-16 09:33:321894 if (!get_oid_1(repo, name, len, &tree_oid, sub_flags)) {
Matthieu Moy009fee42009-12-07 10:10:501895 const char *filename = cp+1;
Nguyễn Thái Ngọc Duy979f79292010-11-28 03:37:321896 char *new_filename = NULL;
1897
Nguyễn Thái Ngọc Duy0381f7f2019-04-16 09:33:351898 new_filename = resolve_relative_path(repo, filename);
Nguyễn Thái Ngọc Duy979f79292010-11-28 03:37:321899 if (new_filename)
1900 filename = new_filename;
brian m. carlson321c89b2017-07-13 23:49:291901 if (flags & GET_OID_FOLLOW_SYMLINKS) {
Nguyễn Thái Ngọc Duy0dd1f0c2019-06-27 09:28:501902 ret = get_tree_entry_follow_symlinks(repo, &tree_oid,
brian m. carlson3b683bc2018-05-02 00:25:401903 filename, oid, &oc->symlink_path,
David Turnerc4ec9672015-05-20 17:03:391904 &oc->mode);
1905 } else {
Nguyễn Thái Ngọc Duy50ddb082019-06-27 09:28:491906 ret = get_tree_entry(repo, &tree_oid, filename, oid,
brian m. carlson916bc352018-03-12 02:27:511907 &oc->mode);
David Turnerc4ec9672015-05-20 17:03:391908 if (ret && only_to_die) {
Nguyễn Thái Ngọc Duy50ddb082019-06-27 09:28:491909 diagnose_invalid_oid_path(repo, prefix,
David Turnerc4ec9672015-05-20 17:03:391910 filename,
brian m. carlsone82caf32017-07-13 23:49:281911 &tree_oid,
David Turnerc4ec9672015-05-20 17:03:391912 name, len);
1913 }
Matthieu Moy009fee42009-12-07 10:10:501914 }
brian m. carlson321c89b2017-07-13 23:49:291915 if (flags & GET_OID_RECORD_PATH)
Jeff Kingdc944b62017-05-19 12:54:431916 oc->path = xstrdup(filename);
Clément Poulain573285e2010-06-09 17:02:061917
Nguyễn Thái Ngọc Duy979f79292010-11-28 03:37:321918 free(new_filename);
Matthieu Moy009fee42009-12-07 10:10:501919 return ret;
1920 } else {
Junio C Hamano2e83b662011-05-10 19:02:541921 if (only_to_die)
Jeff Kingb0418302020-01-25 00:13:011922 die(_("invalid object name '%.*s'."), len, name);
Matthieu Moy009fee42009-12-07 10:10:501923 }
Linus Torvalds51196022006-04-18 23:45:161924 }
1925 return ret;
Junio C Hamano9938af62005-08-04 05:15:491926}
Junio C Hamanof01cc142012-07-02 17:19:351927
Junio C Hamano8c135ea2012-07-02 18:01:251928/*
1929 * Call this function when you know "name" given by the end user must
1930 * name an object but it doesn't; the function _may_ die with a better
1931 * diagnostic message than "no such object 'name'", e.g. "Path 'doc' does not
1932 * exist in 'HEAD'" when given "HEAD:doc", or it may return in which case
1933 * you have a chance to diagnose the error further.
1934 */
Nguyễn Thái Ngọc Duye270f422019-04-16 09:33:391935void maybe_die_on_misspelt_object_name(struct repository *r,
1936 const char *name,
1937 const char *prefix)
Junio C Hamanof01cc142012-07-02 17:19:351938{
1939 struct object_context oc;
brian m. carlsone82caf32017-07-13 23:49:281940 struct object_id oid;
Nguyễn Thái Ngọc Duye270f422019-04-16 09:33:391941 get_oid_with_context_1(r, name, GET_OID_ONLY_TO_DIE,
Nguyễn Thái Ngọc Duy3a7a6982019-01-12 02:13:281942 prefix, &oid, &oc);
Junio C Hamano8c135ea2012-07-02 18:01:251943}
1944
Duy Nguyen127b48f2019-02-12 12:43:231945enum get_oid_result get_oid_with_context(struct repository *repo,
1946 const char *str,
1947 unsigned flags,
1948 struct object_id *oid,
1949 struct object_context *oc)
Junio C Hamanof01cc142012-07-02 17:19:351950{
brian m. carlson321c89b2017-07-13 23:49:291951 if (flags & GET_OID_FOLLOW_SYMLINKS && flags & GET_OID_ONLY_TO_DIE)
Johannes Schindelin033abf92018-05-02 09:38:391952 BUG("incompatible flags for get_sha1_with_context");
Nguyễn Thái Ngọc Duy3a7a6982019-01-12 02:13:281953 return get_oid_with_context_1(repo, str, flags, NULL, oid, oc);
Junio C Hamanof01cc142012-07-02 17:19:351954}