@@ -986,6 +986,16 @@ std::error_code InMemoryFileSystem::isLocal(const Twine &Path, bool &Result) {
986
986
// RedirectingFileSystem implementation
987
987
// ===-----------------------------------------------------------------------===/
988
988
989
+ RedirectingFileSystem::RedirectingFileSystem (IntrusiveRefCntPtr<FileSystem> FS)
990
+ : ExternalFS(std::move(FS)) {
991
+ if (ExternalFS)
992
+ if (auto ExternalWorkingDirectory =
993
+ ExternalFS->getCurrentWorkingDirectory ()) {
994
+ WorkingDirectory = *ExternalWorkingDirectory;
995
+ ExternalFSValidWD = true ;
996
+ }
997
+ }
998
+
989
999
// FIXME: reuse implementation common with OverlayFSDirIterImpl as these
990
1000
// iterators are conceptually similar.
991
1001
class llvm ::vfs::VFSFromYamlDirIterImpl
@@ -1032,12 +1042,27 @@ class llvm::vfs::VFSFromYamlDirIterImpl
1032
1042
1033
1043
llvm::ErrorOr<std::string>
1034
1044
RedirectingFileSystem::getCurrentWorkingDirectory () const {
1035
- return ExternalFS-> getCurrentWorkingDirectory () ;
1045
+ return WorkingDirectory ;
1036
1046
}
1037
1047
1038
1048
std::error_code
1039
1049
RedirectingFileSystem::setCurrentWorkingDirectory (const Twine &Path) {
1040
- return ExternalFS->setCurrentWorkingDirectory (Path);
1050
+ // Don't change the working directory if the path doesn't exist.
1051
+ if (!exists (Path))
1052
+ return errc::no_such_file_or_directory;
1053
+
1054
+ // Always change the external FS but ignore its result.
1055
+ if (ExternalFS) {
1056
+ auto EC = ExternalFS->setCurrentWorkingDirectory (Path);
1057
+ ExternalFSValidWD = !static_cast <bool >(EC);
1058
+ }
1059
+
1060
+ SmallString<128 > AbsolutePath;
1061
+ Path.toVector (AbsolutePath);
1062
+ if (std::error_code EC = makeAbsolute (AbsolutePath))
1063
+ return EC;
1064
+ WorkingDirectory = AbsolutePath.str ();
1065
+ return {};
1041
1066
}
1042
1067
1043
1068
std::error_code RedirectingFileSystem::isLocal (const Twine &Path,
@@ -1050,7 +1075,7 @@ directory_iterator RedirectingFileSystem::dir_begin(const Twine &Dir,
1050
1075
ErrorOr<RedirectingFileSystem::Entry *> E = lookupPath (Dir);
1051
1076
if (!E) {
1052
1077
EC = E.getError ();
1053
- if (IsFallthrough && EC == errc::no_such_file_or_directory)
1078
+ if (shouldUseExternalFS () && EC == errc::no_such_file_or_directory)
1054
1079
return ExternalFS->dir_begin (Dir, EC);
1055
1080
return {};
1056
1081
}
@@ -1068,7 +1093,7 @@ directory_iterator RedirectingFileSystem::dir_begin(const Twine &Dir,
1068
1093
auto *D = cast<RedirectingFileSystem::RedirectingDirectoryEntry>(*E);
1069
1094
return directory_iterator (std::make_shared<VFSFromYamlDirIterImpl>(
1070
1095
Dir, D->contents_begin (), D->contents_end (),
1071
- /* IterateExternalFS=*/ IsFallthrough , *ExternalFS, EC));
1096
+ /* IterateExternalFS=*/ shouldUseExternalFS () , *ExternalFS, EC));
1072
1097
}
1073
1098
1074
1099
void RedirectingFileSystem::setExternalContentsPrefixDir (StringRef PrefixDir) {
@@ -1218,7 +1243,7 @@ class llvm::vfs::RedirectingFileSystemParser {
1218
1243
}
1219
1244
1220
1245
auto *DE =
1221
- dyn_cast <RedirectingFileSystem::RedirectingDirectoryEntry>(ParentEntry);
1246
+ cast <RedirectingFileSystem::RedirectingDirectoryEntry>(ParentEntry);
1222
1247
DE->addContent (std::move (E));
1223
1248
return DE->getLastContent ();
1224
1249
}
@@ -1229,9 +1254,7 @@ class llvm::vfs::RedirectingFileSystemParser {
1229
1254
StringRef Name = SrcE->getName ();
1230
1255
switch (SrcE->getKind ()) {
1231
1256
case RedirectingFileSystem::EK_Directory: {
1232
- auto *DE =
1233
- dyn_cast<RedirectingFileSystem::RedirectingDirectoryEntry>(SrcE);
1234
- assert (DE && " Must be a directory" );
1257
+ auto *DE = cast<RedirectingFileSystem::RedirectingDirectoryEntry>(SrcE);
1235
1258
// Empty directories could be present in the YAML as a way to
1236
1259
// describe a file for a current directory after some of its subdir
1237
1260
// is parsed. This only leads to redundant walks, ignore it.
@@ -1243,11 +1266,10 @@ class llvm::vfs::RedirectingFileSystemParser {
1243
1266
break ;
1244
1267
}
1245
1268
case RedirectingFileSystem::EK_File: {
1246
- auto *FE = dyn_cast<RedirectingFileSystem::RedirectingFileEntry>(SrcE);
1247
- assert (FE && " Must be a file" );
1248
1269
assert (NewParentE && " Parent entry must exist" );
1249
- auto *DE = dyn_cast<RedirectingFileSystem::RedirectingDirectoryEntry>(
1250
- NewParentE);
1270
+ auto *FE = cast<RedirectingFileSystem::RedirectingFileEntry>(SrcE);
1271
+ auto *DE =
1272
+ cast<RedirectingFileSystem::RedirectingDirectoryEntry>(NewParentE);
1251
1273
DE->addContent (
1252
1274
llvm::make_unique<RedirectingFileSystem::RedirectingFileEntry>(
1253
1275
Name, FE->getExternalContentsPath (), FE->getUseName ()));
@@ -1570,7 +1592,7 @@ RedirectingFileSystem::create(std::unique_ptr<MemoryBuffer> Buffer,
1570
1592
RedirectingFileSystemParser P (Stream);
1571
1593
1572
1594
std::unique_ptr<RedirectingFileSystem> FS (
1573
- new RedirectingFileSystem (std::move ( ExternalFS) ));
1595
+ new RedirectingFileSystem (ExternalFS));
1574
1596
1575
1597
if (!YAMLFilePath.empty ()) {
1576
1598
// Use the YAML path from -ivfsoverlay to compute the dir to be prefixed
@@ -1699,7 +1721,7 @@ ErrorOr<Status> RedirectingFileSystem::status(const Twine &Path,
1699
1721
ErrorOr<Status> RedirectingFileSystem::status (const Twine &Path) {
1700
1722
ErrorOr<RedirectingFileSystem::Entry *> Result = lookupPath (Path);
1701
1723
if (!Result) {
1702
- if (IsFallthrough &&
1724
+ if (shouldUseExternalFS () &&
1703
1725
Result.getError () == llvm::errc::no_such_file_or_directory) {
1704
1726
return ExternalFS->status (Path);
1705
1727
}
@@ -1737,7 +1759,7 @@ ErrorOr<std::unique_ptr<File>>
1737
1759
RedirectingFileSystem::openFileForRead (const Twine &Path) {
1738
1760
ErrorOr<RedirectingFileSystem::Entry *> E = lookupPath (Path);
1739
1761
if (!E) {
1740
- if (IsFallthrough &&
1762
+ if (shouldUseExternalFS () &&
1741
1763
E.getError () == llvm::errc::no_such_file_or_directory) {
1742
1764
return ExternalFS->openFileForRead (Path);
1743
1765
}
@@ -1768,7 +1790,7 @@ RedirectingFileSystem::getRealPath(const Twine &Path,
1768
1790
SmallVectorImpl<char > &Output) const {
1769
1791
ErrorOr<RedirectingFileSystem::Entry *> Result = lookupPath (Path);
1770
1792
if (!Result) {
1771
- if (IsFallthrough &&
1793
+ if (shouldUseExternalFS () &&
1772
1794
Result.getError () == llvm::errc::no_such_file_or_directory) {
1773
1795
return ExternalFS->getRealPath (Path, Output);
1774
1796
}
@@ -1781,8 +1803,8 @@ RedirectingFileSystem::getRealPath(const Twine &Path,
1781
1803
}
1782
1804
// Even if there is a directory entry, fall back to ExternalFS if allowed,
1783
1805
// because directories don't have a single external contents path.
1784
- return IsFallthrough ? ExternalFS->getRealPath (Path, Output)
1785
- : llvm::errc::invalid_argument;
1806
+ return shouldUseExternalFS () ? ExternalFS->getRealPath (Path, Output)
1807
+ : llvm::errc::invalid_argument;
1786
1808
}
1787
1809
1788
1810
IntrusiveRefCntPtr<FileSystem>
0 commit comments