1818#include "object-store.h"
1919#include "mem-pool.h"
2020#include "commit-reach.h"
21+ #include "khash.h"
2122
2223#define PACK_ID_BITS 16
2324#define MAX_PACK_ID ((1<<PACK_ID_BITS)-1)
@@ -53,6 +54,7 @@ struct object_entry_pool {
5354
5455struct mark_set {
5556 union {
57+ struct object_id * oids [1024 ];
5658 struct object_entry * marked [1024 ];
5759 struct mark_set * sets [1024 ];
5860 } data ;
@@ -225,6 +227,11 @@ static int allow_unsafe_features;
225227/* Signal handling */
226228static volatile sig_atomic_t checkpoint_requested ;
227229
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+
228235/* Where to write output of cat-blob commands */
229236static int cat_blob_fd = STDOUT_FILENO ;
230237
@@ -1731,6 +1738,11 @@ static void insert_object_entry(struct mark_set *s, struct object_id *oid, uintm
17311738 insert_mark (s , mark , e );
17321739}
17331740
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+
17341746static void read_mark_file (struct mark_set * s , FILE * f , mark_set_inserter_t inserter )
17351747{
17361748 char line [512 ];
@@ -1739,13 +1751,17 @@ static void read_mark_file(struct mark_set *s, FILE *f, mark_set_inserter_t inse
17391751 char * end ;
17401752 struct object_id oid ;
17411753
1754+ /* Ensure SHA-1 objects are padded with zeros. */
1755+ memset (oid .hash , 0 , sizeof (oid .hash ));
1756+
17421757 end = strchr (line , '\n' );
17431758 if (line [0 ] != ':' || !end )
17441759 die ("corrupt mark line: %s" , line );
17451760 * end = 0 ;
17461761 mark = strtoumax (line + 1 , & end , 10 );
17471762 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 )
17491765 die ("corrupt mark line: %s" , line );
17501766 inserter (s , & oid , mark );
17511767 }
@@ -2146,6 +2162,30 @@ static uintmax_t change_note_fanout(struct tree_entry *root,
21462162 return do_change_note_fanout (root , root , hex_oid , 0 , path , 0 , fanout );
21472163}
21482164
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+
21492189/*
21502190 * Given a pointer into a string, parse a mark reference:
21512191 *
@@ -2232,7 +2272,7 @@ static void file_change_m(const char *p, struct branch *b)
22322272 inline_data = 1 ;
22332273 oe = NULL ; /* not used with inline_data, but makes gcc happy */
22342274 } else {
2235- if (parse_oid_hex (p , & oid , & p ))
2275+ if (parse_mapped_oid_hex (p , & oid , & p ))
22362276 die ("Invalid dataref: %s" , command_buf .buf );
22372277 oe = find_object (& oid );
22382278 if (* p ++ != ' ' )
@@ -2406,7 +2446,7 @@ static void note_change_n(const char *p, struct branch *b, unsigned char *old_fa
24062446 inline_data = 1 ;
24072447 oe = NULL ; /* not used with inline_data, but makes gcc happy */
24082448 } else {
2409- if (parse_oid_hex (p , & oid , & p ))
2449+ if (parse_mapped_oid_hex (p , & oid , & p ))
24102450 die ("Invalid dataref: %s" , command_buf .buf );
24112451 oe = find_object (& oid );
24122452 if (* p ++ != ' ' )
@@ -2941,7 +2981,7 @@ static void parse_cat_blob(const char *p)
29412981 die ("Unknown mark: %s" , command_buf .buf );
29422982 oidcpy (& oid , & oe -> idx .oid );
29432983 } else {
2944- if (parse_oid_hex (p , & oid , & p ))
2984+ if (parse_mapped_oid_hex (p , & oid , & p ))
29452985 die ("Invalid dataref: %s" , command_buf .buf );
29462986 if (* p )
29472987 die ("Garbage after SHA1: %s" , command_buf .buf );
@@ -3005,6 +3045,42 @@ static struct object_entry *dereference(struct object_entry *oe,
30053045 return find_object (oid );
30063046}
30073047
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+
30083084static struct object_entry * parse_treeish_dataref (const char * * p )
30093085{
30103086 struct object_id oid ;
@@ -3016,7 +3092,7 @@ static struct object_entry *parse_treeish_dataref(const char **p)
30163092 die ("Unknown mark: %s" , command_buf .buf );
30173093 oidcpy (& oid , & e -> idx .oid );
30183094 } else { /* <sha1> */
3019- if (parse_oid_hex (* p , & oid , p ))
3095+ if (parse_mapped_oid_hex (* p , & oid , p ))
30203096 die ("Invalid dataref: %s" , command_buf .buf );
30213097 e = find_object (& oid );
30223098 if (* (* p )++ != ' ' )
@@ -3222,6 +3298,26 @@ static void option_export_pack_edges(const char *edges)
32223298 pack_edges = xfopen (edges , "a" );
32233299}
32243300
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+
32253321static int parse_one_option (const char * option )
32263322{
32273323 if (skip_prefix (option , "max-pack-size=" , & option )) {
@@ -3284,6 +3380,11 @@ static int parse_one_feature(const char *feature, int from_stream)
32843380 option_export_marks (arg );
32853381 } else if (!strcmp (feature , "alias" )) {
32863382 ; /* 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 )) {
32873388 } else if (!strcmp (feature , "get-mark" )) {
32883389 ; /* Don't die - this feature is supported */
32893390 } else if (!strcmp (feature , "cat-blob" )) {
@@ -3389,6 +3490,7 @@ static void parse_argv(void)
33893490 seen_data_command = 1 ;
33903491 if (import_marks_file )
33913492 read_marks ();
3493+ build_mark_map (& sub_marks_from , & sub_marks_to );
33923494}
33933495
33943496int cmd_main (int argc , const char * * argv )
0 commit comments