13#include "llvm/Support/FileSystem.h"
14#include "llvm/Support/MemoryBuffer.h"
15#include "llvm/Support/Path.h"
16#include "llvm/Support/raw_ostream.h"
31 for (MappingsTy::iterator
32 I = FromToMappings.begin(),
E = FromToMappings.end();
I !=
E; ++
I)
33 resetTarget(
I->second);
34 FromToMappings.clear();
35 assert(ToFromMappings.empty());
36 if (!outputDir.empty()) {
37 std::string infoFile = getRemapInfoFile(outputDir);
38 llvm::sys::fs::remove(infoFile);
42std::string FileRemapper::getRemapInfoFile(StringRef outputDir) {
43 assert(!outputDir.empty());
45 llvm::sys::path::append(InfoFile,
"remap");
46 return std::string(InfoFile);
50 bool ignoreIfFilesChanged) {
51 std::string infoFile = getRemapInfoFile(outputDir);
56 bool ignoreIfFilesChanged) {
57 assert(FromToMappings.empty() &&
58 "initFromDisk should be called before any remap calls");
59 std::string infoFile = std::string(filePath);
60 if (!llvm::sys::fs::exists(infoFile))
63 std::vector<std::pair<FileEntryRef, FileEntryRef>> pairs;
65 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileBuf =
66 llvm::MemoryBuffer::getFile(infoFile,
true);
68 return report(
"Error opening file: " + infoFile,
Diag);
71 fileBuf.get()->getBuffer().split(lines,
"\n");
73 for (
unsigned idx = 0; idx+3 <= lines.size(); idx += 3) {
74 StringRef fromFilename = lines[idx];
75 unsigned long long timeModified;
76 if (lines[idx+1].getAsInteger(10, timeModified))
77 return report(
"Invalid file data: '" + lines[idx+1] +
"' not a number",
79 StringRef toFilename = lines[idx+2];
81 auto origFE = FileMgr->getOptionalFileRef(fromFilename);
83 if (ignoreIfFilesChanged)
85 return report(
"File does not exist: " + fromFilename,
Diag);
87 auto newFE = FileMgr->getOptionalFileRef(toFilename);
89 if (ignoreIfFilesChanged)
91 return report(
"File does not exist: " + toFilename,
Diag);
94 if ((uint64_t)origFE->getModificationTime() != timeModified) {
95 if (ignoreIfFilesChanged)
97 return report(
"File was modified: " + fromFilename,
Diag);
100 pairs.push_back(std::make_pair(*origFE, *newFE));
103 for (
unsigned i = 0, e = pairs.size(); i != e; ++i)
104 remap(pairs[i].first, pairs[i].second);
110 using namespace llvm::sys;
112 if (fs::create_directory(outputDir))
113 return report(
"Could not create directory: " + outputDir,
Diag);
115 std::string infoFile = getRemapInfoFile(outputDir);
120 using namespace llvm::sys;
123 std::string infoFile = std::string(outputPath);
124 llvm::raw_fd_ostream infoOut(infoFile, EC, llvm::sys::fs::OF_Text);
126 return report(EC.message(),
Diag);
128 for (MappingsTy::iterator
129 I = FromToMappings.begin(),
E = FromToMappings.end();
I !=
E; ++
I) {
133 fs::make_absolute(origPath);
134 infoOut << origPath <<
'\n';
137 if (
const auto *FE = std::get_if<FileEntryRef>(&
I->second)) {
139 fs::make_absolute(newPath);
140 infoOut << newPath <<
'\n';
145 if (fs::createTemporaryFile(
146 path::filename(origFE.
getName()),
147 path::extension(origFE.
getName()).drop_front(), fd, tempPath,
148 llvm::sys::fs::OF_Text))
149 return report(
"Could not create file: " + tempPath.str(),
Diag);
151 llvm::raw_fd_ostream newOut(fd,
true);
152 llvm::MemoryBuffer *mem = std::get<llvm::MemoryBuffer *>(
I->second);
153 newOut.write(mem->getBufferStart(), mem->getBufferSize());
156 auto newE = FileMgr->getOptionalFileRef(tempPath);
158 remap(origFE, *newE);
159 infoOut << newE->getName() <<
'\n';
169 StringRef outputDir) {
170 using namespace llvm::sys;
172 for (MappingsTy::iterator
173 I = FromToMappings.begin(),
E = FromToMappings.end();
I !=
E; ++
I) {
175 assert(std::holds_alternative<llvm::MemoryBuffer *>(
I->second));
176 if (!fs::exists(origFE.
getName()))
177 return report(StringRef(
"File does not exist: ") + origFE.
getName(),
181 llvm::raw_fd_ostream Out(origFE.
getName(), EC, llvm::sys::fs::OF_None);
183 return report(EC.message(),
Diag);
185 llvm::MemoryBuffer *mem = std::get<llvm::MemoryBuffer *>(
I->second);
186 Out.write(mem->getBufferStart(), mem->getBufferSize());
195 llvm::function_ref<
void(StringRef, StringRef)> CaptureFile,
196 llvm::function_ref<
void(StringRef,
const llvm::MemoryBufferRef &)>
197 CaptureBuffer)
const {
198 for (
auto &Mapping : FromToMappings) {
199 if (
const auto *FE = std::get_if<FileEntryRef>(&Mapping.second)) {
200 CaptureFile(Mapping.first.getName(), FE->getName());
204 Mapping.first.getName(),
205 std::get<llvm::MemoryBuffer *>(Mapping.second)->getMemBufferRef());
210 for (MappingsTy::const_iterator
211 I = FromToMappings.begin(),
E = FromToMappings.end();
I !=
E; ++
I) {
212 if (
const auto *FE = std::get_if<FileEntryRef>(&
I->second)) {
215 llvm::MemoryBuffer *mem = std::get<llvm::MemoryBuffer *>(
I->second);
224 std::unique_ptr<llvm::MemoryBuffer> memBuf) {
231 std::unique_ptr<llvm::MemoryBuffer> MemBuf) {
232 auto [It, New] = FromToMappings.insert({
File,
nullptr});
234 resetTarget(It->second);
235 It->second = MemBuf.release();
239 auto [It, New] = FromToMappings.insert({
File,
nullptr});
241 resetTarget(It->second);
242 It->second = NewFile;
243 ToFromMappings.insert({NewFile,
File});
252 auto I = ToFromMappings.find(*
File);
253 if (
I != ToFromMappings.end()) {
255 assert(FromToMappings.contains(*
File) &&
"Original file not in mappings!");
260void FileRemapper::resetTarget(
Target &targ) {
261 if (std::holds_alternative<llvm::MemoryBuffer *>(targ)) {
262 llvm::MemoryBuffer *oldmem = std::get<llvm::MemoryBuffer *>(targ);
266 ToFromMappings.erase(toFE);
Defines the Diagnostic-related interfaces.
Defines the clang::FileManager interface and associated types.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
llvm::MachO::Target Target
Concrete class used by the front-end to report problems and issues.
A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...
time_t getModificationTime() const
StringRef getName() const
The name of this FileEntry.
Implements support for file system lookup, file system caching, and directory search management.
Keeps track of options that affect how file operations are performed.
PreprocessorOptions - This class is used for passing the various options used in preprocessor initial...
bool RetainRemappedFileBuffers
Whether the compiler instance should retain (i.e., not free) the buffers associated with remapped fil...
void addRemappedFile(StringRef From, StringRef To)
bool initFromFile(StringRef filePath, DiagnosticsEngine &Diag, bool ignoreIfFilesChanged)
void forEachMapping(llvm::function_ref< void(StringRef, StringRef)> CaptureFile, llvm::function_ref< void(StringRef, const llvm::MemoryBufferRef &)> CaptureBuffer) const
Iterate through all the mappings.
bool flushToDisk(StringRef outputDir, DiagnosticsEngine &Diag)
bool flushToFile(StringRef outputPath, DiagnosticsEngine &Diag)
void remap(StringRef filePath, std::unique_ptr< llvm::MemoryBuffer > memBuf)
void clear(StringRef outputDir=StringRef())
void applyMappings(PreprocessorOptions &PPOpts) const
bool initFromDisk(StringRef outputDir, DiagnosticsEngine &Diag, bool ignoreIfFilesChanged)
bool overwriteOriginal(DiagnosticsEngine &Diag, StringRef outputDir=StringRef())
The JSON file list parser is used to communicate input to InstallAPI.