@@ -986,6 +986,16 @@ std::error_code InMemoryFileSystem::isLocal(const Twine &Path, bool &Result) {
986986// RedirectingFileSystem implementation
987987// ===-----------------------------------------------------------------------===/
988988
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+
989999// FIXME: reuse implementation common with OverlayFSDirIterImpl as these
9901000// iterators are conceptually similar.
9911001class llvm ::vfs::VFSFromYamlDirIterImpl
@@ -1032,12 +1042,27 @@ class llvm::vfs::VFSFromYamlDirIterImpl
10321042
10331043llvm::ErrorOr<std::string>
10341044RedirectingFileSystem::getCurrentWorkingDirectory () const {
1035- return ExternalFS-> getCurrentWorkingDirectory () ;
1045+ return WorkingDirectory ;
10361046}
10371047
10381048std::error_code
10391049RedirectingFileSystem::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 {};
10411066}
10421067
10431068std::error_code RedirectingFileSystem::isLocal (const Twine &Path,
@@ -1050,7 +1075,7 @@ directory_iterator RedirectingFileSystem::dir_begin(const Twine &Dir,
10501075 ErrorOr<RedirectingFileSystem::Entry *> E = lookupPath (Dir);
10511076 if (!E) {
10521077 EC = E.getError ();
1053- if (IsFallthrough && EC == errc::no_such_file_or_directory)
1078+ if (shouldUseExternalFS () && EC == errc::no_such_file_or_directory)
10541079 return ExternalFS->dir_begin (Dir, EC);
10551080 return {};
10561081 }
@@ -1068,7 +1093,7 @@ directory_iterator RedirectingFileSystem::dir_begin(const Twine &Dir,
10681093 auto *D = cast<RedirectingFileSystem::RedirectingDirectoryEntry>(*E);
10691094 return directory_iterator (std::make_shared<VFSFromYamlDirIterImpl>(
10701095 Dir, D->contents_begin (), D->contents_end (),
1071- /* IterateExternalFS=*/ IsFallthrough , *ExternalFS, EC));
1096+ /* IterateExternalFS=*/ shouldUseExternalFS () , *ExternalFS, EC));
10721097}
10731098
10741099void RedirectingFileSystem::setExternalContentsPrefixDir (StringRef PrefixDir) {
@@ -1218,7 +1243,7 @@ class llvm::vfs::RedirectingFileSystemParser {
12181243 }
12191244
12201245 auto *DE =
1221- dyn_cast <RedirectingFileSystem::RedirectingDirectoryEntry>(ParentEntry);
1246+ cast <RedirectingFileSystem::RedirectingDirectoryEntry>(ParentEntry);
12221247 DE->addContent (std::move (E));
12231248 return DE->getLastContent ();
12241249 }
@@ -1229,9 +1254,7 @@ class llvm::vfs::RedirectingFileSystemParser {
12291254 StringRef Name = SrcE->getName ();
12301255 switch (SrcE->getKind ()) {
12311256 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);
12351258 // Empty directories could be present in the YAML as a way to
12361259 // describe a file for a current directory after some of its subdir
12371260 // is parsed. This only leads to redundant walks, ignore it.
@@ -1243,11 +1266,10 @@ class llvm::vfs::RedirectingFileSystemParser {
12431266 break ;
12441267 }
12451268 case RedirectingFileSystem::EK_File: {
1246- auto *FE = dyn_cast<RedirectingFileSystem::RedirectingFileEntry>(SrcE);
1247- assert (FE && " Must be a file" );
12481269 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);
12511273 DE->addContent (
12521274 llvm::make_unique<RedirectingFileSystem::RedirectingFileEntry>(
12531275 Name, FE->getExternalContentsPath (), FE->getUseName ()));
@@ -1570,7 +1592,7 @@ RedirectingFileSystem::create(std::unique_ptr<MemoryBuffer> Buffer,
15701592 RedirectingFileSystemParser P (Stream);
15711593
15721594 std::unique_ptr<RedirectingFileSystem> FS (
1573- new RedirectingFileSystem (std::move ( ExternalFS) ));
1595+ new RedirectingFileSystem (ExternalFS));
15741596
15751597 if (!YAMLFilePath.empty ()) {
15761598 // Use the YAML path from -ivfsoverlay to compute the dir to be prefixed
@@ -1699,7 +1721,7 @@ ErrorOr<Status> RedirectingFileSystem::status(const Twine &Path,
16991721ErrorOr<Status> RedirectingFileSystem::status (const Twine &Path) {
17001722 ErrorOr<RedirectingFileSystem::Entry *> Result = lookupPath (Path);
17011723 if (!Result) {
1702- if (IsFallthrough &&
1724+ if (shouldUseExternalFS () &&
17031725 Result.getError () == llvm::errc::no_such_file_or_directory) {
17041726 return ExternalFS->status (Path);
17051727 }
@@ -1737,7 +1759,7 @@ ErrorOr<std::unique_ptr<File>>
17371759RedirectingFileSystem::openFileForRead (const Twine &Path) {
17381760 ErrorOr<RedirectingFileSystem::Entry *> E = lookupPath (Path);
17391761 if (!E) {
1740- if (IsFallthrough &&
1762+ if (shouldUseExternalFS () &&
17411763 E.getError () == llvm::errc::no_such_file_or_directory) {
17421764 return ExternalFS->openFileForRead (Path);
17431765 }
@@ -1768,7 +1790,7 @@ RedirectingFileSystem::getRealPath(const Twine &Path,
17681790 SmallVectorImpl<char > &Output) const {
17691791 ErrorOr<RedirectingFileSystem::Entry *> Result = lookupPath (Path);
17701792 if (!Result) {
1771- if (IsFallthrough &&
1793+ if (shouldUseExternalFS () &&
17721794 Result.getError () == llvm::errc::no_such_file_or_directory) {
17731795 return ExternalFS->getRealPath (Path, Output);
17741796 }
@@ -1781,8 +1803,8 @@ RedirectingFileSystem::getRealPath(const Twine &Path,
17811803 }
17821804 // Even if there is a directory entry, fall back to ExternalFS if allowed,
17831805 // 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;
17861808}
17871809
17881810IntrusiveRefCntPtr<FileSystem>
0 commit comments