11
11
#include "pack.h"
12
12
#include "blob.h"
13
13
#include "commit.h"
14
+ #include "run-command.h"
14
15
#include "tag.h"
15
16
#include "tree.h"
16
17
#include "tree-walk.h"
@@ -2578,10 +2579,11 @@ static void check_tag(const void *buf, size_t size)
2578
2579
}
2579
2580
2580
2581
static int index_mem (unsigned char * sha1 , void * buf , size_t size ,
2581
- int write_object , enum object_type type ,
2582
- const char * path , int format_check )
2582
+ enum object_type type ,
2583
+ const char * path , unsigned flags )
2583
2584
{
2584
2585
int ret , re_allocated = 0 ;
2586
+ int write_object = flags & HASH_WRITE_OBJECT ;
2585
2587
2586
2588
if (!type )
2587
2589
type = OBJ_BLOB ;
@@ -2597,7 +2599,7 @@ static int index_mem(unsigned char *sha1, void *buf, size_t size,
2597
2599
re_allocated = 1 ;
2598
2600
}
2599
2601
}
2600
- if (format_check ) {
2602
+ if (flags & HASH_FORMAT_CHECK ) {
2601
2603
if (type == OBJ_TREE )
2602
2604
check_tree (buf , size );
2603
2605
if (type == OBJ_COMMIT )
@@ -2615,44 +2617,141 @@ static int index_mem(unsigned char *sha1, void *buf, size_t size,
2615
2617
return ret ;
2616
2618
}
2617
2619
2620
+ static int index_pipe (unsigned char * sha1 , int fd , enum object_type type ,
2621
+ const char * path , unsigned flags )
2622
+ {
2623
+ struct strbuf sbuf = STRBUF_INIT ;
2624
+ int ret ;
2625
+
2626
+ if (strbuf_read (& sbuf , fd , 4096 ) >= 0 )
2627
+ ret = index_mem (sha1 , sbuf .buf , sbuf .len , type , path , flags );
2628
+ else
2629
+ ret = -1 ;
2630
+ strbuf_release (& sbuf );
2631
+ return ret ;
2632
+ }
2633
+
2618
2634
#define SMALL_FILE_SIZE (32*1024)
2619
2635
2620
- int index_fd (unsigned char * sha1 , int fd , struct stat * st , int write_object ,
2621
- enum object_type type , const char * path , int format_check )
2636
+ static int index_core (unsigned char * sha1 , int fd , size_t size ,
2637
+ enum object_type type , const char * path ,
2638
+ unsigned flags )
2622
2639
{
2623
2640
int ret ;
2624
- size_t size = xsize_t (st -> st_size );
2625
2641
2626
- if (!S_ISREG (st -> st_mode )) {
2627
- struct strbuf sbuf = STRBUF_INIT ;
2628
- if (strbuf_read (& sbuf , fd , 4096 ) >= 0 )
2629
- ret = index_mem (sha1 , sbuf .buf , sbuf .len , write_object ,
2630
- type , path , format_check );
2631
- else
2632
- ret = -1 ;
2633
- strbuf_release (& sbuf );
2634
- } else if (!size ) {
2635
- ret = index_mem (sha1 , NULL , size , write_object , type , path ,
2636
- format_check );
2642
+ if (!size ) {
2643
+ ret = index_mem (sha1 , NULL , size , type , path , flags );
2637
2644
} else if (size <= SMALL_FILE_SIZE ) {
2638
2645
char * buf = xmalloc (size );
2639
2646
if (size == read_in_full (fd , buf , size ))
2640
- ret = index_mem (sha1 , buf , size , write_object , type ,
2641
- path , format_check );
2647
+ ret = index_mem (sha1 , buf , size , type , path , flags );
2642
2648
else
2643
2649
ret = error ("short read %s" , strerror (errno ));
2644
2650
free (buf );
2645
2651
} else {
2646
2652
void * buf = xmmap (NULL , size , PROT_READ , MAP_PRIVATE , fd , 0 );
2647
- ret = index_mem (sha1 , buf , size , write_object , type , path ,
2648
- format_check );
2653
+ ret = index_mem (sha1 , buf , size , type , path , flags );
2649
2654
munmap (buf , size );
2650
2655
}
2656
+ return ret ;
2657
+ }
2658
+
2659
+ /*
2660
+ * This creates one packfile per large blob, because the caller
2661
+ * immediately wants the result sha1, and fast-import can report the
2662
+ * object name via marks mechanism only by closing the created
2663
+ * packfile.
2664
+ *
2665
+ * This also bypasses the usual "convert-to-git" dance, and that is on
2666
+ * purpose. We could write a streaming version of the converting
2667
+ * functions and insert that before feeding the data to fast-import
2668
+ * (or equivalent in-core API described above), but the primary
2669
+ * motivation for trying to stream from the working tree file and to
2670
+ * avoid mmaping it in core is to deal with large binary blobs, and
2671
+ * by definition they do _not_ want to get any conversion.
2672
+ */
2673
+ static int index_stream (unsigned char * sha1 , int fd , size_t size ,
2674
+ enum object_type type , const char * path ,
2675
+ unsigned flags )
2676
+ {
2677
+ struct child_process fast_import ;
2678
+ char export_marks [512 ];
2679
+ const char * argv [] = { "fast-import" , "--quiet" , export_marks , NULL };
2680
+ char tmpfile [512 ];
2681
+ char fast_import_cmd [512 ];
2682
+ char buf [512 ];
2683
+ int len , tmpfd ;
2684
+
2685
+ strcpy (tmpfile , git_path ("hashstream_XXXXXX" ));
2686
+ tmpfd = git_mkstemp_mode (tmpfile , 0600 );
2687
+ if (tmpfd < 0 )
2688
+ die_errno ("cannot create tempfile: %s" , tmpfile );
2689
+ if (close (tmpfd ))
2690
+ die_errno ("cannot close tempfile: %s" , tmpfile );
2691
+ sprintf (export_marks , "--export-marks=%s" , tmpfile );
2692
+
2693
+ memset (& fast_import , 0 , sizeof (fast_import ));
2694
+ fast_import .in = -1 ;
2695
+ fast_import .argv = argv ;
2696
+ fast_import .git_cmd = 1 ;
2697
+ if (start_command (& fast_import ))
2698
+ die_errno ("index-stream: git fast-import failed" );
2699
+
2700
+ len = sprintf (fast_import_cmd , "blob\nmark :1\ndata %lu\n" ,
2701
+ (unsigned long ) size );
2702
+ write_or_whine (fast_import .in , fast_import_cmd , len ,
2703
+ "index-stream: feeding fast-import" );
2704
+ while (size ) {
2705
+ char buf [10240 ];
2706
+ size_t sz = size < sizeof (buf ) ? size : sizeof (buf );
2707
+ size_t actual ;
2708
+
2709
+ actual = read_in_full (fd , buf , sz );
2710
+ if (actual < 0 )
2711
+ die_errno ("index-stream: reading input" );
2712
+ if (write_in_full (fast_import .in , buf , actual ) != actual )
2713
+ die_errno ("index-stream: feeding fast-import" );
2714
+ size -= actual ;
2715
+ }
2716
+ if (close (fast_import .in ))
2717
+ die_errno ("index-stream: closing fast-import" );
2718
+ if (finish_command (& fast_import ))
2719
+ die_errno ("index-stream: finishing fast-import" );
2720
+
2721
+ tmpfd = open (tmpfile , O_RDONLY );
2722
+ if (tmpfd < 0 )
2723
+ die_errno ("index-stream: cannot open fast-import mark" );
2724
+ len = read (tmpfd , buf , sizeof (buf ));
2725
+ if (len < 0 )
2726
+ die_errno ("index-stream: reading fast-import mark" );
2727
+ if (close (tmpfd ) < 0 )
2728
+ die_errno ("index-stream: closing fast-import mark" );
2729
+ if (unlink (tmpfile ))
2730
+ die_errno ("index-stream: unlinking fast-import mark" );
2731
+ if (len != 44 ||
2732
+ memcmp (":1 " , buf , 3 ) ||
2733
+ get_sha1_hex (buf + 3 , sha1 ))
2734
+ die_errno ("index-stream: unexpected fast-import mark: <%s>" , buf );
2735
+ return 0 ;
2736
+ }
2737
+
2738
+ int index_fd (unsigned char * sha1 , int fd , struct stat * st ,
2739
+ enum object_type type , const char * path , unsigned flags )
2740
+ {
2741
+ int ret ;
2742
+ size_t size = xsize_t (st -> st_size );
2743
+
2744
+ if (!S_ISREG (st -> st_mode ))
2745
+ ret = index_pipe (sha1 , fd , type , path , flags );
2746
+ else if (size <= big_file_threshold || type != OBJ_BLOB )
2747
+ ret = index_core (sha1 , fd , size , type , path , flags );
2748
+ else
2749
+ ret = index_stream (sha1 , fd , size , type , path , flags );
2651
2750
close (fd );
2652
2751
return ret ;
2653
2752
}
2654
2753
2655
- int index_path (unsigned char * sha1 , const char * path , struct stat * st , int write_object )
2754
+ int index_path (unsigned char * sha1 , const char * path , struct stat * st , unsigned flags )
2656
2755
{
2657
2756
int fd ;
2658
2757
struct strbuf sb = STRBUF_INIT ;
@@ -2663,7 +2762,7 @@ int index_path(unsigned char *sha1, const char *path, struct stat *st, int write
2663
2762
if (fd < 0 )
2664
2763
return error ("open(\"%s\"): %s" , path ,
2665
2764
strerror (errno ));
2666
- if (index_fd (sha1 , fd , st , write_object , OBJ_BLOB , path , 0 ) < 0 )
2765
+ if (index_fd (sha1 , fd , st , OBJ_BLOB , path , flags ) < 0 )
2667
2766
return error ("%s: failed to insert into database" ,
2668
2767
path );
2669
2768
break ;
@@ -2673,7 +2772,7 @@ int index_path(unsigned char *sha1, const char *path, struct stat *st, int write
2673
2772
return error ("readlink(\"%s\"): %s" , path ,
2674
2773
errstr );
2675
2774
}
2676
- if (!write_object )
2775
+ if (!( flags & HASH_WRITE_OBJECT ) )
2677
2776
hash_sha1_file (sb .buf , sb .len , blob_type , sha1 );
2678
2777
else if (write_sha1_file (sb .buf , sb .len , blob_type , sha1 ))
2679
2778
return error ("%s: failed to insert into database" ,
0 commit comments