@@ -56,18 +56,32 @@ static int has_unshown_parent(struct commit *commit)
5656}
5757
5858/* Since intptr_t is C99, we do not use it here */
59- static void mark_object ( struct object * object )
59+ static inline uint32_t * mark_to_ptr ( uint32_t mark )
6060{
61- last_idnum ++ ;
62- add_decoration (& idnums , object , ((uint32_t * )NULL ) + last_idnum );
61+ return ((uint32_t * )NULL ) + mark ;
62+ }
63+
64+ static inline uint32_t ptr_to_mark (void * mark )
65+ {
66+ return (uint32_t * )mark - (uint32_t * )NULL ;
67+ }
68+
69+ static inline void mark_object (struct object * object , uint32_t mark )
70+ {
71+ add_decoration (& idnums , object , mark_to_ptr (mark ));
72+ }
73+
74+ static inline void mark_next_object (struct object * object )
75+ {
76+ mark_object (object , ++ last_idnum );
6377}
6478
6579static int get_object_mark (struct object * object )
6680{
6781 void * decoration = lookup_decoration (& idnums , object );
6882 if (!decoration )
6983 return 0 ;
70- return ( uint32_t * ) decoration - ( uint32_t * ) NULL ;
84+ return ptr_to_mark ( decoration ) ;
7185}
7286
7387static void show_progress (void )
@@ -100,7 +114,7 @@ static void handle_object(const unsigned char *sha1)
100114 if (!buf )
101115 die ("Could not read blob %s" , sha1_to_hex (sha1 ));
102116
103- mark_object (object );
117+ mark_next_object (object );
104118
105119 printf ("blob\nmark :%d\ndata %lu\n" , last_idnum , size );
106120 if (size && fwrite (buf , size , 1 , stdout ) != 1 )
@@ -185,7 +199,7 @@ static void handle_commit(struct commit *commit, struct rev_info *rev)
185199 for (i = 0 ; i < diff_queued_diff .nr ; i ++ )
186200 handle_object (diff_queued_diff .queue [i ]-> two -> sha1 );
187201
188- mark_object (& commit -> object );
202+ mark_next_object (& commit -> object );
189203 if (!is_encoding_utf8 (encoding ))
190204 reencoded = reencode_string (message , "UTF-8" , encoding );
191205 if (!commit -> parents )
@@ -354,18 +368,85 @@ static void handle_tags_and_duplicates(struct path_list *extra_refs)
354368 }
355369}
356370
371+ static void export_marks (char * file )
372+ {
373+ unsigned int i ;
374+ uint32_t mark ;
375+ struct object_decoration * deco = idnums .hash ;
376+ FILE * f ;
377+
378+ f = fopen (file , "w" );
379+ if (!f )
380+ error ("Unable to open marks file %s for writing" , file );
381+
382+ for (i = 0 ; i < idnums .size ; ++ i ) {
383+ deco ++ ;
384+ if (deco && deco -> base && deco -> base -> type == 1 ) {
385+ mark = ptr_to_mark (deco -> decoration );
386+ fprintf (f , ":%u %s\n" , mark , sha1_to_hex (deco -> base -> sha1 ));
387+ }
388+ }
389+
390+ if (ferror (f ) || fclose (f ))
391+ error ("Unable to write marks file %s." , file );
392+ }
393+
394+ static void import_marks (char * input_file )
395+ {
396+ char line [512 ];
397+ FILE * f = fopen (input_file , "r" );
398+ if (!f )
399+ die ("cannot read %s: %s" , input_file , strerror (errno ));
400+
401+ while (fgets (line , sizeof (line ), f )) {
402+ uint32_t mark ;
403+ char * line_end , * mark_end ;
404+ unsigned char sha1 [20 ];
405+ struct object * object ;
406+
407+ line_end = strchr (line , '\n' );
408+ if (line [0 ] != ':' || !line_end )
409+ die ("corrupt mark line: %s" , line );
410+ * line_end = 0 ;
411+
412+ mark = strtoumax (line + 1 , & mark_end , 10 );
413+ if (!mark || mark_end == line + 1
414+ || * mark_end != ' ' || get_sha1 (mark_end + 1 , sha1 ))
415+ die ("corrupt mark line: %s" , line );
416+
417+ object = parse_object (sha1 );
418+ if (!object )
419+ die ("Could not read blob %s" , sha1_to_hex (sha1 ));
420+
421+ if (object -> flags & SHOWN )
422+ error ("Object %s already has a mark" , sha1 );
423+
424+ mark_object (object , mark );
425+ if (last_idnum < mark )
426+ last_idnum = mark ;
427+
428+ object -> flags |= SHOWN ;
429+ }
430+ fclose (f );
431+ }
432+
357433int cmd_fast_export (int argc , const char * * argv , const char * prefix )
358434{
359435 struct rev_info revs ;
360436 struct object_array commits = { 0 , 0 , NULL };
361437 struct path_list extra_refs = { NULL , 0 , 0 , 0 };
362438 struct commit * commit ;
439+ char * export_filename = NULL , * import_filename = NULL ;
363440 struct option options [] = {
364441 OPT_INTEGER (0 , "progress" , & progress ,
365442 "show progress after <n> objects" ),
366443 OPT_CALLBACK (0 , "signed-tags" , & signed_tag_mode , "mode" ,
367444 "select handling of signed tags" ,
368445 parse_opt_signed_tag_mode ),
446+ OPT_STRING (0 , "export-marks" , & export_filename , "FILE" ,
447+ "Dump marks to this file" ),
448+ OPT_STRING (0 , "import-marks" , & import_filename , "FILE" ,
449+ "Import marks from this file" ),
369450 OPT_END ()
370451 };
371452
@@ -378,6 +459,9 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
378459 if (argc > 1 )
379460 usage_with_options (fast_export_usage , options );
380461
462+ if (import_filename )
463+ import_marks (import_filename );
464+
381465 get_tags_and_duplicates (& revs .pending , & extra_refs );
382466
383467 if (prepare_revision_walk (& revs ))
@@ -400,5 +484,8 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
400484
401485 handle_tags_and_duplicates (& extra_refs );
402486
487+ if (export_filename )
488+ export_marks (export_filename );
489+
403490 return 0 ;
404491}
0 commit comments