1 /* Helper program for git-cinnabar
2 *
3 * It receives commands on stdin and outputs results on stdout.
4 * The following commands are supported:
5 * - git2hg <committish>
6 * Returns the contents of the git note containing git->hg metadata
7 * for the given commit in a `cat-file --batch`-like format.
8 * - hg2git <hg_sha1>
9 * Returns the sha1 of the git object corresponding to the given
10 * mercurial sha1.
11 * - manifest <hg_sha1>
12 * Returns the contents of the mercurial manifest with the given
13 * mercurial sha1, preceded by its length in text form, and followed
14 * by a carriage return.
15 * - check-manifest <hg_sha1>
16 * Returns 'ok' when the sha1 of the contents of the mercurial manifest
17 * matches the manifest sha1, otherwise returns 'error'.
18 * - cat-file <object>
19 * Returns the contents of the given git object, in a `cat-file
20 * --batch`-like format.
21 * - connect <url>
22 * Connects to the mercurial repository at the given url. The helper then
23 * expects one of the following commands:
24 * - state
25 * This prints out three blocks of data, being the result of the
26 * following commands on the repository: branchmap, heads, bookmarks.
27 * - known <node>+
28 * Calls the "known" command on the repository and returns the
29 * corresponding result.
30 * - listkeys <namespace>
31 * Calls the "listkeys" command on the repository and returns the
32 * corresponding result.
33 * - getbundle <heads> <common> <bundle2caps>
34 * Calls the "getbundle" command on the repository and streams a
35 * changegroup in result. `heads` and `common` are comma separated
36 * lists of changesets.
37 * - unbundle <head>+
38 * Calls the "unbundle command on the repository.
39 * - pushkey <namespace> <key> <old> <new>
40 * Calls the "pushkey" command on the repository and returns the
41 * corresponding result.
42 * - lookup <key>
43 * Calls the "lookup" command on the repository and returns the
44 * corresponding result.
45 */
46
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50
51 #include "cache.h"
52 #include "attr.h"
53 #include "blob.h"
54 #include "commit.h"
55 #include "config.h"
56 #include "diff.h"
57 #include "diffcore.h"
58 #include "exec-cmd.h"
59 #include "hashmap.h"
60 #include "log-tree.h"
61 #include "shallow.h"
62 #include "strslice.h"
63 #include "strbuf.h"
64 #include "string-list.h"
65 #include "streaming.h"
66 #include "object.h"
67 #include "oidset.h"
68 #include "progress.h"
69 #include "quote.h"
70 #include "replace-object.h"
71 #include "revision.h"
72 #include "tree.h"
73 #include "tree-walk.h"
74 #include "hg-connect.h"
75 #include "hg-data.h"
76 #include "cinnabar-helper.h"
77 #include "cinnabar-fast-import.h"
78 #include "cinnabar-notes.h"
79 #include "which.h"
80
81 #define _STRINGIFY(s) # s
82 #define STRINGIFY(s) _STRINGIFY(s)
83
84 #ifndef HELPER_HASH
85 #define HELPER_HASH unknown
86 #endif
87
88 #define CMD_VERSION 3003
89
90 #define MIN_CMD_VERSION 3003
91
92 static const char NULL_NODE[] = "0000000000000000000000000000000000000000";
93
94 #define MODE_IMPORT 0x01
95 #define MODE_WIRE 0x02
96
97 static int mode = 0xff; // Enable everything by default
98
99 struct notes_tree git2hg, hg2git, files_meta;
100
101 // XXX: Should use a hg-specific oidset type.
102 struct oidset hg2git_seen = OIDSET_INIT;
103
104 int metadata_flags = 0;
105 int cinnabar_check = 0;
106 int cinnabar_experiments = 0;
107
config(const char * name,struct strbuf * result)108 static int config(const char *name, struct strbuf *result)
109 {
110 struct strbuf key = STRBUF_INIT;
111 char *p, *end;
112 const char *val;
113
114 strbuf_addstr(&key, "GIT_CINNABAR_");
115 strbuf_addstr(&key, name);
116 for (p = key.buf + sizeof("git_cinnabar"), end = key.buf + key.len;
117 p < end; p++)
118 *p = toupper(*p);
119 val = getenv(key.buf);
120 if (!val) {
121 strbuf_release(&key);
122 strbuf_addstr(&key, "cinnabar.");
123 strbuf_addstr(&key, name);
124 if (git_config_get_value(key.buf, &val)) {
125 strbuf_release(&key);
126 return 1;
127 }
128 }
129 strbuf_addstr(result, val);
130 strbuf_release(&key);
131 return 0;
132 }
133
cleanup_object_array_entry(struct object_array_entry * entry,void * data)134 static int cleanup_object_array_entry(struct object_array_entry *entry, void *data)
135 {
136 if (entry->item->type == OBJ_TREE)
137 free_tree_buffer((struct tree *)entry->item);
138 return 1;
139 }
140
rev_info_release(struct rev_info * revs)141 static void rev_info_release(struct rev_info *revs)
142 {
143 int i;
144
145 object_array_filter(&revs->pending, cleanup_object_array_entry, NULL);
146 object_array_clear(&revs->pending);
147 object_array_clear(&revs->boundary_commits);
148 for (i = 0; i < revs->cmdline.nr; i++)
149 free((void *)revs->cmdline.rev[i].name);
150 free(revs->cmdline.rev);
151 clear_pathspec(&revs->prune_data);
152 clear_pathspec(&revs->pruning.pathspec);
153 clear_pathspec(&revs->diffopt.pathspec);
154 revs->cmdline.rev = NULL;
155 for (i = 0; i < revs->treesame.size; i++)
156 if (revs->treesame.entries[i].base)
157 free(revs->treesame.entries[i].decoration);
158 free(revs->treesame.entries);
159 }
160
split_command(char * line,const char ** command,struct string_list * args)161 static void split_command(char *line, const char **command,
162 struct string_list *args)
163 {
164 struct string_list split_line = STRING_LIST_INIT_NODUP;
165 string_list_split_in_place(&split_line, line, ' ', 1);
166 *command = split_line.items[0].string;
167 if (split_line.nr > 1)
168 string_list_split_in_place(
169 args, split_line.items[1].string, ' ', -1);
170 string_list_clear(&split_line, 0);
171 }
172
send_buffer(struct strbuf * buf)173 static void send_buffer(struct strbuf *buf)
174 {
175 if (buf) {
176 struct strbuf header = STRBUF_INIT;
177
178 strbuf_addf(&header, "%lu\n", buf->len);
179 write_or_die(1, header.buf, header.len);
180 strbuf_release(&header);
181
182 write_or_die(1, buf->buf, buf->len);
183 write_or_die(1, "\n", 1);
184 } else {
185 write_or_die(1, "-1\n\n", 4);
186 }
187 }
188
189 /* Send git object info and content to stdout, like cat-file --batch does. */
send_object(const struct object_id * oid)190 static void send_object(const struct object_id *oid)
191 {
192 struct strbuf header = STRBUF_INIT;
193 enum object_type type;
194 unsigned long sz;
195 struct git_istream *st;
196
197 st = open_istream(the_repository, oid, &type, &sz, NULL);
198
199 if (!st)
200 die("open_istream failed for %s", oid_to_hex(oid));
201
202 strbuf_addf(&header, "%s %s %lu\n", oid_to_hex(oid), type_name(type),
203 sz);
204
205 write_or_die(1, header.buf, header.len);
206
207 strbuf_release(&header);
208
209 for (;;) {
210 char buf[1024 * 16];
211 ssize_t wrote;
212 ssize_t readlen = read_istream(st, buf, sizeof(buf));
213
214 if (readlen <= 0)
215 break;
216
217 wrote = write_in_full(1, buf, readlen);
218 if (wrote < readlen)
219 break;
220
221 sz -= wrote;
222 }
223
224 if (sz != 0)
225 die("Failed to write object");
226
227 write_or_die(1, "\n", 1);
228
229 close_istream(st);
230 }
231
do_cat_file(struct string_list * args)232 static void do_cat_file(struct string_list *args)
233 {
234 struct object_id oid;
235
236 if (args->nr != 1)
237 goto not_found;
238
239 if (get_oid(args->items[0].string, &oid))
240 goto not_found;
241
242 send_object(&oid);
243 return;
244
245 not_found:
246 write_or_die(1, NULL_NODE, 40);
247 write_or_die(1, "\n", 1);
248 }
249
250 struct ls_tree_context {
251 struct strbuf buf;
252 struct object_list *list;
253 int recursive;
254 };
255
fill_ls_tree(const struct object_id * oid,struct strbuf * base,const char * pathname,unsigned mode,void * context)256 static int fill_ls_tree(const struct object_id *oid, struct strbuf *base,
257 const char *pathname, unsigned mode, void *context)
258 {
259 struct ls_tree_context *ctx = context;
260 struct strbuf *buf = &ctx->buf;
261 const char *type = blob_type;
262
263 if (S_ISGITLINK(mode)) {
264 type = commit_type;
265 } else if (S_ISDIR(mode)) {
266 object_list_insert((struct object *)lookup_tree(the_repository, oid),
267 &ctx->list);
268 if (ctx->recursive)
269 return READ_TREE_RECURSIVE;
270 type = tree_type;
271 }
272
273 strbuf_addf(buf, "%06o %s %s\t", mode, type, oid_to_hex(oid));
274 strbuf_addbuf(buf, base);
275 strbuf_addstr(buf, pathname);
276 strbuf_addch(buf, '\0');
277 return 0;
278 }
279
do_ls_tree(struct string_list * args)280 static void do_ls_tree(struct string_list *args)
281 {
282 struct object_id oid;
283 struct tree *tree = NULL;
284 struct ls_tree_context ctx = { STRBUF_INIT, NULL, 0 };
285 struct pathspec match_all;
286
287 if (args->nr == 2) {
288 if (strcmp(args->items[1].string, "-r"))
289 goto not_found;
290 ctx.recursive = 1;
291 } else if (args->nr != 1)
292 goto not_found;
293
294 if (get_oid(args->items[0].string, &oid))
295 goto not_found;
296
297 tree = parse_tree_indirect(&oid);
298 if (!tree)
299 goto not_found;
300
301 memset(&match_all, 0, sizeof(match_all));
302 read_tree(the_repository, tree, &match_all, fill_ls_tree, &ctx);
303 send_buffer(&ctx.buf);
304 strbuf_release(&ctx.buf);
305
306 while (ctx.list) {
307 struct object *obj = ctx.list->item;
308 struct object_list *elem = ctx.list;
309 ctx.list = elem->next;
310 free(elem);
311 free_tree_buffer((struct tree *)obj);
312 }
313 return;
314 not_found:
315 write_or_die(1, "0\n\n", 3);
316 }
317
string_list_to_argv(struct string_list * args)318 static const char **string_list_to_argv(struct string_list *args)
319 {
320 const char **argv = malloc(sizeof(char *) * (args->nr + 2));
321 int i;
322
323 argv[0] = "";
324 for (i = 0; i < args->nr; i++) {
325 argv[i + 1] = args->items[i].string;
326 }
327 argv[args->nr + 1] = NULL;
328
329 return argv;
330 }
331
do_rev_list(struct string_list * args)332 static void do_rev_list(struct string_list *args)
333 {
334 struct rev_info revs;
335 struct commit *commit;
336 struct strbuf buf = STRBUF_INIT;
337 const char **argv = string_list_to_argv(args);
338
339 init_revisions(&revs, NULL);
340 // Note: we do a pass through, but don't make much effort to actually
341 // support all the options properly.
342 setup_revisions(args->nr + 1, argv, &revs, NULL);
343 free(argv);
344
345 // Hack to force simplify_commit to save parents. full_diff is only
346 // checked for there or in setup_revisions so there is no other side
347 // effect.
348 revs.full_diff = 1;
349
350 if (prepare_revision_walk(&revs))
351 die("revision walk setup failed");
352
353 while ((commit = get_revision(&revs)) != NULL) {
354 struct commit_list *parent;
355 struct commit_graft *graft;
356 if (commit->object.flags & BOUNDARY)
357 strbuf_addch(&buf, '-');
358 strbuf_addstr(&buf, oid_to_hex(&commit->object.oid));
359 strbuf_addch(&buf, ' ');
360 strbuf_addstr(&buf, oid_to_hex(get_commit_tree_oid(commit)));
361 parent = commit->parents;
362 if (!parent && is_repository_shallow(the_repository) &&
363 (graft = lookup_commit_graft(
364 the_repository, &commit->object.oid)) != NULL &&
365 graft->nr_parent < 0) {
366 strbuf_addstr(&buf, " shallow");
367 if (revs.boundary)
368 strbuf_addstr(&buf, "\n-shallow shallow");
369 } else while (parent) {
370 strbuf_addch(&buf, ' ');
371 strbuf_addstr(&buf, oid_to_hex(
372 &parent->item->object.oid));
373 parent = parent->next;
374 }
375 strbuf_addch(&buf, '\n');
376
377 // If parents were altered by simplify_commit, we want to
378 // restore them for any subsequent operation on the commit.
379 //
380 // get_saved_parents returning NULL means there is no saved
381 // parents for the commit. If there was a saved value of null,
382 // it would mean the commit was a root in the first place, but
383 // then why would it have been saved?
384 parent = get_saved_parents(&revs, commit);
385 if (parent && parent != commit->parents) {
386 free_commit_list(commit->parents);
387 commit->parents = copy_commit_list(parent);
388 }
389 }
390
391 // More extensive than reset_revision_walk(). Otherwise --boundary
392 // and pathspecs don't work properly.
393 clear_object_flags(ALL_REV_FLAGS | TOPO_WALK_EXPLORED | TOPO_WALK_INDEGREE);
394 send_buffer(&buf);
395 strbuf_release(&buf);
396 rev_info_release(&revs);
397 }
398
strbuf_diff_tree(struct diff_queue_struct * q,struct diff_options * opt,void * data)399 static void strbuf_diff_tree(struct diff_queue_struct *q,
400 struct diff_options *opt, void *data)
401 {
402 struct strbuf *buf = data;
403 int i;
404
405 for (i = 0; i < q->nr; i++) {
406 struct diff_filepair *p = q->queue[i];
407 if (p->status == 0)
408 die("internal diff status error");
409 if (p->status == DIFF_STATUS_UNKNOWN)
410 continue;
411 strbuf_addf(buf, "%06o %06o %s %s %c",
412 p->one->mode,
413 p->two->mode,
414 oid_to_hex(&p->one->oid),
415 oid_to_hex(&p->two->oid),
416 p->status);
417 if (p->score)
418 strbuf_addf(buf, "%03d",
419 (int)(p->score * 100 / MAX_SCORE));
420 strbuf_addch(buf, '\t');
421 if (p->status == DIFF_STATUS_COPIED ||
422 p->status == DIFF_STATUS_RENAMED) {
423 strbuf_addstr(buf, p->one->path);
424 strbuf_addch(buf, '\0');
425 strbuf_addstr(buf, p->two->path);
426 } else {
427 strbuf_addstr(buf, p->one->mode ? p->one->path
428 : p->two->path);
429 }
430 strbuf_addch(buf, '\0');
431 }
432 }
433
do_diff_tree(struct string_list * args)434 static void do_diff_tree(struct string_list *args)
435 {
436 struct rev_info revs;
437 struct strbuf buf = STRBUF_INIT;
438 const char **argv = string_list_to_argv(args);
439
440 init_revisions(&revs, NULL);
441 revs.diff = 1;
442 // Note: we do a pass through, but don't make much effort to actually
443 // support all the options properly.
444 setup_revisions(args->nr + 1, argv, &revs, NULL);
445 revs.diffopt.output_format = DIFF_FORMAT_CALLBACK;
446 revs.diffopt.format_callback = strbuf_diff_tree;
447 revs.diffopt.format_callback_data = &buf;
448 revs.diffopt.flags.recursive = 1;
449 free(argv);
450
451 if (revs.pending.nr != 2)
452 die("diff-tree needs two revs");
453
454 diff_tree_oid(&revs.pending.objects[0].item->oid,
455 &revs.pending.objects[1].item->oid,
456 "", &revs.diffopt);
457 log_tree_diff_flush(&revs);
458 send_buffer(&buf);
459 strbuf_release(&buf);
460 rev_info_release(&revs);
461 }
462
do_get_note(struct notes_tree * t,struct string_list * args)463 static void do_get_note(struct notes_tree *t, struct string_list *args)
464 {
465 struct object_id oid;
466 const struct object_id *note;
467
468 if (args->nr != 1)
469 goto not_found;
470
471 ensure_notes(t);
472
473 if (get_oid_committish(args->items[0].string, &oid))
474 goto not_found;
475
476 note = get_note(t, lookup_replace_object(the_repository, &oid));
477 if (!note)
478 goto not_found;
479
480 send_object(note);
481 return;
482
483 not_found:
484 write_or_die(1, NULL_NODE, 40);
485 write_or_die(1, "\n", 1);
486 }
487
get_abbrev_sha1_hex(const char * hex,unsigned char * sha1)488 static size_t get_abbrev_sha1_hex(const char *hex, unsigned char *sha1)
489 {
490 const char *hex_start = hex;
491 unsigned char *end = sha1 + 20;
492 while (sha1 < end) {
493 unsigned int val;
494 if (!hex[0])
495 val = 0xff;
496 else if (!hex[1])
497 val = (hexval(hex[0]) << 4) | 0xf;
498 else
499 val = (hexval(hex[0]) << 4) | hexval(hex[1]);
500 if (val & ~0xff)
501 return 0;
502 *sha1++ = val;
503 if (!hex[0] || !hex[1])
504 break;
505 hex += 2;
506 }
507 while (sha1 < end) {
508 *sha1++ = 0xff;
509 }
510 return hex - hex_start + !!hex[0];
511 }
512
resolve_hg2git(const struct hg_object_id * oid,size_t len)513 static const struct object_id *resolve_hg2git(const struct hg_object_id *oid,
514 size_t len)
515 {
516 struct object_id git_oid;
517 const struct object_id *note;
518
519 ensure_notes(&hg2git);
520
521 note = get_note_hg(&hg2git, oid);
522 if (len == 40)
523 return note;
524
525 hg_oidcpy2git(&git_oid, oid);
526 return get_abbrev_note(&hg2git, &git_oid, len);
527 }
528
do_hg2git(struct string_list * args)529 static void do_hg2git(struct string_list *args)
530 {
531 struct hg_object_id oid;
532 const struct object_id *note;
533 size_t sha1_len;
534
535 if (args->nr != 1)
536 goto not_found;
537
538 sha1_len = get_abbrev_sha1_hex(args->items[0].string, oid.hash);
539 if (!sha1_len)
540 goto not_found;
541
542 note = resolve_hg2git(&oid, sha1_len);
543 if (note) {
544 write_or_die(1, oid_to_hex(note), 40);
545 write_or_die(1, "\n", 1);
546 return;
547 }
548
549 not_found:
550 write_or_die(1, NULL_NODE, 40);
551 write_or_die(1, "\n", 1);
552 }
553
554 /* The git storage for a mercurial manifest uses not-entirely valid file modes
555 * to keep the mercurial manifest data as git trees.
556 * While mercurial manifests are flat, the corresponding git tree uses
557 * sub-directories. The file sha1s are stored as git links (since they're not
558 * valid git sha1s), and the file modes are stored as extra bits in the git
559 * link file mode, that git normally ignores.
560 * - Symlinks are set to have a file mode of 0160000 (standard git link).
561 * - Executables are set to have a file mode of 0160755.
562 * - Regular files are set to have a file mode of 0160644.
563 */
564
565 /* Return the mercurial manifest character corresponding to the given
566 * git file mode. */
hgattr(unsigned int mode)567 static const char *hgattr(unsigned int mode)
568 {
569 if (S_ISGITLINK(mode)) {
570 if ((mode & 0755) == 0755)
571 return "x";
572 else if ((mode & 0644) == 0644)
573 return "";
574 else if ((mode & 0777) == 0)
575 return "l";
576 }
577 die("Unsupported mode %06o", mode);
578 }
579
580 /* The git storage for a mercurial manifest used to be a commit with two
581 * directories at its root:
582 * - a git directory, matching the git tree in the git commit corresponding to
583 * the mercurial changeset using the manifest.
584 * - a hg directory, containing the same file paths, but where all pointed
585 * objects are commits (mode 160000 in the git tree) whose sha1 is actually
586 * the mercurial sha1 for the corresponding mercurial file.
587 * Reconstructing the mercurial manifest required file paths, mercurial sha1
588 * for each file, and the corresponding attribute ("l" for symlinks, "x" for
589 * executables"). The hg directory alone was not enough for that, because it
590 * lacked the attribute information.
591 */
592 struct old_manifest_tree {
593 struct object_id git;
594 struct object_id hg;
595 };
596
track_tree(struct tree * tree,struct object_list ** tree_list)597 static void track_tree(struct tree *tree, struct object_list **tree_list)
598 {
599 if (tree_list) {
600 object_list_insert(&tree->object, tree_list);
601 tree->object.flags |= SEEN;
602 }
603 }
604
605 /* Fills a manifest_tree with the tree sha1s for the git/ and hg/
606 * subdirectories of the given (git) manifest tree. */
get_old_manifest_tree(struct tree * tree,struct old_manifest_tree * result,struct object_list ** tree_list)607 static int get_old_manifest_tree(struct tree *tree,
608 struct old_manifest_tree *result,
609 struct object_list **tree_list)
610 {
611 struct tree_desc desc;
612 struct name_entry entry;
613
614 track_tree(tree, tree_list);
615
616 /* If the tree is empty, return an empty tree for both git
617 * and hg. */
618 if (!tree->size) {
619 oidcpy(&result->git, &tree->object.oid);
620 oidcpy(&result->hg, &tree->object.oid);
621 return 0;
622 }
623
624 init_tree_desc(&desc, tree->buffer, tree->size);
625 /* The first entry in the manifest tree is the git subtree. */
626 if (!tree_entry(&desc, &entry))
627 goto not_found;
628 if (strcmp(entry.path, "git"))
629 goto not_found;
630 oidcpy(&result->git, &entry.oid);
631
632 /* The second entry in the manifest tree is the hg subtree. */
633 if (!tree_entry(&desc, &entry))
634 goto not_found;
635 if (strcmp(entry.path, "hg"))
636 goto not_found;
637 oidcpy(&result->hg, &entry.oid);
638
639 /* There shouldn't be any other entry. */
640 if (tree_entry(&desc, &entry))
641 goto not_found;
642
643 return 0;
644
645 not_found:
646 return -1;
647 }
648
649 struct old_manifest_tree_state {
650 struct tree *tree_git, *tree_hg;
651 struct tree_desc desc_git, desc_hg;
652 };
653
654 struct manifest_tree_state {
655 struct tree *tree;
656 struct tree_desc desc;
657 };
658
manifest_tree_state_init(const struct object_id * tree_id,struct manifest_tree_state * result,struct object_list ** tree_list)659 static int manifest_tree_state_init(const struct object_id *tree_id,
660 struct manifest_tree_state *result,
661 struct object_list **tree_list)
662 {
663 result->tree = parse_tree_indirect(tree_id);
664 if (!result->tree)
665 return -1;
666 track_tree(result->tree, tree_list);
667
668 init_tree_desc(&result->desc, result->tree->buffer,
669 result->tree->size);
670 return 0;
671 }
672
673 struct merge_manifest_tree_state {
674 struct manifest_tree_state state_a, state_b;
675 struct name_entry entry_a, entry_b;
676 struct strslice entry_a_path, entry_b_path;
677 int cmp;
678 };
679
680 struct merge_name_entry {
681 struct name_entry *entry_a, *entry_b;
682 struct strslice path;
683 };
684
merge_manifest_tree_state_init(const struct object_id * tree_id_a,const struct object_id * tree_id_b,struct merge_manifest_tree_state * result,struct object_list ** tree_list)685 static int merge_manifest_tree_state_init(const struct object_id *tree_id_a,
686 const struct object_id *tree_id_b,
687 struct merge_manifest_tree_state *result,
688 struct object_list **tree_list)
689 {
690 int ret;
691 memset(result, 0, sizeof(*result));
692 result->cmp = 0;
693
694 if (tree_id_a) {
695 ret = manifest_tree_state_init(tree_id_a, &result->state_a, tree_list);
696 if (ret)
697 return ret;
698 } else {
699 result->entry_a_path = empty_strslice();
700 result->cmp = 1;
701 }
702 if (tree_id_b) {
703 return manifest_tree_state_init(tree_id_b, &result->state_b, tree_list);
704 } else if (result->cmp == 0) {
705 result->entry_b_path = empty_strslice();
706 result->cmp = -1;
707 return 0;
708 }
709 return 1;
710 }
711
merge_tree_entry(struct merge_manifest_tree_state * state,struct merge_name_entry * entries)712 static int merge_tree_entry(struct merge_manifest_tree_state *state,
713 struct merge_name_entry *entries)
714 {
715 if (state->cmp <= 0) {
716 if (tree_entry(&state->state_a.desc, &state->entry_a)) {
717 state->entry_a_path = strslice_from_str(state->entry_a.path);
718 } else {
719 state->entry_a_path = empty_strslice();
720 }
721 }
722 if (state->cmp >= 0) {
723 if (tree_entry(&state->state_b.desc, &state->entry_b)) {
724 state->entry_b_path = strslice_from_str(state->entry_b.path);
725 } else {
726 state->entry_b_path = empty_strslice();
727 }
728 }
729 if (!state->entry_a_path.len) {
730 if (!state->entry_b_path.len)
731 return 0;
732 state->cmp = 1;
733 } else if (!state->entry_b_path.len) {
734 state->cmp = -1;
735 } else {
736 state->cmp = base_name_compare(
737 state->entry_a_path.buf, state->entry_a_path.len, state->entry_a.mode,
738 state->entry_b_path.buf, state->entry_b_path.len, state->entry_b.mode);
739 }
740 if (state->cmp <= 0) {
741 entries->entry_a = &state->entry_a;
742 entries->path = state->entry_a_path;
743 } else {
744 entries->entry_a = NULL;
745 }
746 if (state->cmp >= 0) {
747 entries->entry_b = &state->entry_b;
748 entries->path = state->entry_b_path;
749 } else {
750 entries->entry_b = NULL;
751 }
752 return 1;
753 }
754
old_manifest_tree_state_init(const struct old_manifest_tree * tree,struct old_manifest_tree_state * result,struct object_list ** tree_list)755 static int old_manifest_tree_state_init(const struct old_manifest_tree *tree,
756 struct old_manifest_tree_state *result,
757 struct object_list **tree_list)
758 {
759 result->tree_git = parse_tree_indirect(&tree->git);
760 if (!result->tree_git)
761 return -1;
762 track_tree(result->tree_git, tree_list);
763
764 result->tree_hg = parse_tree_indirect(&tree->hg);
765 if (!result->tree_hg)
766 return -1;
767 track_tree(result->tree_hg, tree_list);
768
769 init_tree_desc(&result->desc_git, result->tree_git->buffer,
770 result->tree_git->size);
771 init_tree_desc(&result->desc_hg, result->tree_hg->buffer,
772 result->tree_hg->size);
773 return 0;
774 }
775
776 struct old_manifest_entry {
777 struct object_id oid;
778 struct object_id other_oid;
779 const char *path;
780 unsigned int mode;
781 };
782
783 /* Like tree_entry, returns true for success. */
old_manifest_tree_entry(struct old_manifest_tree_state * state,struct old_manifest_entry * result)784 static int old_manifest_tree_entry(struct old_manifest_tree_state *state,
785 struct old_manifest_entry *result)
786 {
787 struct name_entry entry_git, entry_hg;
788 int has_git_entry = tree_entry(&state->desc_git, &entry_git);
789 int has_hg_entry = tree_entry(&state->desc_hg, &entry_hg);
790 if (has_git_entry != has_hg_entry)
791 goto corrupted;
792 if (!has_git_entry) {
793 result->path = NULL;
794 return 0;
795 }
796
797 oidcpy(&result->oid, &entry_hg.oid);
798 result->path = entry_hg.path;
799 result->mode = entry_git.mode;
800 if (strcmp(entry_hg.path, entry_git.path))
801 goto corrupted;
802 if (S_ISDIR(entry_git.mode)) {
803 if (entry_git.mode != entry_hg.mode)
804 goto corrupted;
805 }
806 oidcpy(&result->other_oid, &entry_git.oid);
807 return 1;
808 corrupted:
809 die("Corrupted metadata");
810 }
811
812 /* Return whether two entries have matching sha1s and modes */
manifest_entry_equal(const struct name_entry * e1,const struct name_entry * e2)813 static int manifest_entry_equal(const struct name_entry *e1,
814 const struct name_entry *e2)
815 {
816 return (e1->mode == e2->mode) && (oidcmp(&e1->oid, &e2->oid) == 0);
817 }
818
819 /* Return whether base + name matches path */
path_match(struct strslice base,struct strslice name,struct strslice path)820 static int path_match(struct strslice base, struct strslice name,
821 struct strslice path)
822 {
823 struct strslice slice;
824
825 if (!strslice_startswith(path, base) ||
826 !strslice_startswith(strslice_slice(path, base.len, SIZE_MAX),
827 name))
828 return 0;
829
830 slice = strslice_slice(path, name.len + base.len, 1);
831 return slice.len == 1 && (slice.buf[0] == '\0' || slice.buf[0] == '/');
832 }
833
recurse_manifest(const struct object_id * ref_tree_id,struct strslice ref_manifest,const struct object_id * tree_id,struct strbuf * manifest,struct strslice base,struct object_list ** tree_list)834 static void recurse_manifest(const struct object_id *ref_tree_id,
835 struct strslice ref_manifest,
836 const struct object_id *tree_id,
837 struct strbuf *manifest, struct strslice base,
838 struct object_list **tree_list)
839 {
840 struct merge_manifest_tree_state state;
841 struct merge_name_entry entries;
842 struct strslice cursor;
843 struct strslice underscore = { 1, "_" };
844 struct strbuf dir = STRBUF_INIT;
845
846 if (merge_manifest_tree_state_init(ref_tree_id, tree_id, &state, tree_list))
847 goto corrupted;
848
849 while (merge_tree_entry(&state, &entries)) {
850 if (!strslice_startswith(entries.path, underscore))
851 goto corrupted;
852 cursor = ref_manifest;
853 if (entries.entry_a) {
854 size_t len = base.len + entries.path.len + 40;
855 do {
856 strslice_split_once(&ref_manifest, '\n');
857 } while (S_ISDIR(entries.entry_a->mode) &&
858 (ref_manifest.len > len) &&
859 path_match(base, strslice_slice(
860 entries.path, 1, SIZE_MAX), ref_manifest));
861 }
862 /* File/directory was removed, nothing to do */
863 if (!entries.entry_b)
864 continue;
865 /* File/directory didn't change, copy from the reference
866 * manifest. */
867 if (entries.entry_a && entries.entry_b &&
868 manifest_entry_equal(entries.entry_a, entries.entry_b)) {
869 strbuf_add(manifest, cursor.buf,
870 cursor.len - ref_manifest.len);
871 continue;
872 }
873 if (entries.entry_b && !S_ISDIR(entries.entry_b->mode)) {
874 strbuf_addslice(manifest, base);
875 strbuf_addslice(manifest, strslice_slice(
876 entries.path, 1, SIZE_MAX));
877 strbuf_addf(manifest, "%c%s%s\n", '\0',
878 oid_to_hex(&entries.entry_b->oid),
879 hgattr(entries.entry_b->mode));
880 continue;
881 }
882
883 strbuf_addslice(&dir, base);
884 strbuf_addslice(&dir, strslice_slice(
885 entries.path, 1, SIZE_MAX));
886 strbuf_addch(&dir, '/');
887 if (entries.entry_a && entries.entry_b &&
888 S_ISDIR(entries.entry_a->mode)) {
889 recurse_manifest(&entries.entry_a->oid, cursor,
890 &entries.entry_b->oid, manifest,
891 strbuf_as_slice(&dir), tree_list);
892 } else
893 recurse_manifest(NULL, empty_strslice(),
894 &entries.entry_b->oid, manifest,
895 strbuf_as_slice(&dir), tree_list);
896 strbuf_release(&dir);
897 }
898
899 return;
900 corrupted:
901 die("Corrupted metadata");
902 }
903
904 struct manifest {
905 struct object_id tree_id;
906 struct strbuf content;
907 struct object_list *tree_list;
908 };
909
910 #define MANIFEST_INIT { { { 0, } }, STRBUF_INIT, NULL }
911
912 /* For repositories with a lot of files, generating a manifest is a slow
913 * operation.
914 * In most cases, there are way less changes between changesets than there
915 * are files in the repository, so it is much faster to generate a manifest
916 * from a previously generated manifest, by applying the differences between
917 * the corresponding trees.
918 * Therefore, we always keep the last generated manifest.
919 */
920 static struct manifest generated_manifest = MANIFEST_INIT;
921
922 /* The returned strbuf must not be released and/or freed. */
generate_manifest(const struct object_id * oid)923 struct strbuf *generate_manifest(const struct object_id *oid)
924 {
925 struct strbuf content = STRBUF_INIT;
926 struct object_list *tree_list = NULL;
927
928 /* We keep a list of all the trees we've seen while generating the
929 * previous manifest. Each tree is marked as SEEN at that time.
930 * Then, on the next manifest generation, we unmark them as SEEN,
931 * and the generation that follows will re-mark them if they are
932 * re-used. Trees that are not marked SEEN are subsequently freed.
933 */
934 struct object_list *previous_list = generated_manifest.tree_list;
935 while (previous_list) {
936 previous_list->item->flags &= ~SEEN;
937 previous_list = previous_list->next;
938 }
939
940 if (oidcmp(&generated_manifest.tree_id, oid) == 0) {
941 return &generated_manifest.content;
942 }
943
944 if (generated_manifest.content.len) {
945 struct strslice gm;
946 gm = strbuf_slice(&generated_manifest.content, 0, SIZE_MAX);
947 strbuf_grow(&content, generated_manifest.content.alloc - 1);
948 recurse_manifest(&generated_manifest.tree_id, gm,
949 oid, &content, empty_strslice(), &tree_list);
950 } else {
951 recurse_manifest(NULL, empty_strslice(), oid, &content,
952 empty_strslice(), &tree_list);
953 }
954
955 oidcpy(&generated_manifest.tree_id, oid);
956 strbuf_swap(&content, &generated_manifest.content);
957 strbuf_release(&content);
958
959 previous_list = generated_manifest.tree_list;
960 generated_manifest.tree_list = tree_list;
961
962 while (previous_list) {
963 struct object *obj = previous_list->item;
964 struct object_list *elem = previous_list;
965 previous_list = elem->next;
966 free(elem);
967 if (!(obj->flags & SEEN))
968 free_tree_buffer((struct tree *)obj);
969 }
970 return &generated_manifest.content;
971 }
972
do_manifest(struct string_list * args)973 static void do_manifest(struct string_list *args)
974 {
975 struct hg_object_id hg_oid;
976 struct object_id oid;
977 const struct object_id *manifest_oid;
978 struct strbuf *manifest = NULL;
979 size_t sha1_len;
980
981 if (args->nr != 1)
982 goto not_found;
983
984 if (!strncmp(args->items[0].string, "git:", 4)) {
985 if (get_oid_hex(args->items[0].string + 4, &oid))
986 goto not_found;
987 manifest_oid = &oid;
988 } else {
989 sha1_len = get_abbrev_sha1_hex(args->items[0].string, hg_oid.hash);
990 if (!sha1_len)
991 goto not_found;
992
993 manifest_oid = resolve_hg2git(&hg_oid, sha1_len);
994 if (!manifest_oid)
995 goto not_found;
996 }
997
998 manifest = generate_manifest(manifest_oid);
999 if (!manifest)
1000 goto not_found;
1001
1002 send_buffer(manifest);
1003 return;
1004
1005 not_found:
1006 write_or_die(1, "0\n\n", 3);
1007 }
1008
get_manifest_oid(const struct commit * commit,struct hg_object_id * oid)1009 static void get_manifest_oid(const struct commit *commit, struct hg_object_id *oid)
1010 {
1011 const char *msg;
1012 const char *hex_sha1;
1013
1014 msg = get_commit_buffer(commit, NULL);
1015
1016 hex_sha1 = strstr(msg, "\n\n") + 2;
1017
1018 if (get_sha1_hex(hex_sha1, oid->hash))
1019 hg_oidclr(oid);
1020
1021 unuse_commit_buffer(commit, msg);
1022 }
1023
hg_sha1(struct strbuf * data,const struct hg_object_id * parent1,const struct hg_object_id * parent2,struct hg_object_id * result)1024 static void hg_sha1(struct strbuf *data, const struct hg_object_id *parent1,
1025 const struct hg_object_id *parent2, struct hg_object_id *result)
1026 {
1027 git_SHA_CTX ctx;
1028
1029 if (!parent1)
1030 parent1 = &hg_null_oid;
1031 if (!parent2)
1032 parent2 = &hg_null_oid;
1033
1034 git_SHA1_Init(&ctx);
1035
1036 if (hg_oidcmp(parent1, parent2) < 0) {
1037 git_SHA1_Update(&ctx, parent1, 20);
1038 git_SHA1_Update(&ctx, parent2, 20);
1039 } else {
1040 git_SHA1_Update(&ctx, parent2, 20);
1041 git_SHA1_Update(&ctx, parent1, 20);
1042 }
1043
1044 git_SHA1_Update(&ctx, data->buf, data->len);
1045
1046 git_SHA1_Final(result->hash, &ctx);
1047 }
1048
check_manifest(const struct object_id * oid,struct hg_object_id * hg_oid)1049 int check_manifest(const struct object_id *oid,
1050 struct hg_object_id *hg_oid)
1051 {
1052 struct hg_object_id parent1, parent2, stored, computed;
1053 const struct commit *manifest_commit;
1054 struct strbuf *manifest;
1055
1056 manifest = generate_manifest(oid);
1057 if (!manifest)
1058 return 0;
1059
1060 manifest_commit = lookup_commit(the_repository, oid);
1061 if (!manifest_commit)
1062 return 0;
1063
1064 if (manifest_commit->parents) {
1065 get_manifest_oid(manifest_commit->parents->item, &parent1);
1066 if (manifest_commit->parents->next) {
1067 get_manifest_oid(manifest_commit->parents->next->item,
1068 &parent2);
1069 } else
1070 hg_oidclr(&parent2);
1071 } else {
1072 hg_oidclr(&parent1);
1073 hg_oidclr(&parent2);
1074 }
1075
1076 if (!hg_oid)
1077 hg_oid = &computed;
1078
1079 hg_sha1(manifest, &parent1, &parent2, hg_oid);
1080
1081 get_manifest_oid(manifest_commit, &stored);
1082
1083 return hg_oideq(&stored, hg_oid);
1084 }
1085
do_check_manifest(struct string_list * args)1086 static void do_check_manifest(struct string_list *args)
1087 {
1088 struct hg_object_id hg_oid, stored;
1089 struct object_id oid;
1090 const struct object_id *manifest_oid;
1091
1092 if (args->nr != 1)
1093 goto error;
1094
1095 if (!strncmp(args->items[0].string, "git:", 4)) {
1096 if (get_oid_hex(args->items[0].string + 4, &oid))
1097 goto error;
1098 manifest_oid = &oid;
1099 } else {
1100 if (get_sha1_hex(args->items[0].string, hg_oid.hash))
1101 goto error;
1102
1103 manifest_oid = resolve_hg2git(&hg_oid, 40);
1104 if (!manifest_oid)
1105 goto error;
1106 }
1107
1108 if (!check_manifest(manifest_oid, &stored))
1109 goto error;
1110
1111 if (manifest_oid != &oid && !hg_oideq(&stored, &hg_oid))
1112 goto error;
1113
1114 write_or_die(1, "ok\n", 3);
1115 return;
1116 error:
1117 write_or_die(1, "error\n", 6);
1118 }
1119
do_check_file(struct string_list * args)1120 static void do_check_file(struct string_list *args)
1121 {
1122 struct hg_file file;
1123 struct hg_object_id oid, parent1, parent2, result;
1124
1125 hg_file_init(&file);
1126
1127 if (args->nr < 1 || args->nr > 3)
1128 goto error;
1129
1130 if (get_sha1_hex(args->items[0].string, oid.hash))
1131 goto error;
1132
1133 if (args->nr > 1) {
1134 if (get_sha1_hex(args->items[1].string, parent1.hash))
1135 goto error;
1136 } else
1137 hg_oidclr(&parent1);
1138
1139 if (args->nr > 2) {
1140 if (get_sha1_hex(args->items[2].string, parent2.hash))
1141 goto error;
1142 } else
1143 hg_oidclr(&parent2);
1144
1145 hg_file_load(&file, &oid);
1146
1147 /* We do the quick and dirty thing here, for now.
1148 * See details in cinnabar.githg.FileFindParents._set_parents_fallback
1149 */
1150 hg_sha1(&file.file, &parent1, &parent2, &result);
1151 if (hg_oideq(&oid, &result))
1152 goto ok;
1153
1154 hg_sha1(&file.file, &parent1, NULL, &result);
1155 if (hg_oideq(&oid, &result))
1156 goto ok;
1157
1158 hg_sha1(&file.file, &parent2, NULL, &result);
1159 if (hg_oideq(&oid, &result))
1160 goto ok;
1161
1162 hg_sha1(&file.file, &parent1, &parent1, &result);
1163 if (hg_oideq(&oid, &result))
1164 goto ok;
1165
1166 hg_sha1(&file.file, NULL, NULL, &result);
1167 if (!hg_oideq(&oid, &result))
1168 goto error;
1169
1170 ok:
1171 write_or_die(1, "ok\n", 3);
1172 hg_file_release(&file);
1173 return;
1174
1175 error:
1176 write_or_die(1, "error\n", 6);
1177 hg_file_release(&file);
1178 }
1179
do_version(struct string_list * args)1180 static void do_version(struct string_list *args)
1181 {
1182 long int version;
1183 struct strbuf version_s = STRBUF_INIT;
1184
1185 if (args->nr != 1)
1186 exit(1);
1187
1188 version = strtol(args->items[0].string, NULL, 10);
1189 if (version < 100)
1190 version *= 100;
1191
1192 if (!version || version < MIN_CMD_VERSION || version > CMD_VERSION)
1193 exit(128);
1194
1195 strbuf_add(&version_s, STRINGIFY(HELPER_HASH), sizeof(STRINGIFY(HELPER_HASH)) - 1);
1196 if (version >= 3000)
1197 strbuf_addf(&version_s, " " STRINGIFY(CMD_VERSION));
1198 strbuf_addch(&version_s, '\n');
1199 write_or_die(1, version_s.buf, version_s.len);
1200 strbuf_release(&version_s);
1201 }
1202
do_helpercaps(struct string_list * args)1203 static void do_helpercaps(struct string_list *args)
1204 {
1205 struct strbuf caps = STRBUF_INIT;
1206
1207 if (args->nr != 0)
1208 die("helpercaps takes no arguments");
1209
1210 if (mode & MODE_WIRE) {
1211 char *resolved;
1212 strbuf_addstr(&caps, "compression=UN,GZ");
1213 resolved = which("bzip2");
1214 if (resolved) {
1215 free(resolved);
1216 strbuf_addstr(&caps, ",BZ");
1217 }
1218 resolved = which("zstd");
1219 if (resolved) {
1220 free(resolved);
1221 strbuf_addstr(&caps, ",ZS");
1222 }
1223 }
1224
1225 if (cinnabar_experiments & EXPERIMENT_STORE) {
1226 if (caps.len)
1227 strbuf_addch(&caps, '\n');
1228 strbuf_addstr(&caps, "store=new");
1229 }
1230
1231 send_buffer(&caps);
1232 strbuf_release(&caps);
1233 }
1234
string_list_as_oid_array(struct string_list * list,struct oid_array * array)1235 static void string_list_as_oid_array(struct string_list *list,
1236 struct oid_array *array)
1237 {
1238 struct string_list_item *item;
1239 for_each_string_list_item(item, list) {
1240 struct object_id oid;
1241 if (!get_oid_hex(item->string, &oid))
1242 oid_array_append(array, &oid);
1243 }
1244 }
1245
do_known(struct hg_connection * conn,struct string_list * args)1246 static void do_known(struct hg_connection *conn, struct string_list *args)
1247 {
1248 struct strbuf result = STRBUF_INIT;
1249 struct oid_array nodes = OID_ARRAY_INIT;
1250 string_list_as_oid_array(args, &nodes);
1251 hg_known(conn, &result, &nodes);
1252 send_buffer(&result);
1253 oid_array_clear(&nodes);
1254 strbuf_release(&result);
1255 }
1256
do_listkeys(struct hg_connection * conn,struct string_list * args)1257 static void do_listkeys(struct hg_connection *conn, struct string_list *args)
1258 {
1259 struct strbuf result = STRBUF_INIT;
1260 if (args->nr != 1)
1261 exit(1);
1262
1263 hg_listkeys(conn, &result, args->items[0].string);
1264 send_buffer(&result);
1265 strbuf_release(&result);
1266 }
1267
arg_as_oid_array(char * nodes,struct oid_array * array)1268 static void arg_as_oid_array(char *nodes, struct oid_array *array)
1269 {
1270 struct string_list list = STRING_LIST_INIT_NODUP;
1271 string_list_split_in_place(&list, nodes, ',', -1);
1272 string_list_as_oid_array(&list, array);
1273 string_list_clear(&list, 0);
1274 }
1275
do_getbundle(struct hg_connection * conn,struct string_list * args)1276 static void do_getbundle(struct hg_connection *conn, struct string_list *args)
1277 {
1278 struct oid_array heads = OID_ARRAY_INIT;
1279 struct oid_array common = OID_ARRAY_INIT;
1280 const char *bundle2caps = NULL;
1281
1282 if (args->nr > 3)
1283 exit(1);
1284
1285 if (args->nr > 0)
1286 arg_as_oid_array(args->items[0].string, &heads);
1287 if (args->nr > 1)
1288 arg_as_oid_array(args->items[1].string, &common);
1289 if (args->nr > 2)
1290 bundle2caps = args->items[2].string;
1291
1292 hg_getbundle(conn, stdout, &heads, &common, bundle2caps);
1293
1294 oid_array_clear(&common);
1295 oid_array_clear(&heads);
1296 }
1297
do_unbundle(struct hg_connection * conn,struct string_list * args)1298 static void do_unbundle(struct hg_connection *conn, struct string_list *args)
1299 {
1300 struct strbuf result = STRBUF_INIT;
1301 struct oid_array heads = OID_ARRAY_INIT;
1302 if (args->nr < 1)
1303 exit(1);
1304 if (args->nr != 1 || strcmp(args->items[0].string, "force"))
1305 string_list_as_oid_array(args, &heads);
1306 hg_unbundle(conn, &result, stdin, &heads);
1307 send_buffer(&result);
1308 oid_array_clear(&heads);
1309 strbuf_release(&result);
1310 }
1311
do_pushkey(struct hg_connection * conn,struct string_list * args)1312 static void do_pushkey(struct hg_connection *conn, struct string_list *args)
1313 {
1314 struct strbuf result = STRBUF_INIT;
1315
1316 if (args->nr != 4)
1317 exit(1);
1318
1319 hg_pushkey(conn, &result, args->items[0].string, args->items[1].string,
1320 args->items[2].string, args->items[3].string);
1321 send_buffer(&result);
1322 strbuf_release(&result);
1323 }
1324
do_capable(struct hg_connection * conn,struct string_list * args)1325 static void do_capable(struct hg_connection *conn, struct string_list *args)
1326 {
1327 struct strbuf result = STRBUF_INIT;
1328 const char *result_str;
1329
1330 if (args->nr != 1)
1331 exit(1);
1332
1333 result_str = hg_get_capability(conn, args->items[0].string);
1334 if (result_str) {
1335 strbuf_addstr(&result, result_str);
1336 send_buffer(&result);
1337 } else {
1338 send_buffer(NULL);
1339 }
1340 strbuf_release(&result);
1341 }
1342
do_state(struct hg_connection * conn,struct string_list * args)1343 static void do_state(struct hg_connection *conn, struct string_list *args)
1344 {
1345 struct strbuf branchmap = STRBUF_INIT;
1346 struct strbuf heads = STRBUF_INIT;
1347 struct strbuf bookmarks = STRBUF_INIT;
1348
1349 if (args->nr != 0)
1350 exit(1);
1351
1352 hg_get_repo_state(conn, &branchmap, &heads, &bookmarks);
1353 send_buffer(&branchmap);
1354 send_buffer(&heads);
1355 send_buffer(&bookmarks);
1356 strbuf_release(&branchmap);
1357 strbuf_release(&heads);
1358 strbuf_release(&bookmarks);
1359 }
1360
do_lookup(struct hg_connection * conn,struct string_list * args)1361 static void do_lookup(struct hg_connection *conn, struct string_list *args)
1362 {
1363 struct strbuf result = STRBUF_INIT;
1364 if (args->nr != 1)
1365 exit(1);
1366
1367 hg_lookup(conn, &result, args->items[0].string);
1368 send_buffer(&result);
1369 strbuf_release(&result);
1370 }
1371
do_clonebundles(struct hg_connection * conn,struct string_list * args)1372 static void do_clonebundles(struct hg_connection *conn, struct string_list *args)
1373 {
1374 struct strbuf result = STRBUF_INIT;
1375 if (args->nr != 0)
1376 exit(1);
1377
1378 hg_clonebundles(conn, &result);
1379 send_buffer(&result);
1380 strbuf_release(&result);
1381 }
1382
do_cinnabarclone(struct hg_connection * conn,struct string_list * args)1383 static void do_cinnabarclone(struct hg_connection *conn, struct string_list *args)
1384 {
1385 struct strbuf result = STRBUF_INIT;
1386 if (args->nr != 0)
1387 exit(1);
1388
1389 hg_cinnabarclone(conn, &result);
1390 send_buffer(&result);
1391 strbuf_release(&result);
1392 }
1393
connected_loop(struct hg_connection * conn)1394 static void connected_loop(struct hg_connection *conn)
1395 {
1396 struct strbuf buf = STRBUF_INIT;
1397
1398 while (strbuf_getline(&buf, stdin) != EOF) {
1399 struct string_list args = STRING_LIST_INIT_NODUP;
1400 const char *command;
1401 record_command(&buf);
1402 split_command(buf.buf, &command, &args);
1403
1404 if (!*command) {
1405 string_list_clear(&args, 0);
1406 break;
1407 }
1408 if (!strcmp("known", command))
1409 do_known(conn, &args);
1410 else if (!strcmp("listkeys", command))
1411 do_listkeys(conn, &args);
1412 else if (!strcmp("getbundle", command))
1413 do_getbundle(conn, &args);
1414 else if (!strcmp("unbundle", command))
1415 do_unbundle(conn, &args);
1416 else if (!strcmp("pushkey", command))
1417 do_pushkey(conn, &args);
1418 else if (!strcmp("capable", command))
1419 do_capable(conn, &args);
1420 else if (!strcmp("state", command))
1421 do_state(conn, &args);
1422 else if (!strcmp("lookup", command))
1423 do_lookup(conn, &args);
1424 else if (!strcmp("clonebundles", command))
1425 do_clonebundles(conn, &args);
1426 else if (!strcmp("cinnabarclone", command))
1427 do_cinnabarclone(conn, &args);
1428 else
1429 die("Unknown command: \"%s\"", command);
1430
1431 string_list_clear(&args, 0);
1432 }
1433
1434 strbuf_release(&buf);
1435 }
1436
do_connect(struct string_list * args)1437 static void do_connect(struct string_list *args)
1438 {
1439 const char *url;
1440 struct hg_connection *conn;
1441
1442 if (args->nr != 1)
1443 return;
1444
1445 url = args->items[0].string;
1446
1447 conn = hg_connect(url, 0);
1448
1449 // hg_connect either dies in case of connection failure,
1450 // or returns NULL, in which case it has sent out a stream
1451 // to stdout.
1452 if (conn) {
1453 write_or_die(1, "ok\n", 3);
1454 connected_loop(conn);
1455
1456 hg_finish_connect(conn);
1457 }
1458 }
1459
add_each_head(const struct object_id * oid,void * data)1460 static int add_each_head(const struct object_id *oid, void *data)
1461 {
1462 struct strbuf *buf = data;
1463
1464 strbuf_addstr(buf, oid_to_hex(oid));
1465 strbuf_addch(buf, '\n');
1466 return 0;
1467 }
1468
do_heads(struct string_list * args)1469 static void do_heads(struct string_list *args)
1470 {
1471 //XXX: Should use hg specific oid array.
1472 struct oid_array *heads = NULL;
1473 struct strbuf heads_buf = STRBUF_INIT;
1474
1475 if (args->nr != 1)
1476 die("heads needs 1 argument");
1477
1478 if (!strcmp(args->items[0].string, "manifests")) {
1479 heads = &manifest_heads;
1480 } else
1481 die("Unknown kind: %s", args->items[0].string);
1482
1483 ensure_heads(heads);
1484 oid_array_for_each_unique(heads, add_each_head, &heads_buf);
1485 send_buffer(&heads_buf);
1486 strbuf_release(&heads_buf);
1487 }
1488
reset_heads(struct oid_array * heads)1489 static void reset_heads(struct oid_array *heads)
1490 {
1491 oid_array_clear(heads);
1492 // We don't want subsequent ensure_heads to refill the array,
1493 // so mark it as sorted, which means it's initialized.
1494 heads->sorted = 1;
1495 }
1496
do_reset_heads(struct string_list * args)1497 static void do_reset_heads(struct string_list *args)
1498 {
1499 struct oid_array *heads = NULL;
1500
1501 if (args->nr != 1)
1502 die("reset-heads needs 1 argument");
1503
1504 if (!strcmp(args->items[0].string, "manifests")) {
1505 heads = &manifest_heads;
1506 } else
1507 die("Unknown kind: %s", args->items[0].string);
1508
1509 ensure_heads(heads);
1510 reset_heads(heads);
1511 }
1512
1513 struct track_upgrade {
1514 struct oidset set;
1515 struct progress *progress;
1516 };
1517
upgrade_files(const struct old_manifest_tree * tree,struct track_upgrade * track)1518 static void upgrade_files(const struct old_manifest_tree *tree,
1519 struct track_upgrade *track)
1520 {
1521 struct old_manifest_tree_state state;
1522 struct old_manifest_entry entry;
1523
1524 state.tree_hg = lookup_tree(the_repository, &tree->hg);
1525 if (!state.tree_hg)
1526 goto corrupted;
1527
1528 if (state.tree_hg->object.flags & SEEN)
1529 goto cleanup;
1530
1531 if (old_manifest_tree_state_init(tree, &state, NULL))
1532 goto corrupted;
1533
1534 while (old_manifest_tree_entry(&state, &entry)) {
1535 struct hg_object_id hg_oid;
1536 struct object_id oid;
1537 const struct object_id *note;
1538 if (S_ISDIR(entry.mode)) {
1539 struct old_manifest_tree subtree;
1540 oidcpy(&subtree.git, &entry.other_oid);
1541 oidcpy(&subtree.hg, &entry.oid);
1542 upgrade_files(&subtree, track);
1543 continue;
1544 }
1545
1546 oidcpy(&oid, &entry.oid);
1547 if (oidset_insert(&track->set, &oid))
1548 continue;
1549
1550 oidcpy2hg(&hg_oid, &entry.oid);
1551 note = get_note_hg(&hg2git, &hg_oid);
1552 if (!note && !is_empty_hg_file(&hg_oid))
1553 goto corrupted;
1554 if (note && oidcmp(note, &entry.other_oid)) {
1555 struct hg_file file;
1556 struct strbuf buf = STRBUF_INIT;
1557 unsigned long len;
1558 enum object_type t;
1559 char *content;
1560 content = read_object_file_extended(
1561 the_repository, note, &t, &len, 0);
1562 strbuf_attach(&buf, content, len, len);
1563 hg_file_init(&file);
1564 hg_file_from_memory(&file, &hg_oid, &buf);
1565 remove_note_hg(&hg2git, &hg_oid);
1566 hg_file_store(&file, NULL);
1567 hg_file_release(&file);
1568 note = get_note_hg(&hg2git, &hg_oid);
1569 if (oidcmp(note, &entry.other_oid))
1570 goto corrupted;
1571 }
1572 display_progress(track->progress,
1573 kh_size(&track->set.set));
1574 }
1575
1576 free_tree_buffer(state.tree_git);
1577 cleanup:
1578 state.tree_hg->object.flags |= SEEN;
1579 free_tree_buffer(state.tree_hg);
1580 return;
1581 corrupted:
1582 die("Corrupted metadata");
1583
1584 }
1585
1586 static struct name_entry *
lazy_tree_entry_by_name(struct manifest_tree_state * state,const struct object_id * tree_id,const char * path)1587 lazy_tree_entry_by_name(struct manifest_tree_state *state,
1588 const struct object_id *tree_id,
1589 const char *path)
1590 {
1591 int cmp;
1592
1593 if (!tree_id)
1594 return NULL;
1595
1596 if (!state->tree) {
1597 if (manifest_tree_state_init(tree_id, state, NULL))
1598 return NULL;
1599 }
1600
1601 while (state->desc.size &&
1602 (cmp = strcmp(state->desc.entry.path, path)) < 0)
1603 update_tree_entry(&state->desc);
1604
1605 if (state->desc.size && cmp == 0)
1606 return &state->desc.entry;
1607
1608 return NULL;
1609 }
1610
1611 struct track_manifests_upgrade {
1612 struct progress *progress;
1613 struct oidset manifests;
1614 struct hashmap tree_cache;
1615 struct hashmap commit_cache;
1616 };
1617
1618 struct old2new_manifest_tree {
1619 struct hashmap_entry ent;
1620 struct old_manifest_tree old_tree;
1621 struct object_id new_tree;
1622 };
1623
1624 struct oid_map_entry {
1625 struct hashmap_entry ent;
1626 struct object_id old_oid;
1627 struct object_id new_oid;
1628 };
1629
old2new_manifest_tree_cmp(const void * cmpdata,const struct hashmap_entry * e1,const struct hashmap_entry * e2,const void * keydata)1630 static int old2new_manifest_tree_cmp(const void *cmpdata, const struct hashmap_entry *e1,
1631 const struct hashmap_entry *e2, const void *keydata)
1632 {
1633 const struct old2new_manifest_tree *entry1 =
1634 container_of(e1, const struct old2new_manifest_tree, ent);
1635 const struct old2new_manifest_tree *entry2 =
1636 container_of(e2, const struct old2new_manifest_tree, ent);
1637
1638 return memcmp(&entry1->old_tree, &entry2->old_tree,
1639 sizeof(struct old_manifest_tree));
1640 }
1641
oid_map_entry_cmp(const void * cmpdata,const struct hashmap_entry * e1,const struct hashmap_entry * e2,const void * keydata)1642 static int oid_map_entry_cmp(const void *cmpdata, const struct hashmap_entry *e1,
1643 const struct hashmap_entry *e2, const void *keydata)
1644 {
1645 const struct oid_map_entry *entry1 =
1646 container_of(e1, const struct oid_map_entry, ent);
1647 const struct oid_map_entry *entry2 =
1648 container_of(e2, const struct oid_map_entry, ent);
1649
1650 return oidcmp(&entry1->old_oid, &entry2->old_oid);
1651 }
1652
upgrade_manifest_tree_v1(const struct object_id * tree_id,const struct object_id * reference,struct object_id * result,struct hashmap * cache)1653 static void upgrade_manifest_tree_v1(const struct object_id *tree_id,
1654 const struct object_id *reference,
1655 struct object_id *result,
1656 struct hashmap *cache)
1657 {
1658 struct oid_map_entry k, *old2new;
1659
1660 oidcpy(&k.old_oid, tree_id);
1661 hashmap_entry_init(&k.ent, oidhash(&k.old_oid));
1662 old2new = hashmap_get_entry(cache, &k, ent, NULL);
1663 if (!old2new) {
1664 struct strbuf tree_buf = STRBUF_INIT;
1665 struct strbuf entry_buf = STRBUF_INIT;
1666 struct tree_desc desc;
1667 struct manifest_tree_state ref_state = { NULL, };
1668 struct name_entry entry;
1669 struct tree *tree = parse_tree_indirect(tree_id);
1670
1671 if (!tree)
1672 die("Corrupted metadata");
1673
1674 init_tree_desc(&desc, tree->buffer, tree->size);
1675
1676 while (tree_entry(&desc, &entry)) {
1677 strbuf_addf(&tree_buf, "%o _%s%c",
1678 entry.mode, entry.path, '\0');
1679
1680 if (S_ISDIR(entry.mode)) {
1681 struct name_entry *ref_entry;
1682 struct object_id new_subtree;
1683 strbuf_addch(&entry_buf, '_');
1684 strbuf_addstr(&entry_buf, entry.path);
1685 ref_entry = lazy_tree_entry_by_name(
1686 &ref_state, reference, entry_buf.buf);
1687 strbuf_reset(&entry_buf);
1688 upgrade_manifest_tree_v1(
1689 &entry.oid,
1690 ref_entry ? &ref_entry->oid : NULL,
1691 &new_subtree, cache);
1692 strbuf_add(&tree_buf, new_subtree.hash, 20);
1693 } else {
1694 strbuf_add(&tree_buf, entry.oid.hash, 20);
1695 }
1696 }
1697
1698 old2new = xmalloc(sizeof(k));
1699 old2new->ent = k.ent;
1700 oidcpy(&old2new->old_oid, &k.old_oid);
1701 oidcpy(&old2new->new_oid, &k.old_oid);
1702 store_git_tree(&tree_buf, reference, &old2new->new_oid);
1703 strbuf_release(&tree_buf);
1704 strbuf_release(&entry_buf);
1705 hashmap_add(cache, &old2new->ent);
1706
1707 free_tree_buffer(tree);
1708 if (ref_state.tree)
1709 free_tree_buffer(ref_state.tree);
1710 }
1711 oidcpy(result, &old2new->new_oid);
1712 }
1713
upgrade_manifest_tree(struct old_manifest_tree * tree,const struct object_id * reference,struct object_id * result,struct hashmap * cache)1714 static void upgrade_manifest_tree(struct old_manifest_tree *tree,
1715 const struct object_id *reference,
1716 struct object_id *result,
1717 struct hashmap *cache)
1718 {
1719 struct old2new_manifest_tree k, *old2new;
1720
1721 hashmap_entry_init(&k.ent, memhash(tree, sizeof(*tree)));
1722 k.old_tree = *tree;
1723 old2new = hashmap_get_entry(cache, &k, ent, NULL);
1724 if (!old2new) {
1725 struct old_manifest_tree_state state;
1726 struct old_manifest_entry entry;
1727 struct manifest_tree_state ref_state = { NULL, };
1728 struct strbuf tree_buf = STRBUF_INIT;
1729 struct strbuf entry_buf = STRBUF_INIT;
1730
1731 if (old_manifest_tree_state_init(tree, &state, NULL))
1732 die("Corrupted metadata");
1733
1734 while (old_manifest_tree_entry(&state, &entry)) {
1735 struct object_id oid;
1736 unsigned mode = entry.mode;
1737 if (S_ISDIR(mode)) {
1738 struct old_manifest_tree subtree;
1739 struct name_entry *ref_entry;
1740 strbuf_addch(&entry_buf, '_');
1741 strbuf_addstr(&entry_buf, entry.path);
1742 ref_entry = lazy_tree_entry_by_name(
1743 &ref_state, reference, entry_buf.buf);
1744 strbuf_reset(&entry_buf);
1745 oidcpy(&subtree.git, &entry.other_oid);
1746 oidcpy(&subtree.hg, &entry.oid);
1747 upgrade_manifest_tree(
1748 &subtree,
1749 ref_entry ? &ref_entry->oid : NULL,
1750 &oid, cache);
1751 } else {
1752 if (S_ISLNK(mode))
1753 mode = S_IFGITLINK;
1754 else
1755 mode |= S_IFGITLINK;
1756 oidcpy(&oid, &entry.oid);
1757 }
1758 strbuf_addf(&tree_buf, "%o _%s%c", mode, entry.path, '\0');
1759 strbuf_add(&tree_buf, oid.hash, 20);
1760 }
1761
1762 old2new = xmalloc(sizeof(k));
1763 old2new->ent = k.ent;
1764 old2new->old_tree = k.old_tree;
1765 store_git_tree(&tree_buf, reference, &old2new->new_tree);
1766 strbuf_release(&tree_buf);
1767 strbuf_release(&entry_buf);
1768 hashmap_add(cache, &old2new->ent);
1769
1770 free_tree_buffer(state.tree_git);
1771 free_tree_buffer(state.tree_hg);
1772 if (ref_state.tree)
1773 free_tree_buffer(ref_state.tree);
1774 }
1775 oidcpy(result, &old2new->new_tree);
1776 }
1777
upgrade_manifest(struct commit * commit,struct track_manifests_upgrade * track)1778 static void upgrade_manifest(struct commit *commit,
1779 struct track_manifests_upgrade *track)
1780 {
1781 struct object_id new_tree_id;
1782 size_t size = 0;
1783 unsigned long size_l = 0;
1784 struct strbuf new_commit = STRBUF_INIT;
1785 const char *buf;
1786 char *cursor;
1787 struct hg_object_id oid;
1788 struct oid_map_entry *entry;
1789 struct tree *tree;
1790 struct object_id *ref_tree = NULL;
1791
1792 if (parse_commit(commit))
1793 die("Corrupt mercurial metadata");
1794
1795 tree = get_commit_tree(commit);
1796
1797 if (parse_tree(tree))
1798 die("Corrupt mercurial metadata");
1799
1800 if (commit->parents) {
1801 struct oid_map_entry k;
1802 struct commit *p;
1803 oidcpy(&k.old_oid, &commit->parents->item->object.oid);
1804 hashmap_entry_init(&k.ent, oidhash(&k.old_oid));
1805 entry = hashmap_get_entry(&track->commit_cache, &k, ent, NULL);
1806 if (!entry)
1807 die("Something went wrong");
1808 p = lookup_commit(the_repository, &entry->new_oid);
1809 if (!p)
1810 die("Something went wrong");
1811 ref_tree = get_commit_tree_oid(p);
1812 }
1813
1814 if (metadata_flags & UNIFIED_MANIFESTS) {
1815 upgrade_manifest_tree_v1(&tree->object.oid, ref_tree,
1816 &new_tree_id, &track->tree_cache);
1817 } else {
1818 struct old_manifest_tree manifest_tree;
1819 if (get_old_manifest_tree(tree, &manifest_tree, NULL))
1820 die("Corrupt mercurial metadata");
1821
1822 upgrade_manifest_tree(&manifest_tree, ref_tree, &new_tree_id,
1823 &track->tree_cache);
1824 }
1825
1826 buf = get_commit_buffer(commit, &size_l);
1827 size = size_l;
1828 strbuf_add(&new_commit, buf, size);
1829 unuse_commit_buffer(commit, buf);
1830
1831 cursor = (char *)find_commit_header(new_commit.buf, "tree", &size);
1832 oid_to_hex_r(cursor, &new_tree_id);
1833 cursor[40] = '\n';
1834
1835 cursor = new_commit.buf;
1836 while ((cursor = (char *)find_commit_header(cursor, "parent", &size))) {
1837 struct oid_map_entry k;
1838 if (get_oid_hex(cursor, &k.old_oid))
1839 die("Invalid sha1");
1840 hashmap_entry_init(&k.ent, oidhash(&k.old_oid));
1841 entry = hashmap_get_entry(&track->commit_cache, &k, ent, NULL);
1842 if (!entry)
1843 die("Something went wrong");
1844 oid_to_hex_r(cursor, &entry->new_oid);
1845 cursor[40] = '\n';
1846 cursor += 41;
1847 }
1848
1849 entry = xmalloc(sizeof(*entry));
1850 hashmap_entry_init(&entry->ent, oidhash(&commit->object.oid));
1851 oidcpy(&entry->old_oid, &commit->object.oid);
1852 store_git_commit(&new_commit, &entry->new_oid);
1853 hashmap_add(&track->commit_cache, &entry->ent);
1854 oidset_insert(&track->manifests, &entry->new_oid);
1855
1856 get_manifest_oid(commit, &oid);
1857 add_note_hg(&hg2git, &oid, &entry->new_oid, combine_notes_overwrite);
1858 add_head(&manifest_heads, &entry->new_oid);
1859
1860 strbuf_release(&new_commit);
1861
1862 display_progress(track->progress,
1863 hashmap_get_size(&track->commit_cache));
1864 }
1865
revs_add_each_head(const struct object_id * oid,void * data)1866 static int revs_add_each_head(const struct object_id *oid, void *data)
1867 {
1868 struct rev_info *revs = data;
1869
1870 add_pending_oid(revs, oid_to_hex(oid), oid, 0);
1871
1872 return 0;
1873 }
1874
1875 static struct commit *
resolve_manifest_for_upgrade(struct commit * commit,struct track_manifests_upgrade * track)1876 resolve_manifest_for_upgrade(struct commit *commit,
1877 struct track_manifests_upgrade *track)
1878 {
1879 const struct object_id *note;
1880 char *buffer;
1881 const char *manifest;
1882 enum object_type type;
1883 unsigned long size;
1884 struct hg_object_id manifest_oid;
1885 const struct object_id *git_manifest;
1886
1887 ensure_notes(&git2hg);
1888 note = get_note(&git2hg, lookup_replace_object(the_repository, &commit->object.oid));
1889 if (!note)
1890 goto corrupted;
1891
1892 buffer = read_object_file(note, &type, &size);
1893
1894 if (!buffer || type != OBJ_BLOB)
1895 goto corrupted;
1896
1897 manifest = strstr(buffer, "manifest ") + sizeof("manifest");
1898 if (get_sha1_hex(manifest, manifest_oid.hash))
1899 goto corrupted;
1900
1901 git_manifest = resolve_hg2git(&manifest_oid, 40);
1902 if (!git_manifest)
1903 goto corrupted;
1904
1905 free(buffer);
1906
1907 if (oidset_contains(&track->manifests, git_manifest))
1908 return NULL;
1909 return lookup_commit(the_repository, git_manifest);
1910
1911 corrupted:
1912 die("Corrupt mercurial metadata");
1913 }
1914
do_upgrade(struct string_list * args)1915 static void do_upgrade(struct string_list *args)
1916 {
1917 struct rev_info revs;
1918 struct commit *commit;
1919
1920 if (args->nr != 0)
1921 die("upgrade takes no arguments");
1922
1923 ensure_notes(&hg2git);
1924
1925 init_revisions(&revs, NULL);
1926
1927 if (!(metadata_flags & FILES_META)) {
1928 struct track_upgrade track = { OIDSET_INIT, NULL };
1929 track.progress = start_progress("Upgrading files metadata", 0);
1930
1931 ensure_heads(&manifest_heads);
1932 oid_array_for_each_unique(&manifest_heads, revs_add_each_head,
1933 &revs);
1934
1935 if (prepare_revision_walk(&revs))
1936 die("revision walk setup failed");
1937
1938 while ((commit = get_revision(&revs)) != NULL) {
1939 struct tree *tree = get_commit_tree(commit);
1940 if (parse_tree(tree))
1941 die("Corrupt mercurial metadata");
1942 struct old_manifest_tree manifest_tree;
1943 if (get_old_manifest_tree(tree, &manifest_tree,
1944 NULL))
1945 die("Corrupt mercurial metadata");
1946 upgrade_files(&manifest_tree, &track);
1947 }
1948 stop_progress(&track.progress);
1949 oidset_clear(&track.set);
1950 reset_revision_walk();
1951 }
1952
1953 if (!(metadata_flags & UNIFIED_MANIFESTS_v2)) {
1954 struct track_manifests_upgrade track = { NULL, OIDSET_INIT, };
1955 track.progress = start_progress("Upgrading manifests metadata", 0);
1956 if (metadata_flags & UNIFIED_MANIFESTS) {
1957 hashmap_init(&track.tree_cache, oid_map_entry_cmp, NULL, 0);
1958 } else {
1959 hashmap_init(&track.tree_cache, old2new_manifest_tree_cmp, NULL, 0);
1960 }
1961 hashmap_init(&track.commit_cache, oid_map_entry_cmp, NULL, 0);
1962
1963 reset_heads(&manifest_heads);
1964 // Normally, we'd operate on manifest_heads, but some might be
1965 // missing for $reasons, and a partial upgrade would leave things
1966 // in a very bad shape, so we use changeset_heads instead.
1967 ensure_heads(&changeset_heads);
1968 oid_array_for_each_unique(&changeset_heads,
1969 revs_add_each_head, &revs);
1970
1971 revs.topo_order = 1;
1972 revs.limited = 1;
1973 revs.sort_order = REV_SORT_IN_GRAPH_ORDER;
1974 revs.reverse = 1;
1975
1976 if (prepare_revision_walk(&revs))
1977 die("revision walk setup failed");
1978
1979 while ((commit = get_revision(&revs)) != NULL) {
1980 struct commit *manifest_commit;
1981 manifest_commit = resolve_manifest_for_upgrade(commit,
1982 &track);
1983 if (manifest_commit) {
1984 upgrade_manifest(manifest_commit, &track);
1985 free_tree_buffer(get_commit_tree(manifest_commit));
1986 }
1987 }
1988 hashmap_clear_and_free(&track.commit_cache, struct oid_map_entry, ent);
1989 hashmap_clear_and_free(&track.tree_cache, struct oid_map_entry, ent);
1990 oidset_clear(&track.manifests);
1991 stop_progress(&track.progress);
1992 }
1993
1994 write_or_die(1, "ok\n", 3);
1995 rev_info_release(&revs);
1996 }
1997
recurse_create_git_tree(const struct object_id * tree_id,const struct object_id * reference,const struct object_id * merge_tree_id,struct object_id * result,struct hashmap * cache)1998 static void recurse_create_git_tree(const struct object_id *tree_id,
1999 const struct object_id *reference,
2000 const struct object_id *merge_tree_id,
2001 struct object_id *result,
2002 struct hashmap *cache)
2003 {
2004 struct oid_map_entry k, *cache_entry = NULL;
2005
2006 if (!merge_tree_id) {
2007 hashmap_entry_init(&k.ent, oidhash(tree_id));
2008 oidcpy(&k.old_oid, tree_id);
2009 cache_entry = hashmap_get_entry(cache, &k, ent, NULL);
2010 }
2011 if (!cache_entry) {
2012 struct merge_manifest_tree_state state;
2013 struct manifest_tree_state ref_state = { NULL, };
2014 struct merge_name_entry entries;
2015 struct strbuf tree_buf = STRBUF_INIT;
2016
2017 if (merge_manifest_tree_state_init(tree_id, merge_tree_id, &state, NULL))
2018 goto corrupted;
2019
2020 while (merge_tree_entry(&state, &entries)) {
2021 struct object_id oid;
2022 struct name_entry *entry = entries.entry_a ? entries.entry_a : entries.entry_b;
2023 unsigned mode = entry->mode;
2024 struct strslice entry_path;
2025 struct strslice underscore = { 1, "_" };
2026 if (!strslice_startswith(entries.path, underscore))
2027 goto corrupted;
2028 entry_path = strslice_slice(entries.path, 1, SIZE_MAX);
2029 // In some edge cases, presumably all related to the use of
2030 // `hg convert` before Mercurial 2.0.1, manifest trees have
2031 // double slashes, which end up as "_" directories in the
2032 // corresponding git cinnabar metadata.
2033 // With further changes in the subsequent Mercurial manifests,
2034 // those entries with double slashes are superseded with entries
2035 // with single slash, while still being there. So to create
2036 // the corresponding git commit, we need to merge both in some
2037 // manner.
2038 // Mercurial doesn't actually guarantee which of the paths would
2039 // actually be checked out when checking out such manifests,
2040 // but we always choose the single slash path. Most of the time,
2041 // though, both will have the same contents. At least for files.
2042 // Sub-directories may differ in what paths they contain, but
2043 // again, the files they contain are usually identical.
2044 if (entry_path.len == 0) {
2045 if (!S_ISDIR(mode))
2046 goto corrupted;
2047 if (merge_tree_id)
2048 continue;
2049 recurse_create_git_tree(
2050 tree_id, reference, &entry->oid, result, cache);
2051 goto cleanup;
2052 } else if (S_ISDIR(mode)) {
2053 struct name_entry *ref_entry;
2054 ref_entry = lazy_tree_entry_by_name(
2055 &ref_state, reference, entry_path.buf);
2056 recurse_create_git_tree(
2057 &entry->oid,
2058 ref_entry ? &ref_entry->oid : NULL,
2059 (entries.entry_b && S_ISDIR(entries.entry_b->mode))
2060 ? &entries.entry_b->oid : NULL,
2061 &oid, cache);
2062 } else {
2063 const struct object_id *file_oid;
2064 struct hg_object_id hg_oid;
2065 oidcpy2hg(&hg_oid, &entry->oid);
2066 if (is_empty_hg_file(&hg_oid))
2067 file_oid = ensure_empty_blob();
2068 else
2069 file_oid = resolve_hg2git(&hg_oid, 40);
2070 if (!file_oid)
2071 goto corrupted;
2072 oidcpy(&oid, file_oid);
2073 mode &= 0777;
2074 if (!mode)
2075 mode = S_IFLNK;
2076 else
2077 mode = S_IFREG | mode;
2078 }
2079 strbuf_addf(&tree_buf, "%o ", canon_mode(mode));
2080 strbuf_addslice(&tree_buf, entry_path);
2081 strbuf_addch(&tree_buf, '\0');
2082 strbuf_add(&tree_buf, oid.hash, 20);
2083 }
2084
2085 if (!merge_tree_id) {
2086 cache_entry = xmalloc(sizeof(k));
2087 cache_entry->ent = k.ent;
2088 cache_entry->old_oid = k.old_oid;
2089 }
2090 store_git_tree(&tree_buf, reference, cache_entry ? &cache_entry->new_oid : result);
2091 strbuf_release(&tree_buf);
2092 if (!merge_tree_id) {
2093 hashmap_add(cache, &cache_entry->ent);
2094 }
2095
2096 cleanup:
2097 if (state.state_a.tree)
2098 free_tree_buffer(state.state_a.tree);
2099 if (state.state_b.tree)
2100 free_tree_buffer(state.state_b.tree);
2101 if (ref_state.tree)
2102 free_tree_buffer(ref_state.tree);
2103 }
2104 if (result && cache_entry)
2105 oidcpy(result, &cache_entry->new_oid);
2106 return;
2107
2108 corrupted:
2109 die("Corrupt mercurial metadata");
2110 }
2111
2112 static struct hashmap git_tree_cache;
2113
do_create_git_tree(struct string_list * args)2114 static void do_create_git_tree(struct string_list *args)
2115 {
2116 struct hg_object_id hg_oid;
2117 struct object_id oid;
2118 const struct object_id *manifest_oid;
2119 struct commit *commit;
2120 struct object_id *ref_tree = NULL;
2121
2122 if (args->nr == 0 || args->nr > 2)
2123 die("create-git-tree takes 1 or 2 arguments");
2124
2125 if (!strncmp(args->items[0].string, "git:", 4)) {
2126 if (get_oid_hex(args->items[0].string + 4, &oid))
2127 goto not_found;
2128 manifest_oid = &oid;
2129 } else {
2130 if (get_sha1_hex(args->items[0].string, hg_oid.hash))
2131 goto not_found;
2132
2133 manifest_oid = resolve_hg2git(&hg_oid, 40);
2134 if (!manifest_oid)
2135 goto not_found;
2136 }
2137
2138 commit = lookup_commit(the_repository, manifest_oid);
2139 if (parse_commit(commit))
2140 goto not_found;
2141
2142 if (args->nr == 2) {
2143 struct hg_object_id ref_oid;
2144 const struct object_id *ref_commit_oid;
2145 struct commit *ref_commit;
2146 if (get_sha1_hex(args->items[1].string, ref_oid.hash))
2147 die("invalid argument");
2148 ref_commit_oid = resolve_hg2git(&ref_oid, 40);
2149 if (!ref_commit_oid)
2150 die("invalid argument");
2151 ref_commit = lookup_commit(the_repository, ref_commit_oid);
2152 parse_commit_or_die(ref_commit);
2153 ref_tree = get_commit_tree_oid(ref_commit);
2154 }
2155
2156 recurse_create_git_tree(get_commit_tree_oid(commit), ref_tree, NULL,
2157 &oid, &git_tree_cache);
2158
2159 write_or_die(1, oid_to_hex(&oid), 40);
2160 write_or_die(1, "\n", 1);
2161 return;
2162
2163 not_found:
2164 die("Couldn't find manifest %s", args->items[0].string);
2165 }
2166
2167 // 12th bit is only used by builtin/blame.c, so it should be safe to use.
2168 #define FSCK_SEEN (1 << 12)
2169
do_seen(struct string_list * args)2170 static void do_seen(struct string_list *args)
2171 {
2172 struct object_id oid;
2173 int seen = 0;
2174
2175 if (args->nr != 2)
2176 die("seen takes two argument");
2177
2178 if (get_oid_hex(args->items[1].string, &oid))
2179 die("Invalid sha1");
2180
2181 if (!strcmp(args->items[0].string, "hg2git"))
2182 seen = oidset_insert(&hg2git_seen, &oid);
2183 else if (!strcmp(args->items[0].string, "git2hg")) {
2184 struct commit *c = lookup_commit(the_repository, &oid);
2185 if (!c)
2186 die("Unknown commit");
2187 seen = c->object.flags & FSCK_SEEN;
2188 c->object.flags |= FSCK_SEEN;
2189 }
2190
2191 if (seen)
2192 write_or_die(1, "yes\n", 4);
2193 else
2194 write_or_die(1, "no\n", 3);
2195 }
2196
2197 struct dangling_data {
2198 struct notes_tree *notes;
2199 struct strbuf *buf;
2200 int exclude_blobs;
2201 };
2202
dangling_note(const struct object_id * object_oid,const struct object_id * note_oid,char * note_path,void * cb_data)2203 static int dangling_note(const struct object_id *object_oid,
2204 const struct object_id *note_oid, char *note_path,
2205 void *cb_data)
2206 {
2207 struct dangling_data *data = cb_data;
2208 struct object_id oid;
2209 int is_dangling = 0;
2210
2211 oidcpy(&oid, object_oid);
2212 if (data->notes == &hg2git) {
2213 if (!data->exclude_blobs ||
2214 (oid_object_info(the_repository, note_oid, NULL) != OBJ_BLOB))
2215 is_dangling = !oidset_contains(&hg2git_seen, &oid);
2216 } else if (data->notes == &git2hg) {
2217 struct commit *c = lookup_commit(the_repository, &oid);
2218 is_dangling = !c || !(c->object.flags & FSCK_SEEN);
2219 }
2220
2221 if (is_dangling) {
2222 strbuf_add(data->buf, oid_to_hex(&oid), 40);
2223 strbuf_addch(data->buf, '\n');
2224 }
2225
2226 return 0;
2227 }
2228
do_dangling(struct string_list * args)2229 static void do_dangling(struct string_list *args)
2230 {
2231 struct strbuf buf = STRBUF_INIT;
2232 struct dangling_data data = { NULL, &buf, 0 };
2233
2234 if (args->nr != 1)
2235 die("dangling takes one argument");
2236
2237 if (!strcmp(args->items[0].string, "hg2git-no-blobs")) {
2238 data.notes = &hg2git;
2239 data.exclude_blobs = 1;
2240 } else if (!strcmp(args->items[0].string, "hg2git")) {
2241 data.notes = &hg2git;
2242 } else if (!strcmp(args->items[0].string, "git2hg")) {
2243 data.notes = &git2hg;
2244 } else {
2245 die("Unknown argument");
2246 }
2247
2248 ensure_notes(data.notes);
2249 for_each_note(data.notes, 0, dangling_note, &data);
2250
2251 send_buffer(&buf);
2252 strbuf_release(&buf);
2253 }
2254
init_config()2255 static void init_config()
2256 {
2257 struct strbuf conf = STRBUF_INIT;
2258 if (!config("check", &conf)) {
2259 struct strbuf **check = strbuf_split(&conf, ',');
2260 struct strbuf **c;
2261 for (c = check; *c; c++) {
2262 // strbuf_split leaves the `,`.
2263 if ((*c)->buf[(*c) -> len - 1] == ',')
2264 strbuf_setlen(*c, (*c)->len - 1);
2265 if (!strcmp((*c)->buf, "true") ||
2266 !strcmp((*c)->buf, "all"))
2267 cinnabar_check = -1;
2268 else if (!strcmp((*c)->buf, "helper"))
2269 cinnabar_check |= CHECK_HELPER;
2270 else if (!strcmp((*c)->buf, "manifests"))
2271 cinnabar_check |= CHECK_MANIFESTS;
2272 }
2273 strbuf_list_free(check);
2274 }
2275 strbuf_release(&conf);
2276
2277 if (!config("experiments", &conf)) {
2278 struct strbuf **check = strbuf_split(&conf, ',');
2279 struct strbuf **c;
2280 for (c = check; *c; c++) {
2281 // strbuf_split leaves the `,`.
2282 if ((*c)->buf[(*c) -> len - 1] == ',')
2283 strbuf_setlen(*c, (*c)->len - 1);
2284 if (!strcmp((*c)->buf, "true") ||
2285 !strcmp((*c)->buf, "all"))
2286 cinnabar_experiments = -1;
2287 else if (!strcmp((*c)->buf, "store"))
2288 cinnabar_experiments |= EXPERIMENT_STORE;
2289 }
2290 strbuf_list_free(check);
2291 }
2292 strbuf_release(&conf);
2293 }
2294
reset_replace_map()2295 static void reset_replace_map()
2296 {
2297 oidmap_free(the_repository->objects->replace_map, 1);
2298 FREE_AND_NULL(the_repository->objects->replace_map);
2299 the_repository->objects->replace_map_initialized = 0;
2300 }
2301
init_metadata()2302 static void init_metadata()
2303 {
2304 struct commit *c;
2305 const char *msg, *body;
2306 struct strbuf **flags, **f;
2307 struct tree *tree;
2308 struct tree_desc desc;
2309 struct name_entry entry;
2310 struct replace_object *replace;
2311
2312 c = lookup_commit_reference_by_name(METADATA_REF);
2313 if (!c)
2314 return;
2315 msg = get_commit_buffer(c, NULL);
2316 body = strstr(msg, "\n\n") + 2;
2317 unuse_commit_buffer(c, msg);
2318 flags = strbuf_split_str(body, ' ', -1);
2319 for (f = flags; *f; f++) {
2320 strbuf_trim(*f);
2321 if (!strcmp("files-meta", (*f)->buf))
2322 metadata_flags |= FILES_META;
2323 else if (!strcmp("unified-manifests", (*f)->buf))
2324 metadata_flags |= UNIFIED_MANIFESTS;
2325 else if (!strcmp("unified-manifests-v2", (*f)->buf))
2326 metadata_flags |= UNIFIED_MANIFESTS_v2;
2327 }
2328 strbuf_list_free(flags);
2329
2330 reset_replace_map();
2331 the_repository->objects->replace_map =
2332 xmalloc(sizeof(*the_repository->objects->replace_map));
2333 oidmap_init(the_repository->objects->replace_map, 0);
2334 the_repository->objects->replace_map_initialized = 1;
2335
2336 tree = get_commit_tree(c);
2337 parse_tree(tree);
2338 init_tree_desc(&desc, tree->buffer, tree->size);
2339 while (tree_entry(&desc, &entry)) {
2340 struct object_id original_oid;
2341 if (entry.pathlen != 40 ||
2342 get_oid_hex(entry.path, &original_oid)) {
2343 struct strbuf buf = STRBUF_INIT;
2344 strbuf_add(&buf, entry.path, entry.pathlen);
2345 warning(_("bad replace name: %s"), buf.buf);
2346 strbuf_release(&buf);
2347 continue;
2348 }
2349 if (oideq(&entry.oid, &original_oid)) {
2350 warning(_("self-referencing graft: %s"),
2351 oid_to_hex(&original_oid));
2352 continue;
2353 }
2354 replace = xmalloc(sizeof(*replace));
2355 oidcpy(&replace->original.oid, &original_oid);
2356 oidcpy(&replace->replacement, &entry.oid);
2357 if (oidmap_put(the_repository->objects->replace_map, replace))
2358 die(_("duplicate replace: %s"),
2359 oid_to_hex(&replace->original.oid));
2360 }
2361 }
2362
2363 void dump_branches(void);
2364
do_reload(struct string_list * args)2365 static void do_reload(struct string_list *args)
2366 {
2367 if (args->nr != 0)
2368 die("reload takes no arguments");
2369
2370 if (notes_initialized(&git2hg))
2371 free_notes(&git2hg);
2372
2373 if (notes_initialized(&hg2git))
2374 free_notes(&hg2git);
2375
2376 if (notes_initialized(&files_meta))
2377 free_notes(&files_meta);
2378
2379 oidset_clear(&hg2git_seen);
2380
2381 hashmap_clear_and_free(&git_tree_cache, struct oid_map_entry, ent);
2382 hashmap_init(&git_tree_cache, oid_map_entry_cmp, NULL, 0);
2383
2384 oid_array_clear(&manifest_heads);
2385 oid_array_clear(&changeset_heads);
2386
2387 dump_branches();
2388
2389 metadata_flags = 0;
2390 reset_replace_map();
2391 init_metadata();
2392 }
2393
2394 int configset_add_value(struct config_set *, const char*, const char *);
2395
config_set_callback(const char * key,const char * value,void * data)2396 static int config_set_callback(const char *key, const char *value, void *data)
2397 {
2398 struct config_set *config = data;
2399 configset_add_value(config, key, value);
2400 return 0;
2401 }
2402
init_git_config()2403 static void init_git_config()
2404 {
2405 struct child_process proc = CHILD_PROCESS_INIT;
2406 struct strbuf path = STRBUF_INIT;
2407 const char *env = getenv(EXEC_PATH_ENVIRONMENT);
2408 /* As the helper is not necessarily built with the same build options
2409 * as git (because it's built separately), the way its libgit.a is
2410 * going to find the system gitconfig may not match git's, and there
2411 * might be important configuration items there (like http.sslcainfo
2412 * on git for windows).
2413 * Trick git into giving us the path to it system gitconfig. */
2414 const char *argv[] = {
2415 "git", "config", "--system", "-e", NULL
2416 };
2417 if (env && *env) {
2418 setup_path();
2419 }
2420 proc.argv = argv;
2421 strvec_push(&proc.env_array, "GIT_EDITOR=echo");
2422 proc.no_stdin = 1;
2423 proc.no_stderr = 1;
2424 /* We don't really care about the capture_command return value. If
2425 * the path we get is empty we'll know it failed. */
2426 capture_command(&proc, &path, 0);
2427 strbuf_trim_trailing_newline(&path);
2428 /* Bail early when GIT_CONFIG_NO_SYSTEM is set. */
2429 if (!git_config_system())
2430 goto cleanup;
2431
2432 /* Avoid future uses of the git_config infrastructure reading the
2433 * config we just read (or the wrong system gitconfig). */
2434 putenv("GIT_CONFIG_NOSYSTEM=1");
2435
2436 /* If we couldn't get a path, then so be it. We may just not have
2437 * a complete configuration. */
2438 if (!path.len || access_or_die(path.buf, R_OK, 0))
2439 goto cleanup;
2440
2441 if (the_repository->config)
2442 // This shouldn't happen, but just in case...
2443 git_configset_clear(the_repository->config);
2444 else
2445 the_repository->config = xcalloc(1, sizeof(struct config_set));
2446
2447 git_configset_init(the_repository->config);
2448 git_configset_add_file(the_repository->config, path.buf);
2449 read_early_config(config_set_callback, the_repository->config);
2450
2451 cleanup:
2452 strbuf_release(&path);
2453 }
2454
restore_sigpipe_to_default(void)2455 static void restore_sigpipe_to_default(void)
2456 {
2457 sigset_t unblock;
2458
2459 sigemptyset(&unblock);
2460 sigaddset(&unblock, SIGPIPE);
2461 sigprocmask(SIG_UNBLOCK, &unblock, NULL);
2462 signal(SIGPIPE, SIG_DFL);
2463 }
2464
main(int argc,const char * argv[])2465 int main(int argc, const char *argv[])
2466 {
2467 int initialized = 0;
2468 struct strbuf buf = STRBUF_INIT;
2469
2470 // Initialization from common-main.c.
2471 trace2_initialize_clock();
2472
2473 sanitize_stdfds();
2474 restore_sigpipe_to_default();
2475
2476 git_resolve_executable_dir(argv[0]);
2477
2478 git_setup_gettext();
2479
2480 initialize_the_repository();
2481
2482 attr_start();
2483
2484 trace2_initialize();
2485 trace2_cmd_start(argv);
2486 trace2_collect_process_info(TRACE2_PROCESS_INFO_STARTUP);
2487
2488 if (argc > 1) {
2489 if (argc > 2)
2490 die("Too many arguments");
2491 if (!strcmp(argv[1], "--wire")) {
2492 mode = MODE_WIRE;
2493 } else if (!strcmp(argv[1], "--import")) {
2494 mode = MODE_IMPORT;
2495 }
2496 }
2497
2498 init_git_config();
2499 git_config(git_default_config, NULL);
2500 init_config();
2501 ignore_case = 0;
2502 save_commit_buffer = 0;
2503 warn_on_object_refname_ambiguity = 0;
2504
2505 while (strbuf_getline(&buf, stdin) != EOF) {
2506 struct string_list args = STRING_LIST_INIT_NODUP;
2507 const char *command;
2508 record_command(&buf);
2509 split_command(buf.buf, &command, &args);
2510 if (!strcmp("version", command)) {
2511 do_version(&args);
2512 string_list_clear(&args, 0);
2513 continue;
2514 } else if (!strcmp("helpercaps", command)) {
2515 do_helpercaps(&args);
2516 string_list_clear(&args, 0);
2517 continue;
2518 } else if ((mode & MODE_WIRE) && !strcmp("connect", command)) {
2519 do_connect(&args);
2520 string_list_clear(&args, 0);
2521 break;
2522 }
2523 if (!(mode & MODE_IMPORT))
2524 die("Unknown command: \"%s\"", command);
2525 if (!initialized) {
2526 setup_git_directory();
2527 git_config(git_diff_basic_config, NULL);
2528 ignore_case = 0;
2529 init_metadata();
2530 initialized = 1;
2531 hashmap_init(&git_tree_cache, oid_map_entry_cmp, NULL, 0);
2532 }
2533 if (!strcmp("git2hg", command))
2534 do_get_note(&git2hg, &args);
2535 else if (!strcmp("file-meta", command))
2536 // XXX: Should use a different function that reads a hg oid.
2537 do_get_note(&files_meta, &args);
2538 else if (!strcmp("hg2git", command))
2539 do_hg2git(&args);
2540 else if (!strcmp("manifest", command))
2541 do_manifest(&args);
2542 else if (!strcmp("check-manifest", command))
2543 do_check_manifest(&args);
2544 else if (!strcmp("check-file", command))
2545 do_check_file(&args);
2546 else if (!strcmp("cat-file", command))
2547 do_cat_file(&args);
2548 else if (!strcmp("ls-tree", command))
2549 do_ls_tree(&args);
2550 else if (!strcmp("rev-list", command))
2551 do_rev_list(&args);
2552 else if (!strcmp("diff-tree", command))
2553 do_diff_tree(&args);
2554 else if (!strcmp("heads", command))
2555 do_heads(&args);
2556 else if (!strcmp("reset-heads", command))
2557 do_reset_heads(&args);
2558 else if (!strcmp("upgrade", command))
2559 do_upgrade(&args);
2560 else if (!strcmp("create-git-tree", command))
2561 do_create_git_tree(&args);
2562 else if (!strcmp("seen", command))
2563 do_seen(&args);
2564 else if (!strcmp("dangling", command))
2565 do_dangling(&args);
2566 else if (!strcmp("reload", command))
2567 do_reload(&args);
2568 else if (!maybe_handle_command(command, &args))
2569 die("Unknown command: \"%s\"", command);
2570
2571 string_list_clear(&args, 0);
2572 }
2573
2574 strbuf_release(&buf);
2575
2576 if (notes_initialized(&git2hg))
2577 free_notes(&git2hg);
2578
2579 if (notes_initialized(&hg2git))
2580 free_notes(&hg2git);
2581
2582 if (notes_initialized(&files_meta))
2583 free_notes(&files_meta);
2584
2585 oidset_clear(&hg2git_seen);
2586 hashmap_clear_and_free(&git_tree_cache, struct oid_map_entry, ent);
2587 return 0;
2588 }
2589