@@ -246,20 +246,39 @@ IncludeTree::FileList::getFileSize(size_t I) const {
246
246
Data.data () + I * sizeof (FileSizeTy));
247
247
}
248
248
249
+ static llvm::Error diagnoseFileChange (IncludeTree::File F, ObjectRef Content) {
250
+ auto FilenameBlob = F.getFilename ();
251
+ if (!FilenameBlob)
252
+ return FilenameBlob.takeError ();
253
+ cas::ObjectStore &DB = F.getCAS ();
254
+ std::string Filename (FilenameBlob->getData ());
255
+ std::string OldID = DB.getID (Content).toString ();
256
+ std::string NewID = DB.getID (F.getContentsRef ()).toString ();
257
+ return llvm::createStringError (llvm::inconvertibleErrorCode (),
258
+ " file '%s' changed during build; include-tree "
259
+ " contents changed from %s to %s" ,
260
+ Filename.c_str (), OldID.c_str (),
261
+ NewID.c_str ());
262
+ }
263
+
249
264
llvm::Error IncludeTree::FileList::forEachFileImpl (
250
- llvm::DenseSet< ObjectRef> &Seen,
265
+ llvm::DenseMap<ObjectRef, ObjectRef> &Seen,
251
266
llvm::function_ref<llvm::Error(File, FileSizeTy)> Callback) {
252
267
size_t Next = 0 ;
253
268
size_t FileCount = getNumFilesCurrentList ();
269
+
254
270
return forEachReference ([&](ObjectRef Ref) -> llvm::Error {
255
271
size_t Index = Next++;
256
- if (!Seen.insert (Ref).second )
257
- return llvm::Error::success ();
258
-
259
272
if (Index < FileCount) {
260
273
auto Include = File::get (getCAS (), Ref);
261
274
if (!Include)
262
275
return Include.takeError ();
276
+ auto Inserted = Seen.try_emplace (Ref, Include->getContentsRef ());
277
+ if (!Inserted.second ) {
278
+ if (Inserted.first ->second != Include->getContentsRef ())
279
+ return diagnoseFileChange (*Include, Inserted.first ->second );
280
+ return llvm::Error::success ();
281
+ }
263
282
return Callback (std::move (*Include), getFileSize (Index));
264
283
}
265
284
@@ -274,7 +293,7 @@ llvm::Error IncludeTree::FileList::forEachFileImpl(
274
293
275
294
llvm::Error IncludeTree::FileList::forEachFile (
276
295
llvm::function_ref<llvm::Error(File, FileSizeTy)> Callback) {
277
- llvm::DenseSet< ObjectRef> Seen;
296
+ llvm::DenseMap<ObjectRef, ObjectRef> Seen;
278
297
return forEachFileImpl (Seen, Callback);
279
298
}
280
299
@@ -321,7 +340,7 @@ bool IncludeTree::FileList::isValid(const ObjectProxy &Node) {
321
340
return false ;
322
341
unsigned NumFiles =
323
342
llvm::support::endian::read <uint32_t , llvm::endianness::little>(Data.data ());
324
- return NumFiles != 0 && NumFiles <= Base.getNumReferences () &&
343
+ return NumFiles <= Base.getNumReferences () &&
325
344
Data.size () == sizeof (uint32_t ) + NumFiles * sizeof (FileSizeTy);
326
345
}
327
346
@@ -1015,38 +1034,19 @@ class IncludeTreeFileSystem : public llvm::vfs::FileSystem {
1015
1034
};
1016
1035
} // namespace
1017
1036
1018
- static llvm::Error diagnoseFileChange (IncludeTree::File F, ObjectRef Content) {
1019
- auto FilenameBlob = F.getFilename ();
1020
- if (!FilenameBlob)
1021
- return FilenameBlob.takeError ();
1022
- cas::ObjectStore &DB = F.getCAS ();
1023
- std::string Filename (FilenameBlob->getData ());
1024
- std::string OldID = DB.getID (Content).toString ();
1025
- std::string NewID = DB.getID (F.getContentsRef ()).toString ();
1026
- return llvm::createStringError (llvm::inconvertibleErrorCode (),
1027
- " file '%s' changed during build; include-tree "
1028
- " contents changed from %s to %s" ,
1029
- Filename.c_str (), OldID.c_str (),
1030
- NewID.c_str ());
1031
- }
1032
-
1033
- Expected<IntrusiveRefCntPtr<llvm::vfs::FileSystem>>
1034
- cas::createIncludeTreeFileSystem (IncludeTreeRoot &Root) {
1035
- auto FileList = Root.getFileList ();
1036
- if (!FileList)
1037
- return FileList.takeError ();
1038
-
1039
- std::vector<IncludeTree::FileList::FileEntry> Files;
1040
- Files.reserve (FileList->getNumReferences ());
1041
-
1042
- if (auto Err = FileList->forEachFile (
1043
- [&](IncludeTree::File File, IncludeTree::FileList::FileSizeTy Size ) {
1044
- Files.push_back ({File.getRef (), Size });
1045
- return llvm::Error::success ();
1046
- }))
1047
- return std::move (Err);
1048
-
1049
- return createIncludeTreeFileSystem (Root.getCAS (), Files);
1037
+ static std::string computeFilename (StringRef Name, IncludeTreeFileSystem &FS) {
1038
+ SmallString<128 > Filename (Name);
1039
+ assert (Filename != " ." );
1040
+ llvm::sys::path::remove_dots (Filename);
1041
+
1042
+ StringRef DirName = llvm::sys::path::parent_path (Filename);
1043
+ if (DirName.empty ())
1044
+ DirName = " ." ;
1045
+ auto &DirEntry = FS.Directories [DirName];
1046
+ if (DirEntry == llvm::sys::fs::UniqueID ()) {
1047
+ DirEntry = llvm::vfs::getNextVirtualUniqueID ();
1048
+ }
1049
+ return Filename.str ().str ();
1050
1050
}
1051
1051
1052
1052
Expected<IntrusiveRefCntPtr<llvm::vfs::FileSystem>>
@@ -1077,20 +1077,7 @@ cas::createIncludeTreeFileSystem(
1077
1077
if (!FilenameBlob)
1078
1078
return FilenameBlob.takeError ();
1079
1079
1080
- SmallString<128 > Filename (FilenameBlob->getData ());
1081
- // Strip './' in the filename to match the behaviour of ASTWriter; we
1082
- // also strip './' in IncludeTreeFileSystem::getPath.
1083
- assert (Filename != " ." );
1084
- llvm::sys::path::remove_dots (Filename);
1085
-
1086
- StringRef DirName = llvm::sys::path::parent_path (Filename);
1087
- if (DirName.empty ())
1088
- DirName = " ." ;
1089
- auto &DirEntry = IncludeTreeFS->Directories [DirName];
1090
- if (DirEntry == llvm::sys::fs::UniqueID ()) {
1091
- DirEntry = llvm::vfs::getNextVirtualUniqueID ();
1092
- }
1093
-
1080
+ auto Filename = computeFilename (FilenameBlob->getData (), *IncludeTreeFS);
1094
1081
IncludeTreeFS->Files .insert (std::make_pair (
1095
1082
Filename,
1096
1083
IncludeTreeFileSystem::FileEntry{File->getContentsRef (), Entry.Size ,
@@ -1099,3 +1086,30 @@ cas::createIncludeTreeFileSystem(
1099
1086
1100
1087
return IncludeTreeFS;
1101
1088
}
1089
+
1090
+ Expected<IntrusiveRefCntPtr<llvm::vfs::FileSystem>>
1091
+ cas::createIncludeTreeFileSystem (IncludeTree::FileList &List) {
1092
+ auto &CAS = List.getCAS ();
1093
+ IntrusiveRefCntPtr<IncludeTreeFileSystem> IncludeTreeFS =
1094
+ new IncludeTreeFileSystem (CAS);
1095
+
1096
+ auto E = List.forEachFile (
1097
+ [&](IncludeTree::File File,
1098
+ IncludeTree::FileList::FileSizeTy Size ) -> llvm::Error {
1099
+ auto FilenameBlob = File.getFilename ();
1100
+ if (!FilenameBlob)
1101
+ return FilenameBlob.takeError ();
1102
+ auto Filename =
1103
+ computeFilename (FilenameBlob->getData (), *IncludeTreeFS);
1104
+ IncludeTreeFS->Files .insert (
1105
+ std::make_pair (Filename, IncludeTreeFileSystem::FileEntry{
1106
+ File.getContentsRef (), Size ,
1107
+ llvm::vfs::getNextVirtualUniqueID ()}));
1108
+ return llvm::Error::success ();
1109
+ });
1110
+
1111
+ if (E)
1112
+ return std::move (E);
1113
+
1114
+ return IncludeTreeFS;
1115
+ }
0 commit comments