92
93
static struct packed_git *reuse_packfile;
94
static uint32_t reuse_packfile_objects;
95
-static off_t reuse_packfile_offset;
95
+static struct bitmap *reuse_packfile_bitmap;
96
97
static int use_bitmap_index_default = 1;
98
static int use_bitmap_index = -1;
785
return wo;
786
}
787
788
-static off_t write_reused_pack(struct hashfile *f)
788
+
789
+/*
790
+ * A reused set of objects. All objects in a chunk have the same
791
+ * relative position in the original packfile and the generated
792
+ * packfile.
793
+ */
794
+
795
+static struct reused_chunk {
796
+ /* The offset of the first object of this chunk in the original
797
+ * packfile. */
798
+ off_t original;
799
+ /* The offset of the first object of this chunk in the generated
800
+ * packfile minus "original". */
801
+ off_t difference;
802
+} *reused_chunks;
803
+static int reused_chunks_nr;
804
+static int reused_chunks_alloc;
805
+
806
+static void record_reused_object(off_t where, off_t offset)
807
+{
808
+ if (reused_chunks_nr && reused_chunks[reused_chunks_nr-1].difference == offset)
809
+ return;
810
+
811
+ ALLOC_GROW(reused_chunks, reused_chunks_nr + 1,
812
+ reused_chunks_alloc);
813
+ reused_chunks[reused_chunks_nr].original = where;
814
+ reused_chunks[reused_chunks_nr].difference = offset;
815
+ reused_chunks_nr++;
816
+}
817
+
818
+/*
819
+ * Binary search to find the chunk that "where" is in. Note
820
+ * that we're not looking for an exact match, just the first
821
+ * chunk that contains it (which implicitly ends at the start
822
+ * of the next chunk.
823
+ */
824
+static off_t find_reused_offset(off_t where)
825
{
790
- unsigned char buffer[8192];
791
- off_t to_write, total;
792
- int fd;
826
+ int lo = 0, hi = reused_chunks_nr;
827
+ while (lo < hi) {
828
+ int mi = lo + ((hi - lo) / 2);
829
+ if (where == reused_chunks[mi].original)
830
+ return reused_chunks[mi].difference;
831
+ if (where < reused_chunks[mi].original)
832
+ hi = mi;
833
+ else
834
+ lo = mi + 1;
835
+ }
836
794
- if (!is_pack_valid(reuse_packfile))
795
- die(_("packfile is invalid: %s"), reuse_packfile->pack_name);
837
+ /*
838
+ * The first chunk starts at zero, so we can't have gone below
839
+ * there.
840
+ */
841
+ assert(lo);
842
+ return reused_chunks[lo-1].difference;
843
+}
844
797
- fd = git_open(reuse_packfile->pack_name);
798
- if (fd < 0)
799
- die_errno(_("unable to open packfile for reuse: %s"),
800
- reuse_packfile->pack_name);
845
+static void write_reused_pack_one(size_t pos, struct hashfile *out,
846
+ struct pack_window **w_curs)
847
+{
848
+ off_t offset, next, cur;
849
+ enum object_type type;
850
+ unsigned long size;
851
802
- if (lseek(fd, sizeof(struct pack_header), SEEK_SET) == -1)
803
- die_errno(_("unable to seek in reused packfile"));
852
+ offset = reuse_packfile->revindex[pos].offset;
853
+ next = reuse_packfile->revindex[pos + 1].offset;
854
805
- if (reuse_packfile_offset < 0)
806
- reuse_packfile_offset = reuse_packfile->pack_size - the_hash_algo->rawsz;
855
+ record_reused_object(offset, offset - hashfile_total(out));
856
808
- total = to_write = reuse_packfile_offset - sizeof(struct pack_header);
857
+ cur = offset;
858
+ type = unpack_object_header(reuse_packfile, w_curs, &cur, &size);
859
+ assert(type >= 0);
860
810
- while (to_write) {
811
- int read_pack = xread(fd, buffer, sizeof(buffer));
861
+ if (type == OBJ_OFS_DELTA) {
862
+ off_t base_offset;
863
+ off_t fixup;
864
+
865
+ unsigned char header[MAX_PACK_OBJECT_HEADER];
866
+ unsigned len;
867
+
868
+ base_offset = get_delta_base(reuse_packfile, w_curs, &cur, type, offset);
869
+ assert(base_offset != 0);
870
+
871
+ /* Convert to REF_DELTA if we must... */
872
+ if (!allow_ofs_delta) {
873
+ int base_pos = find_revindex_position(reuse_packfile, base_offset);
874
+ const unsigned char *base_sha1 =
875
+ nth_packed_object_sha1(reuse_packfile,
876
+ reuse_packfile->revindex[base_pos].nr);
877
+
878
+ len = encode_in_pack_object_header(header, sizeof(header),
879
+ OBJ_REF_DELTA, size);
880
+ hashwrite(out, header, len);
881
+ hashwrite(out, base_sha1, 20);
882
+ copy_pack_data(out, reuse_packfile, w_curs, cur, next - cur);
883
+ return;
884
+ }
885
813
- if (read_pack <= 0)
814
- die_errno(_("unable to read from reused packfile"));
886
+ /* Otherwise see if we need to rewrite the offset... */
887
+ fixup = find_reused_offset(offset) -
888
+ find_reused_offset(base_offset);
889
+ if (fixup) {
890
+ unsigned char ofs_header[10];
891
+ unsigned i, ofs_len;
892
+ off_t ofs = offset - base_offset - fixup;
893
816
- if (read_pack > to_write)
817
- read_pack = to_write;
894
+ len = encode_in_pack_object_header(header, sizeof(header),
895
+ OBJ_OFS_DELTA, size);
896
819
- hashwrite(f, buffer, read_pack);
820
- to_write -= read_pack;
897
+ i = sizeof(ofs_header) - 1;
898
+ ofs_header[i] = ofs & 127;
899
+ while (ofs >>= 7)
900
+ ofs_header[--i] = 128 | (--ofs & 127);
901
+
902
+ ofs_len = sizeof(ofs_header) - i;
903
+
904
+ hashwrite(out, header, len);
905
+ hashwrite(out, ofs_header + sizeof(ofs_header) - ofs_len, ofs_len);
906
+ copy_pack_data(out, reuse_packfile, w_curs, cur, next - cur);
907
+ return;
908
+ }
909
+
910
+ /* ...otherwise we have no fixup, and can write it verbatim */
911
+ }
912
+
913
+ copy_pack_data(out, reuse_packfile, w_curs, offset, next - offset);
914
+}
915
+
916
+static size_t write_reused_pack_verbatim(struct hashfile *out,
917
+ struct pack_window **w_curs)
918
+{
919
+ size_t pos = 0;
920
+
921
+ while (pos < reuse_packfile_bitmap->word_alloc &&
922
+ reuse_packfile_bitmap->words[pos] == (eword_t)~0)
923
+ pos++;
924
+
925
+ if (pos) {
926
+ off_t to_write;
927
+
928
+ written = (pos * BITS_IN_EWORD);
929
+ to_write = reuse_packfile->revindex[written].offset
930
+ - sizeof(struct pack_header);
931
+
932
+ /* We're recording one chunk, not one object. */
933
+ record_reused_object(sizeof(struct pack_header), 0);
934
+ hashflush(out);
935
+ copy_pack_data(out, reuse_packfile, w_curs,
936
+ sizeof(struct pack_header), to_write);
937
822
- /*
823
- * We don't know the actual number of objects written,
824
- * only how many bytes written, how many bytes total, and
825
- * how many objects total. So we can fake it by pretending all
826
- * objects we are writing are the same size. This gives us a
827
- * smooth progress meter, and at the end it matches the true
828
- * answer.
829
- */
830
- written = reuse_packfile_objects *
831
- (((double)(total - to_write)) / total);
938
display_progress(progress_state, written);
939
}
940
+ return pos;
941
+}
942
+
943
+static void write_reused_pack(struct hashfile *f)
944
+{
945
+ size_t i = 0;
946
+ uint32_t offset;
947
+ struct pack_window *w_curs = NULL;
948
+
949
+ if (allow_ofs_delta)
950
+ i = write_reused_pack_verbatim(f, &w_curs);
951
+
952
+ for (; i < reuse_packfile_bitmap->word_alloc; ++i) {
953
+ eword_t word = reuse_packfile_bitmap->words[i];
954
+ size_t pos = (i * BITS_IN_EWORD);
955
+
956
+ for (offset = 0; offset < BITS_IN_EWORD; ++offset) {
957
+ if ((word >> offset) == 0)
958
+ break;
959
+
960
+ offset += ewah_bit_ctz64(word >> offset);
961
+ write_reused_pack_one(pos + offset, f, &w_curs);
962
+ display_progress(progress_state, ++written);
963
+ }
964
+ }
965
835
- close(fd);
836
- written = reuse_packfile_objects;
837
- display_progress(progress_state, written);
838
- return reuse_packfile_offset - sizeof(struct pack_header);
966
+ unuse_pack(&w_curs);
967
}
968
969
static const char no_split_warning[] = N_(
996
offset = write_pack_header(f, nr_remaining);
997
998
if (reuse_packfile) {
871
- off_t packfile_size;
999
assert(pack_to_stdout);
873
-
874
- packfile_size = write_reused_pack(f);
875
- offset += packfile_size;
1000
+ write_reused_pack(f);
1001
+ offset = hashfile_total(f);
1002
}
1003
1004
nr_written = 0;
2803
2804
if (nr_deltas && n > 1) {
2805
unsigned nr_done = 0;
2806
+
2807
if (progress)
2808
progress_state = start_progress(_("Compressing objects"),
2809
nr_deltas);
3189
{
3190
return allow_pack_reuse &&
3191
pack_to_stdout &&
3065
- allow_ofs_delta &&
3192
!ignore_packed_keep_on_disk &&
3193
!ignore_packed_keep_in_core &&
3194
(!local || !have_non_local_packs) &&
3205
bitmap_git,
3206
&reuse_packfile,
3207
&reuse_packfile_objects,
3082
- &reuse_packfile_offset)) {
3208
+ &reuse_packfile_bitmap)) {
3209
assert(reuse_packfile_objects);
3210
nr_result += reuse_packfile_objects;
3211
display_progress(progress_state, nr_result);