@@ -34,10 +34,127 @@ static int write_oid(const struct object_id *oid,
3434 return 0 ;
3535}
3636
37+ /*
38+ * Go through all .promisor files contained in repo (excluding those whose name
39+ * appears in not_repacked_basenames, which acts as a ignorelist), and copies
40+ * their content inside the destination file "<packtmp>-<dest_hex>.promisor".
41+ * Each line of a never repacked .promisor file is: "<oid> <ref>" (as described
42+ * in the write_promisor_file() function).
43+ * After a repack, the copied lines will be: "<oid> <ref> <time>", where <time>
44+ * is the time at which the .promisor file was last modified.
45+ * Only the lines whose <oid> is present inside "<packtmp>-<dest_hex>.idx" will
46+ * be copied.
47+ * The contents of all .promisor files are assumed to be correctly formed.
48+ */
49+ static void copy_promisor_content (struct repository * repo ,
50+ const char * dest_hex ,
51+ const char * packtmp ,
52+ struct strset * not_repacked_basenames )
53+ {
54+ char * dest_idx_name ;
55+ char * dest_promisor_name ;
56+ FILE * dest ;
57+ struct strset dest_content = STRSET_INIT ;
58+ struct strbuf dest_to_write = STRBUF_INIT ;
59+ struct strbuf source_promisor_name = STRBUF_INIT ;
60+ struct strbuf line = STRBUF_INIT ;
61+ struct object_id dest_oid ;
62+ struct packed_git * dest_pack , * p ;
63+ int err ;
64+
65+ dest_idx_name = mkpathdup ("%s-%s.idx" , packtmp , dest_hex );
66+ get_oid_hex_algop (dest_hex , & dest_oid , repo -> hash_algo );
67+ dest_pack = parse_pack_index (repo , dest_oid .hash , dest_idx_name );
68+
69+ /* Open the .promisor dest file, and fill dest_content with its content */
70+ dest_promisor_name = mkpathdup ("%s-%s.promisor" , packtmp , dest_hex );
71+ dest = xfopen (dest_promisor_name , "r+" );
72+ while (strbuf_getline (& line , dest ) != EOF )
73+ strset_add (& dest_content , line .buf );
74+
75+ repo_for_each_pack (repo , p ) {
76+ FILE * source ;
77+ struct stat source_stat ;
78+
79+ if (!p -> pack_promisor )
80+ continue ;
81+
82+ if (not_repacked_basenames &&
83+ strset_contains (not_repacked_basenames , pack_basename (p )))
84+ continue ;
85+
86+ strbuf_reset (& source_promisor_name );
87+ strbuf_addstr (& source_promisor_name , p -> pack_name );
88+ strbuf_strip_suffix (& source_promisor_name , ".pack" );
89+ strbuf_addstr (& source_promisor_name , ".promisor" );
90+
91+ if (stat (source_promisor_name .buf , & source_stat ))
92+ die (_ ("File not found: %s" ), source_promisor_name .buf );
93+
94+ source = xfopen (source_promisor_name .buf , "r" );
95+
96+ while (strbuf_getline (& line , source ) != EOF ) {
97+ struct strbuf * * parts ;
98+ struct object_id oid ;
99+
100+ /* Split line into <oid>, <ref> and <time> (if <time> exists) */
101+ parts = strbuf_split_max (& line , ' ' , 3 );
102+
103+ /* Ignore the lines where <oid> doesn't appear in the dest_pack */
104+ strbuf_rtrim (parts [0 ]);
105+ get_oid_hex_algop (parts [0 ]-> buf , & oid , repo -> hash_algo );
106+ if (!find_pack_entry_one (& oid , dest_pack ))
107+ continue ;
108+
109+ /* If <time> doesn't exist, retrieve it and add it to line */
110+ if (!parts [2 ])
111+ strbuf_addf (& line , " %" PRIuMAX ,
112+ (uintmax_t )source_stat .st_mtime );
113+
114+ /*
115+ * Add the finalized line to dest_to_write and dest_content if it
116+ * wasn't already present inside dest_content
117+ */
118+ if (strset_add (& dest_content , line .buf )) {
119+ strbuf_addbuf (& dest_to_write , & line );
120+ strbuf_addch (& dest_to_write , '\n' );
121+ }
122+
123+ strbuf_list_free (parts );
124+ }
125+
126+ err = ferror (source );
127+ err |= fclose (source );
128+ if (err )
129+ die (_ ("Could not read '%s' promisor file" ), source_promisor_name .buf );
130+ }
131+
132+ /* If dest_to_write is not empty, then there are new lines to append */
133+ if (dest_to_write .len ) {
134+ if (fseek (dest , 0L , SEEK_END ))
135+ die_errno (_ ("fseek failed" ));
136+ fprintf (dest , "%s" , dest_to_write .buf );
137+ }
138+
139+ err = ferror (dest );
140+ err |= fclose (dest );
141+ if (err )
142+ die (_ ("Could not write '%s' promisor file" ), dest_promisor_name );
143+
144+ close_pack_index (dest_pack );
145+ free (dest_idx_name );
146+ free (dest_promisor_name );
147+ strset_clear (& dest_content );
148+ strbuf_release (& dest_to_write );
149+ strbuf_release (& source_promisor_name );
150+ strbuf_release (& line );
151+ }
152+
37153static void finish_repacking_promisor_objects (struct repository * repo ,
38154 struct child_process * cmd ,
39155 struct string_list * names ,
40- const char * packtmp )
156+ const char * packtmp ,
157+ struct strset * not_repacked_basenames )
41158{
42159 struct strbuf line = STRBUF_INIT ;
43160 FILE * out ;
@@ -55,19 +172,15 @@ static void finish_repacking_promisor_objects(struct repository *repo,
55172
56173 /*
57174 * pack-objects creates the .pack and .idx files, but not the
58- * .promisor file. Create the .promisor file, which is empty.
59- *
60- * NEEDSWORK: fetch-pack sometimes generates non-empty
61- * .promisor files containing the ref names and associated
62- * hashes at the point of generation of the corresponding
63- * packfile, but this would not preserve their contents. Maybe
64- * concatenate the contents of all .promisor files instead of
65- * just creating a new empty file.
175+ * .promisor file. Create the .promisor file.
66176 */
67177 promisor_name = mkpathdup ("%s-%s.promisor" , packtmp ,
68178 line .buf );
69179 write_promisor_file (promisor_name , NULL , 0 );
70180
181+ /* Now let's fill the content of the newly created .promisor file */
182+ copy_promisor_content (repo , line .buf , packtmp , not_repacked_basenames );
183+
71184 item -> util = generated_pack_populate (item -> string , packtmp );
72185
73186 free (promisor_name );
@@ -107,7 +220,7 @@ void repack_promisor_objects(struct repository *repo,
107220 return ;
108221 }
109222
110- finish_repacking_promisor_objects (repo , & cmd , names , packtmp );
223+ finish_repacking_promisor_objects (repo , & cmd , names , packtmp , NULL );
111224}
112225
113226void pack_geometry_repack_promisors (struct repository * repo ,
@@ -118,6 +231,7 @@ void pack_geometry_repack_promisors(struct repository *repo,
118231{
119232 struct child_process cmd = CHILD_PROCESS_INIT ;
120233 FILE * in ;
234+ struct strset not_repacked_basenames = STRSET_INIT ;
121235
122236 if (!geometry -> promisor_split )
123237 return ;
@@ -131,9 +245,15 @@ void pack_geometry_repack_promisors(struct repository *repo,
131245 in = xfdopen (cmd .in , "w" );
132246 for (size_t i = 0 ; i < geometry -> promisor_split ; i ++ )
133247 fprintf (in , "%s\n" , pack_basename (geometry -> promisor_pack [i ]));
134- for (size_t i = geometry -> promisor_split ; i < geometry -> promisor_pack_nr ; i ++ )
135- fprintf (in , "^%s\n" , pack_basename (geometry -> promisor_pack [i ]));
248+ for (size_t i = geometry -> promisor_split ; i < geometry -> promisor_pack_nr ; i ++ ) {
249+ const char * name = pack_basename (geometry -> promisor_pack [i ]);
250+ fprintf (in , "^%s\n" , name );
251+ strset_add (& not_repacked_basenames , name );
252+ }
136253 fclose (in );
137254
138- finish_repacking_promisor_objects (repo , & cmd , names , packtmp );
255+ finish_repacking_promisor_objects (repo , & cmd , names , packtmp ,
256+ strset_get_size (& not_repacked_basenames ) ? & not_repacked_basenames : NULL );
257+
258+ strset_clear (& not_repacked_basenames );
139259}
0 commit comments