8
8
#include "strbuf.h"
9
9
#include "string-list.h"
10
10
#include "argv-array.h"
11
+ #include "packfile.h"
11
12
12
13
static int delta_base_offset = 1 ;
13
14
static int pack_kept_objects = -1 ;
@@ -83,7 +84,7 @@ static void remove_pack_on_signal(int signo)
83
84
84
85
/*
85
86
* Adds all packs hex strings to the fname list, which do not
86
- * have a corresponding .keep or .promisor file. These packs are not to
87
+ * have a corresponding .keep file. These packs are not to
87
88
* be kept if we are going to pack everything into one file.
88
89
*/
89
90
static void get_non_kept_pack_filenames (struct string_list * fname_list ,
@@ -111,8 +112,7 @@ static void get_non_kept_pack_filenames(struct string_list *fname_list,
111
112
112
113
fname = xmemdupz (e -> d_name , len );
113
114
114
- if (!file_exists (mkpath ("%s/%s.keep" , packdir , fname )) &&
115
- !file_exists (mkpath ("%s/%s.promisor" , packdir , fname )))
115
+ if (!file_exists (mkpath ("%s/%s.keep" , packdir , fname )))
116
116
string_list_append_nodup (fname_list , fname );
117
117
else
118
118
free (fname );
@@ -122,7 +122,7 @@ static void get_non_kept_pack_filenames(struct string_list *fname_list,
122
122
123
123
static void remove_redundant_pack (const char * dir_name , const char * base_name )
124
124
{
125
- const char * exts [] = {".pack" , ".idx" , ".keep" , ".bitmap" };
125
+ const char * exts [] = {".pack" , ".idx" , ".keep" , ".bitmap" , ".promisor" };
126
126
int i ;
127
127
struct strbuf buf = STRBUF_INIT ;
128
128
size_t plen ;
@@ -179,6 +179,76 @@ static void prepare_pack_objects(struct child_process *cmd,
179
179
cmd -> out = -1 ;
180
180
}
181
181
182
+ /*
183
+ * Write oid to the given struct child_process's stdin, starting it first if
184
+ * necessary.
185
+ */
186
+ static int write_oid (const struct object_id * oid , struct packed_git * pack ,
187
+ uint32_t pos , void * data )
188
+ {
189
+ struct child_process * cmd = data ;
190
+
191
+ if (cmd -> in == -1 ) {
192
+ if (start_command (cmd ))
193
+ die ("Could not start pack-objects to repack promisor objects" );
194
+ }
195
+
196
+ xwrite (cmd -> in , oid_to_hex (oid ), GIT_SHA1_HEXSZ );
197
+ xwrite (cmd -> in , "\n" , 1 );
198
+ return 0 ;
199
+ }
200
+
201
+ static void repack_promisor_objects (const struct pack_objects_args * args ,
202
+ struct string_list * names )
203
+ {
204
+ struct child_process cmd = CHILD_PROCESS_INIT ;
205
+ FILE * out ;
206
+ struct strbuf line = STRBUF_INIT ;
207
+
208
+ prepare_pack_objects (& cmd , args );
209
+ cmd .in = -1 ;
210
+
211
+ /*
212
+ * NEEDSWORK: Giving pack-objects only the OIDs without any ordering
213
+ * hints may result in suboptimal deltas in the resulting pack. See if
214
+ * the OIDs can be sent with fake paths such that pack-objects can use a
215
+ * {type -> existing pack order} ordering when computing deltas instead
216
+ * of a {type -> size} ordering, which may produce better deltas.
217
+ */
218
+ for_each_packed_object (write_oid , & cmd ,
219
+ FOR_EACH_OBJECT_PROMISOR_ONLY );
220
+
221
+ if (cmd .in == -1 )
222
+ /* No packed objects; cmd was never started */
223
+ return ;
224
+
225
+ close (cmd .in );
226
+
227
+ out = xfdopen (cmd .out , "r" );
228
+ while (strbuf_getline_lf (& line , out ) != EOF ) {
229
+ char * promisor_name ;
230
+ int fd ;
231
+ if (line .len != 40 )
232
+ die ("repack: Expecting 40 character sha1 lines only from pack-objects." );
233
+ string_list_append (names , line .buf );
234
+
235
+ /*
236
+ * pack-objects creates the .pack and .idx files, but not the
237
+ * .promisor file. Create the .promisor file, which is empty.
238
+ */
239
+ promisor_name = mkpathdup ("%s-%s.promisor" , packtmp ,
240
+ line .buf );
241
+ fd = open (promisor_name , O_CREAT |O_EXCL |O_WRONLY , 0600 );
242
+ if (fd < 0 )
243
+ die_errno ("unable to create '%s'" , promisor_name );
244
+ close (fd );
245
+ free (promisor_name );
246
+ }
247
+ fclose (out );
248
+ if (finish_command (& cmd ))
249
+ die ("Could not finish pack-objects to repack promisor objects" );
250
+ }
251
+
182
252
#define ALL_INTO_ONE 1
183
253
#define LOOSEN_UNREACHABLE 2
184
254
@@ -191,6 +261,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
191
261
{".pack" },
192
262
{".idx" },
193
263
{".bitmap" , 1 },
264
+ {".promisor" , 1 },
194
265
};
195
266
struct child_process cmd = CHILD_PROCESS_INIT ;
196
267
struct string_list_item * item ;
@@ -293,6 +364,8 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
293
364
if (pack_everything & ALL_INTO_ONE ) {
294
365
get_non_kept_pack_filenames (& existing_packs , & keep_pack_list );
295
366
367
+ repack_promisor_objects (& po_args , & names );
368
+
296
369
if (existing_packs .nr && delete_redundant ) {
297
370
if (unpack_unreachable ) {
298
371
argv_array_pushf (& cmd .args ,
@@ -440,6 +513,8 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
440
513
441
514
/* End of pack replacement. */
442
515
516
+ reprepare_packed_git (the_repository );
517
+
443
518
if (delete_redundant ) {
444
519
int opts = 0 ;
445
520
string_list_sort (& names );
0 commit comments