@@ -56,18 +56,32 @@ static int has_unshown_parent(struct commit *commit)
56
56
}
57
57
58
58
/* 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 )
60
60
{
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 );
63
77
}
64
78
65
79
static int get_object_mark (struct object * object )
66
80
{
67
81
void * decoration = lookup_decoration (& idnums , object );
68
82
if (!decoration )
69
83
return 0 ;
70
- return ( uint32_t * ) decoration - ( uint32_t * ) NULL ;
84
+ return ptr_to_mark ( decoration ) ;
71
85
}
72
86
73
87
static void show_progress (void )
@@ -100,7 +114,7 @@ static void handle_object(const unsigned char *sha1)
100
114
if (!buf )
101
115
die ("Could not read blob %s" , sha1_to_hex (sha1 ));
102
116
103
- mark_object (object );
117
+ mark_next_object (object );
104
118
105
119
printf ("blob\nmark :%d\ndata %lu\n" , last_idnum , size );
106
120
if (size && fwrite (buf , size , 1 , stdout ) != 1 )
@@ -185,7 +199,7 @@ static void handle_commit(struct commit *commit, struct rev_info *rev)
185
199
for (i = 0 ; i < diff_queued_diff .nr ; i ++ )
186
200
handle_object (diff_queued_diff .queue [i ]-> two -> sha1 );
187
201
188
- mark_object (& commit -> object );
202
+ mark_next_object (& commit -> object );
189
203
if (!is_encoding_utf8 (encoding ))
190
204
reencoded = reencode_string (message , "UTF-8" , encoding );
191
205
if (!commit -> parents )
@@ -354,18 +368,85 @@ static void handle_tags_and_duplicates(struct path_list *extra_refs)
354
368
}
355
369
}
356
370
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
+
357
433
int cmd_fast_export (int argc , const char * * argv , const char * prefix )
358
434
{
359
435
struct rev_info revs ;
360
436
struct object_array commits = { 0 , 0 , NULL };
361
437
struct path_list extra_refs = { NULL , 0 , 0 , 0 };
362
438
struct commit * commit ;
439
+ char * export_filename = NULL , * import_filename = NULL ;
363
440
struct option options [] = {
364
441
OPT_INTEGER (0 , "progress" , & progress ,
365
442
"show progress after <n> objects" ),
366
443
OPT_CALLBACK (0 , "signed-tags" , & signed_tag_mode , "mode" ,
367
444
"select handling of signed tags" ,
368
445
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" ),
369
450
OPT_END ()
370
451
};
371
452
@@ -378,6 +459,9 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
378
459
if (argc > 1 )
379
460
usage_with_options (fast_export_usage , options );
380
461
462
+ if (import_filename )
463
+ import_marks (import_filename );
464
+
381
465
get_tags_and_duplicates (& revs .pending , & extra_refs );
382
466
383
467
if (prepare_revision_walk (& revs ))
@@ -400,5 +484,8 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
400
484
401
485
handle_tags_and_duplicates (& extra_refs );
402
486
487
+ if (export_filename )
488
+ export_marks (export_filename );
489
+
403
490
return 0 ;
404
491
}
0 commit comments