Status::Status(StringRef Name, StringRef ExternalName, UniqueID UID,
sys::TimeValue MTime, uint32_t User, uint32_t Group,
uint64_t Size, file_type Type, perms Perms)
- : Name(Name), ExternalName(ExternalName), UID(UID), MTime(MTime),
- User(User), Group(Group), Size(Size), Type(Type), Perms(Perms) {}
+ : Name(Name), UID(UID), MTime(MTime), User(User), Group(Group), Size(Size),
+ Type(Type), Perms(Perms) {}
bool Status::equivalent(const Status &Other) const {
return getUniqueID() == Other.getUniqueID();
return EC;
Status Result(RealStatus);
Result.setName(Path.str());
- Result.setExternalName(Path.str());
return Result;
}
};
class FileEntry : public Entry {
+public:
+ enum NameKind {
+ NK_NotSet,
+ NK_External,
+ NK_Virtual
+ };
+private:
std::string ExternalContentsPath;
-
+ NameKind UseName;
public:
- FileEntry(StringRef Name, StringRef ExternalContentsPath)
- : Entry(EK_File, Name), ExternalContentsPath(ExternalContentsPath) {}
+ FileEntry(StringRef Name, StringRef ExternalContentsPath, NameKind UseName)
+ : Entry(EK_File, Name), ExternalContentsPath(ExternalContentsPath),
+ UseName(UseName) {}
StringRef getExternalContentsPath() const { return ExternalContentsPath; }
+ /// \brief whether to use the external path as the name for this file.
+ NameKind useName() const { return UseName; }
static bool classof(const Entry *E) { return E->getKind() == EK_File; }
};
///
/// All configuration options are optional.
/// 'case-sensitive': <boolean, default=true>
+/// 'use-external-names': <boolean, default=true>
///
/// Virtual directories are represented as
/// \verbatim
/// {
/// 'type': 'file',
/// 'name': <string>,
+/// 'use-external-name': <boolean> # Optional
/// 'external-contents': <path to external file>)
/// }
/// \endverbatim
/// \brief Whether to perform case-sensitive comparisons.
///
/// Currently, case-insensitive matching only works correctly with ASCII.
- bool CaseSensitive; ///< Whether to perform case-sensitive comparisons.
+ bool CaseSensitive;
+
+ /// \brief Whether to use to use the value of 'external-contents' for the
+ /// names of files. This global value is overridable on a per-file basis.
+ bool UseExternalNames;
/// @}
friend class VFSFromYAMLParser;
private:
VFSFromYAML(IntrusiveRefCntPtr<FileSystem> ExternalFS)
- : ExternalFS(ExternalFS), CaseSensitive(true) {}
+ : ExternalFS(ExternalFS), CaseSensitive(true), UseExternalNames(true) {}
/// \brief Looks up \p Path in \c Roots.
ErrorOr<Entry *> lookupPath(const Twine &Path);
KeyStatusPair("name", true),
KeyStatusPair("type", true),
KeyStatusPair("contents", false),
- KeyStatusPair("external-contents", false)
+ KeyStatusPair("external-contents", false),
+ KeyStatusPair("use-external-name", false),
};
DenseMap<StringRef, KeyStatus> Keys(
std::vector<Entry *> EntryArrayContents;
std::string ExternalContentsPath;
std::string Name;
+ FileEntry::NameKind UseExternalName = FileEntry::NK_NotSet;
EntryKind Kind;
for (yaml::MappingNode::iterator I = M->begin(), E = M->end(); I != E;
if (!parseScalarString(I->getValue(), Value, Buffer))
return NULL;
ExternalContentsPath = Value;
+ } else if (Key == "use-external-name") {
+ bool Val;
+ if (!parseScalarBool(I->getValue(), Val))
+ return NULL;
+ UseExternalName = Val ? FileEntry::NK_External : FileEntry::NK_Virtual;
} else {
llvm_unreachable("key missing from Keys");
}
if (!checkMissingKeys(N, Keys))
return NULL;
+ // check invalid configuration
+ if (Kind == EK_Directory && UseExternalName != FileEntry::NK_NotSet) {
+ error(N, "'use-external-name' is not supported for directories");
+ return NULL;
+ }
+
// Remove trailing slash(es)
StringRef Trimmed(Name);
while (Trimmed.size() > 1 && sys::path::is_separator(Trimmed.back()))
Entry *Result = 0;
switch (Kind) {
case EK_File:
- Result = new FileEntry(LastComponent, llvm_move(ExternalContentsPath));
+ Result = new FileEntry(LastComponent, llvm_move(ExternalContentsPath),
+ UseExternalName);
break;
case EK_Directory:
Result = new DirectoryEntry(LastComponent, llvm_move(EntryArrayContents),
KeyStatusPair Fields[] = {
KeyStatusPair("version", true),
KeyStatusPair("case-sensitive", false),
+ KeyStatusPair("use-external-names", false),
KeyStatusPair("roots", true),
};
} else if (Key == "case-sensitive") {
if (!parseScalarBool(I->getValue(), FS->CaseSensitive))
return false;
+ } else if (Key == "use-external-names") {
+ if (!parseScalarBool(I->getValue(), FS->UseExternalNames))
+ return false;
} else {
llvm_unreachable("key missing from Keys");
}
std::string PathStr(Path.str());
if (FileEntry *F = dyn_cast<FileEntry>(*Result)) {
ErrorOr<Status> S = ExternalFS->status(F->getExternalContentsPath());
- if (S) {
- assert(S->getName() == S->getExternalName() &&
- S->getName() == F->getExternalContentsPath());
+ assert(!S || S->getName() == F->getExternalContentsPath());
+ if (S && (F->useName() == FileEntry::NK_Virtual ||
+ (F->useName() == FileEntry::NK_NotSet && !UseExternalNames)))
S->setName(PathStr);
- }
return S;
} else { // directory
DirectoryEntry *DE = cast<DirectoryEntry>(*Result);
Status S = DE->getStatus();
S.setName(PathStr);
- S.setExternalName(PathStr);
return S;
}
}
// file
ErrorOr<vfs::Status> S = O->status("/file1");
ASSERT_EQ(errc::success, S.getError());
- EXPECT_EQ("/file1", S->getName());
- EXPECT_EQ("/foo/bar/a", S->getExternalName());
+ EXPECT_EQ("/foo/bar/a", S->getName());
ErrorOr<vfs::Status> SLower = O->status("/foo/bar/a");
EXPECT_EQ("/foo/bar/a", SLower->getName());
EXPECT_EQ(24, NumDiagnostics);
}
+TEST_F(VFSFromYAMLTest, UseExternalName) {
+ IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
+ Lower->addRegularFile("/external/file");
+
+ IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
+ "{ 'roots': [\n"
+ " { 'type': 'file', 'name': '/A',\n"
+ " 'external-contents': '/external/file'\n"
+ " },\n"
+ " { 'type': 'file', 'name': '/B',\n"
+ " 'use-external-name': true,\n"
+ " 'external-contents': '/external/file'\n"
+ " },\n"
+ " { 'type': 'file', 'name': '/C',\n"
+ " 'use-external-name': false,\n"
+ " 'external-contents': '/external/file'\n"
+ " }\n"
+ "] }", Lower);
+ ASSERT_TRUE(NULL != FS.getPtr());
+
+ // default true
+ EXPECT_EQ("/external/file", FS->status("/A")->getName());
+ // explicit
+ EXPECT_EQ("/external/file", FS->status("/B")->getName());
+ EXPECT_EQ("/C", FS->status("/C")->getName());
+
+ // global configuration
+ FS = getFromYAMLString(
+ "{ 'use-external-names': false,\n"
+ " 'roots': [\n"
+ " { 'type': 'file', 'name': '/A',\n"
+ " 'external-contents': '/external/file'\n"
+ " },\n"
+ " { 'type': 'file', 'name': '/B',\n"
+ " 'use-external-name': true,\n"
+ " 'external-contents': '/external/file'\n"
+ " },\n"
+ " { 'type': 'file', 'name': '/C',\n"
+ " 'use-external-name': false,\n"
+ " 'external-contents': '/external/file'\n"
+ " }\n"
+ "] }", Lower);
+ ASSERT_TRUE(NULL != FS.getPtr());
+
+ // default
+ EXPECT_EQ("/A", FS->status("/A")->getName());
+ // explicit
+ EXPECT_EQ("/external/file", FS->status("/B")->getName());
+ EXPECT_EQ("/C", FS->status("/C")->getName());
+}
+
TEST_F(VFSFromYAMLTest, MultiComponentPath) {
IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Lower->addRegularFile("/other");