55
('from' sp committish lf)?
56
lf?;
57
58
+ cat_blob ::= 'cat-blob' sp (hexsha1 | idnum) lf;
59
+
60
checkpoint ::= 'checkpoint' lf
61
lf?;
62
363
static struct strbuf new_data = STRBUF_INIT;
364
static int seen_data_command;
365
366
+/* Where to write output of cat-blob commands */
367
+static int cat_blob_fd = STDOUT_FILENO;
368
+
369
static void parse_argv(void);
370
371
static void write_branch_report(FILE *rpt, struct branch *b)
2694
unread_command_buf = 1;
2695
}
2696
2697
+static void cat_blob_write(const char *buf, unsigned long size)
2698
+{
2699
+ if (write_in_full(cat_blob_fd, buf, size) != size)
2700
+ die_errno("Write to frontend failed");
2701
+}
2702
+
2703
+static void cat_blob(struct object_entry *oe, unsigned char sha1[20])
2704
+{
2705
+ struct strbuf line = STRBUF_INIT;
2706
+ unsigned long size;
2707
+ enum object_type type = 0;
2708
+ char *buf;
2709
+
2710
+ if (!oe || oe->pack_id == MAX_PACK_ID) {
2711
+ buf = read_sha1_file(sha1, &type, &size);
2712
+ } else {
2713
+ type = oe->type;
2714
+ buf = gfi_unpack_entry(oe, &size);
2715
+ }
2716
+
2717
+ /*
2718
+ * Output based on batch_one_object() from cat-file.c.
2719
+ */
2720
+ if (type <= 0) {
2721
+ strbuf_reset(&line);
2722
+ strbuf_addf(&line, "%s missing\n", sha1_to_hex(sha1));
2723
+ cat_blob_write(line.buf, line.len);
2724
+ strbuf_release(&line);
2725
+ free(buf);
2726
+ return;
2727
+ }
2728
+ if (!buf)
2729
+ die("Can't read object %s", sha1_to_hex(sha1));
2730
+ if (type != OBJ_BLOB)
2731
+ die("Object %s is a %s but a blob was expected.",
2732
+ sha1_to_hex(sha1), typename(type));
2733
+ strbuf_reset(&line);
2734
+ strbuf_addf(&line, "%s %s %lu\n", sha1_to_hex(sha1),
2735
+ typename(type), size);
2736
+ cat_blob_write(line.buf, line.len);
2737
+ strbuf_release(&line);
2738
+ cat_blob_write(buf, size);
2739
+ cat_blob_write("\n", 1);
2740
+ free(buf);
2741
+}
2742
+
2743
+static void parse_cat_blob(void)
2744
+{
2745
+ const char *p;
2746
+ struct object_entry *oe = oe;
2747
+ unsigned char sha1[20];
2748
+
2749
+ /* cat-blob SP <object> LF */
2750
+ p = command_buf.buf + strlen("cat-blob ");
2751
+ if (*p == ':') {
2752
+ char *x;
2753
+ oe = find_mark(strtoumax(p + 1, &x, 10));
2754
+ if (x == p + 1)
2755
+ die("Invalid mark: %s", command_buf.buf);
2756
+ if (!oe)
2757
+ die("Unknown mark: %s", command_buf.buf);
2758
+ if (*x)
2759
+ die("Garbage after mark: %s", command_buf.buf);
2760
+ hashcpy(sha1, oe->idx.sha1);
2761
+ } else {
2762
+ if (get_sha1_hex(p, sha1))
2763
+ die("Invalid SHA1: %s", command_buf.buf);
2764
+ if (p[40])
2765
+ die("Garbage after SHA1: %s", command_buf.buf);
2766
+ oe = find_object(sha1);
2767
+ }
2768
+
2769
+ cat_blob(oe, sha1);
2770
+}
2771
+
2772
static void parse_checkpoint(void)
2773
{
2774
if (object_count) {
2853
safe_create_leading_directories_const(export_marks_file);
2854
}
2855
2856
+static void option_cat_blob_fd(const char *fd)
2857
+{
2858
+ unsigned long n = ulong_arg("--cat-blob-fd", fd);
2859
+ if (n > (unsigned long) INT_MAX)
2860
+ die("--cat-blob-fd cannot exceed %d", INT_MAX);
2861
+ cat_blob_fd = (int) n;
2862
+}
2863
+
2864
static void option_export_pack_edges(const char *edges)
2865
{
2866
if (pack_edges)
2914
option_import_marks(feature + 13, from_stream);
2915
} else if (!prefixcmp(feature, "export-marks=")) {
2916
option_export_marks(feature + 13);
2917
+ } else if (!strcmp(feature, "cat-blob")) {
2918
+ ; /* Don't die - this feature is supported */
2919
} else if (!prefixcmp(feature, "relative-marks")) {
2920
relative_marks_paths = 1;
2921
} else if (!prefixcmp(feature, "no-relative-marks")) {
3010
if (parse_one_feature(a + 2, 0))
3011
continue;
3012
3013
+ if (!prefixcmp(a + 2, "cat-blob-fd=")) {
3014
+ option_cat_blob_fd(a + 2 + strlen("cat-blob-fd="));
3015
+ continue;
3016
+ }
3017
+
3018
die("unknown option %s", a);
3019
}
3020
if (i != global_argc)
3066
parse_new_tag();
3067
else if (!prefixcmp(command_buf.buf, "reset "))
3068
parse_reset_branch();
3069
+ else if (!prefixcmp(command_buf.buf, "cat-blob "))
3070
+ parse_cat_blob();
3071
else if (!strcmp("checkpoint", command_buf.buf))
3072
parse_checkpoint();
3073
else if (!prefixcmp(command_buf.buf, "progress "))