18
18
#include "object-store.h"
19
19
#include "mem-pool.h"
20
20
#include "commit-reach.h"
21
+ #include "khash.h"
21
22
22
23
#define PACK_ID_BITS 16
23
24
#define MAX_PACK_ID ((1<<PACK_ID_BITS)-1)
@@ -53,6 +54,7 @@ struct object_entry_pool {
53
54
54
55
struct mark_set {
55
56
union {
57
+ struct object_id * oids [1024 ];
56
58
struct object_entry * marked [1024 ];
57
59
struct mark_set * sets [1024 ];
58
60
} data ;
@@ -225,6 +227,11 @@ static int allow_unsafe_features;
225
227
/* Signal handling */
226
228
static volatile sig_atomic_t checkpoint_requested ;
227
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
+
228
235
/* Where to write output of cat-blob commands */
229
236
static int cat_blob_fd = STDOUT_FILENO ;
230
237
@@ -1731,6 +1738,11 @@ static void insert_object_entry(struct mark_set *s, struct object_id *oid, uintm
1731
1738
insert_mark (s , mark , e );
1732
1739
}
1733
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
+
1734
1746
static void read_mark_file (struct mark_set * s , FILE * f , mark_set_inserter_t inserter )
1735
1747
{
1736
1748
char line [512 ];
@@ -1739,13 +1751,17 @@ static void read_mark_file(struct mark_set *s, FILE *f, mark_set_inserter_t inse
1739
1751
char * end ;
1740
1752
struct object_id oid ;
1741
1753
1754
+ /* Ensure SHA-1 objects are padded with zeros. */
1755
+ memset (oid .hash , 0 , sizeof (oid .hash ));
1756
+
1742
1757
end = strchr (line , '\n' );
1743
1758
if (line [0 ] != ':' || !end )
1744
1759
die ("corrupt mark line: %s" , line );
1745
1760
* end = 0 ;
1746
1761
mark = strtoumax (line + 1 , & end , 10 );
1747
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 )
1749
1765
die ("corrupt mark line: %s" , line );
1750
1766
inserter (s , & oid , mark );
1751
1767
}
@@ -2146,6 +2162,30 @@ static uintmax_t change_note_fanout(struct tree_entry *root,
2146
2162
return do_change_note_fanout (root , root , hex_oid , 0 , path , 0 , fanout );
2147
2163
}
2148
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
+
2149
2189
/*
2150
2190
* Given a pointer into a string, parse a mark reference:
2151
2191
*
@@ -2232,7 +2272,7 @@ static void file_change_m(const char *p, struct branch *b)
2232
2272
inline_data = 1 ;
2233
2273
oe = NULL ; /* not used with inline_data, but makes gcc happy */
2234
2274
} else {
2235
- if (parse_oid_hex (p , & oid , & p ))
2275
+ if (parse_mapped_oid_hex (p , & oid , & p ))
2236
2276
die ("Invalid dataref: %s" , command_buf .buf );
2237
2277
oe = find_object (& oid );
2238
2278
if (* p ++ != ' ' )
@@ -2406,7 +2446,7 @@ static void note_change_n(const char *p, struct branch *b, unsigned char *old_fa
2406
2446
inline_data = 1 ;
2407
2447
oe = NULL ; /* not used with inline_data, but makes gcc happy */
2408
2448
} else {
2409
- if (parse_oid_hex (p , & oid , & p ))
2449
+ if (parse_mapped_oid_hex (p , & oid , & p ))
2410
2450
die ("Invalid dataref: %s" , command_buf .buf );
2411
2451
oe = find_object (& oid );
2412
2452
if (* p ++ != ' ' )
@@ -2941,7 +2981,7 @@ static void parse_cat_blob(const char *p)
2941
2981
die ("Unknown mark: %s" , command_buf .buf );
2942
2982
oidcpy (& oid , & oe -> idx .oid );
2943
2983
} else {
2944
- if (parse_oid_hex (p , & oid , & p ))
2984
+ if (parse_mapped_oid_hex (p , & oid , & p ))
2945
2985
die ("Invalid dataref: %s" , command_buf .buf );
2946
2986
if (* p )
2947
2987
die ("Garbage after SHA1: %s" , command_buf .buf );
@@ -3005,6 +3045,42 @@ static struct object_entry *dereference(struct object_entry *oe,
3005
3045
return find_object (oid );
3006
3046
}
3007
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
+
3008
3084
static struct object_entry * parse_treeish_dataref (const char * * p )
3009
3085
{
3010
3086
struct object_id oid ;
@@ -3016,7 +3092,7 @@ static struct object_entry *parse_treeish_dataref(const char **p)
3016
3092
die ("Unknown mark: %s" , command_buf .buf );
3017
3093
oidcpy (& oid , & e -> idx .oid );
3018
3094
} else { /* <sha1> */
3019
- if (parse_oid_hex (* p , & oid , p ))
3095
+ if (parse_mapped_oid_hex (* p , & oid , p ))
3020
3096
die ("Invalid dataref: %s" , command_buf .buf );
3021
3097
e = find_object (& oid );
3022
3098
if (* (* p )++ != ' ' )
@@ -3222,6 +3298,26 @@ static void option_export_pack_edges(const char *edges)
3222
3298
pack_edges = xfopen (edges , "a" );
3223
3299
}
3224
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
+
3225
3321
static int parse_one_option (const char * option )
3226
3322
{
3227
3323
if (skip_prefix (option , "max-pack-size=" , & option )) {
@@ -3284,6 +3380,11 @@ static int parse_one_feature(const char *feature, int from_stream)
3284
3380
option_export_marks (arg );
3285
3381
} else if (!strcmp (feature , "alias" )) {
3286
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 )) {
3287
3388
} else if (!strcmp (feature , "get-mark" )) {
3288
3389
; /* Don't die - this feature is supported */
3289
3390
} else if (!strcmp (feature , "cat-blob" )) {
@@ -3389,6 +3490,7 @@ static void parse_argv(void)
3389
3490
seen_data_command = 1 ;
3390
3491
if (import_marks_file )
3391
3492
read_marks ();
3493
+ build_mark_map (& sub_marks_from , & sub_marks_to );
3392
3494
}
3393
3495
3394
3496
int cmd_main (int argc , const char * * argv )
0 commit comments