@@ -200,54 +200,54 @@ static void parse(FileSystemObjectSink & sink, Source & source, const CanonPath
200200 }
201201
202202 else if (type == " directory" ) {
203- sink.createDirectory (path);
203+ sink.createDirectory (path, [&](FileSystemObjectSink & dirSink, const CanonPath & relDirPath) {
204+ std::map<Path, int , CaseInsensitiveCompare> names;
204205
205- std::map<Path, int , CaseInsensitiveCompare> names ;
206+ std::string prevName ;
206207
207- std::string prevName;
208+ while (1 ) {
209+ auto tag = getString ();
208210
209- while ( 1 ) {
210- auto tag = getString () ;
211+ if (tag == " ) " )
212+ break ;
211213
212- if (tag == " )" )
213- break ;
214-
215- if (tag != " entry" )
216- throw badArchive (" expected tag 'entry' or ')', got '%s'" , tag);
217-
218- expectTag (" (" );
219-
220- expectTag (" name" );
221-
222- auto name = getString ();
223- if (name.empty () || name == " ." || name == " .." || name.find (' /' ) != std::string::npos
224- || name.find ((char ) 0 ) != std::string::npos)
225- throw badArchive (" NAR contains invalid file name '%1%'" , name);
226- if (name <= prevName)
227- throw badArchive (" NAR directory is not sorted" );
228- prevName = name;
229- if (archiveSettings.useCaseHack ) {
230- auto i = names.find (name);
231- if (i != names.end ()) {
232- debug (" case collision between '%1%' and '%2%'" , i->first , name);
233- name += caseHackSuffix;
234- name += std::to_string (++i->second );
235- auto j = names.find (name);
236- if (j != names.end ())
237- throw badArchive (
238- " NAR contains file name '%s' that collides with case-hacked file name '%s'" ,
239- prevName,
240- j->first );
241- } else
242- names[name] = 0 ;
243- }
214+ if (tag != " entry" )
215+ throw badArchive (" expected tag 'entry' or ')', got '%s'" , tag);
244216
245- expectTag (" node " );
217+ expectTag (" ( " );
246218
247- parse (sink, source, path / name);
219+ expectTag ( " name" );
248220
249- expectTag (" )" );
250- }
221+ auto name = getString ();
222+ if (name.empty () || name == " ." || name == " .." || name.find (' /' ) != std::string::npos
223+ || name.find ((char ) 0 ) != std::string::npos)
224+ throw badArchive (" NAR contains invalid file name '%1%'" , name);
225+ if (name <= prevName)
226+ throw badArchive (" NAR directory is not sorted" );
227+ prevName = name;
228+ if (archiveSettings.useCaseHack ) {
229+ auto i = names.find (name);
230+ if (i != names.end ()) {
231+ debug (" case collision between '%1%' and '%2%'" , i->first , name);
232+ name += caseHackSuffix;
233+ name += std::to_string (++i->second );
234+ auto j = names.find (name);
235+ if (j != names.end ())
236+ throw badArchive (
237+ " NAR contains file name '%s' that collides with case-hacked file name '%s'" ,
238+ prevName,
239+ j->first );
240+ } else
241+ names[name] = 0 ;
242+ }
243+
244+ expectTag (" node" );
245+
246+ parse (dirSink, source, relDirPath / name);
247+
248+ expectTag (" )" );
249+ }
250+ });
251251 }
252252
253253 else if (type == " symlink" ) {
0 commit comments