18
#include "object-store.h"
19
#include "mem-pool.h"
20
#include "commit-reach.h"
21
+#include "khash.h"
22
23
#define PACK_ID_BITS 16
24
#define MAX_PACK_ID ((1<<PACK_ID_BITS)-1)
54
55
struct mark_set {
56
union {
57
+ struct object_id *oids[1024];
58
struct object_entry *marked[1024];
59
struct mark_set *sets[1024];
60
} data;
227
/* Signal handling */
228
static volatile sig_atomic_t checkpoint_requested;
229
230
+/* Submodule marks */
231
+static struct string_list sub_marks_from = STRING_LIST_INIT_DUP;
232
+static struct string_list sub_marks_to = STRING_LIST_INIT_DUP;
233
+static kh_oid_map_t *sub_oid_map;
234
+
235
/* Where to write output of cat-blob commands */
236
static int cat_blob_fd = STDOUT_FILENO;
237
1738
insert_mark(s, mark, e);
1739
}
1740
1741
+static void insert_oid_entry(struct mark_set *s, struct object_id *oid, uintmax_t mark)
1742
+{
1743
+ insert_mark(s, mark, xmemdupz(oid, sizeof(*oid)));
1744
+}
1745
+
1746
static void read_mark_file(struct mark_set *s, FILE *f, mark_set_inserter_t inserter)
1747
{
1748
char line[512];
1751
char *end;
1752
struct object_id oid;
1753
1754
+ /* Ensure SHA-1 objects are padded with zeros. */
1755
+ memset(oid.hash, 0, sizeof(oid.hash));
1756
+
1757
end = strchr(line, '\n');
1758
if (line[0] != ':' || !end)
1759
die("corrupt mark line: %s", line);
1760
*end = 0;
1761
mark = strtoumax(line + 1, &end, 10);
1762
if (!mark || end == line + 1
1748
- || *end != ' ' || get_oid_hex(end + 1, &oid))
1763
+ || *end != ' '
1764
+ || get_oid_hex_any(end + 1, &oid) == GIT_HASH_UNKNOWN)
1765
die("corrupt mark line: %s", line);
1766
inserter(s, &oid, mark);
1767
}
2162
return do_change_note_fanout(root, root, hex_oid, 0, path, 0, fanout);
2163
}
2164
2165
+static int parse_mapped_oid_hex(const char *hex, struct object_id *oid, const char **end)
2166
+{
2167
+ int algo;
2168
+ khiter_t it;
2169
+
2170
+ /* Make SHA-1 object IDs have all-zero padding. */
2171
+ memset(oid->hash, 0, sizeof(oid->hash));
2172
+
2173
+ algo = parse_oid_hex_any(hex, oid, end);
2174
+ if (algo == GIT_HASH_UNKNOWN)
2175
+ return -1;
2176
+
2177
+ it = kh_get_oid_map(sub_oid_map, *oid);
2178
+ /* No such object? */
2179
+ if (it == kh_end(sub_oid_map)) {
2180
+ /* If we're using the same algorithm, pass it through. */
2181
+ if (hash_algos[algo].format_id == the_hash_algo->format_id)
2182
+ return 0;
2183
+ return -1;
2184
+ }
2185
+ oidcpy(oid, kh_value(sub_oid_map, it));
2186
+ return 0;
2187
+}
2188
+
2189
/*
2190
* Given a pointer into a string, parse a mark reference:
2191
*
2272
inline_data = 1;
2273
oe = NULL; /* not used with inline_data, but makes gcc happy */
2274
} else {
2235
- if (parse_oid_hex(p, &oid, &p))
2275
+ if (parse_mapped_oid_hex(p, &oid, &p))
2276
die("Invalid dataref: %s", command_buf.buf);
2277
oe = find_object(&oid);
2278
if (*p++ != ' ')
2446
inline_data = 1;
2447
oe = NULL; /* not used with inline_data, but makes gcc happy */
2448
} else {
2409
- if (parse_oid_hex(p, &oid, &p))
2449
+ if (parse_mapped_oid_hex(p, &oid, &p))
2450
die("Invalid dataref: %s", command_buf.buf);
2451
oe = find_object(&oid);
2452
if (*p++ != ' ')
2981
die("Unknown mark: %s", command_buf.buf);
2982
oidcpy(&oid, &oe->idx.oid);
2983
} else {
2944
- if (parse_oid_hex(p, &oid, &p))
2984
+ if (parse_mapped_oid_hex(p, &oid, &p))
2985
die("Invalid dataref: %s", command_buf.buf);
2986
if (*p)
2987
die("Garbage after SHA1: %s", command_buf.buf);
3045
return find_object(oid);
3046
}
3047
3048
+static void insert_mapped_mark(uintmax_t mark, void *object, void *cbp)
3049
+{
3050
+ struct object_id *fromoid = object;
3051
+ struct object_id *tooid = find_mark(cbp, mark);
3052
+ int ret;
3053
+ khiter_t it;
3054
+
3055
+ it = kh_put_oid_map(sub_oid_map, *fromoid, &ret);
3056
+ /* We've already seen this object. */
3057
+ if (ret == 0)
3058
+ return;
3059
+ kh_value(sub_oid_map, it) = tooid;
3060
+}
3061
+
3062
+static void build_mark_map_one(struct mark_set *from, struct mark_set *to)
3063
+{
3064
+ for_each_mark(from, 0, insert_mapped_mark, to);
3065
+}
3066
+
3067
+static void build_mark_map(struct string_list *from, struct string_list *to)
3068
+{
3069
+ struct string_list_item *fromp, *top;
3070
+
3071
+ sub_oid_map = kh_init_oid_map();
3072
+
3073
+ for_each_string_list_item(fromp, from) {
3074
+ top = string_list_lookup(to, fromp->string);
3075
+ if (!fromp->util) {
3076
+ die(_("Missing from marks for submodule '%s'"), fromp->string);
3077
+ } else if (!top || !top->util) {
3078
+ die(_("Missing to marks for submodule '%s'"), fromp->string);
3079
+ }
3080
+ build_mark_map_one(fromp->util, top->util);
3081
+ }
3082
+}
3083
+
3084
static struct object_entry *parse_treeish_dataref(const char **p)
3085
{
3086
struct object_id oid;
3092
die("Unknown mark: %s", command_buf.buf);
3093
oidcpy(&oid, &e->idx.oid);
3094
} else { /* <sha1> */
3019
- if (parse_oid_hex(*p, &oid, p))
3095
+ if (parse_mapped_oid_hex(*p, &oid, p))
3096
die("Invalid dataref: %s", command_buf.buf);
3097
e = find_object(&oid);
3098
if (*(*p)++ != ' ')
3298
pack_edges = xfopen(edges, "a");
3299
}
3300
3301
+static void option_rewrite_submodules(const char *arg, struct string_list *list)
3302
+{
3303
+ struct mark_set *ms;
3304
+ FILE *fp;
3305
+ char *s = xstrdup(arg);
3306
+ char *f = strchr(s, ':');
3307
+ if (!f)
3308
+ die(_("Expected format name:filename for submodule rewrite option"));
3309
+ *f = '\0';
3310
+ f++;
3311
+ ms = xcalloc(1, sizeof(*ms));
3312
+ string_list_insert(list, s)->util = ms;
3313
+
3314
+ fp = fopen(f, "r");
3315
+ if (!fp)
3316
+ die_errno("cannot read '%s'", f);
3317
+ read_mark_file(ms, fp, insert_oid_entry);
3318
+ fclose(fp);
3319
+}
3320
+
3321
static int parse_one_option(const char *option)
3322
{
3323
if (skip_prefix(option, "max-pack-size=", &option)) {
3380
option_export_marks(arg);
3381
} else if (!strcmp(feature, "alias")) {
3382
; /* Don't die - this feature is supported */
3383
+ } else if (skip_prefix(feature, "rewrite-submodules-to=", &arg)) {
3384
+ option_rewrite_submodules(arg, &sub_marks_to);
3385
+ } else if (skip_prefix(feature, "rewrite-submodules-from=", &arg)) {
3386
+ option_rewrite_submodules(arg, &sub_marks_from);
3387
+ } else if (skip_prefix(feature, "rewrite-submodules-from=", &arg)) {
3388
} else if (!strcmp(feature, "get-mark")) {
3389
; /* Don't die - this feature is supported */
3390
} else if (!strcmp(feature, "cat-blob")) {
3490
seen_data_command = 1;
3491
if (import_marks_file)
3492
read_marks();
3493
+ build_mark_map(&sub_marks_from, &sub_marks_to);
3494
}
3495
3496
int cmd_main(int argc, const char **argv)