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.str());
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';
140 fs::make_absolute(newPath);
141 infoOut << newPath <<
'\n';
146 if (fs::createTemporaryFile(
147 path::filename(origFE.
getName()),
148 path::extension(origFE.
getName()).drop_front(), fd, tempPath,
149 llvm::sys::fs::OF_Text))
150 return report(
"Could not create file: " + tempPath.str(),
Diag);
152 llvm::raw_fd_ostream newOut(fd,
true);
153 llvm::MemoryBuffer *mem = I->second.get<llvm::MemoryBuffer *>();
154 newOut.write(mem->getBufferStart(), mem->getBufferSize());
157 auto newE = FileMgr->getOptionalFileRef(tempPath);
159 remap(origFE, *newE);
160 infoOut << newE->getName() <<
'\n';
170 StringRef outputDir) {
171 using namespace llvm::sys;
173 for (MappingsTy::iterator
174 I = FromToMappings.begin(), E = FromToMappings.end(); I != E; ++I) {
176 assert(I->second.is<llvm::MemoryBuffer *>());
177 if (!fs::exists(origFE.
getName()))
178 return report(StringRef(
"File does not exist: ") + origFE.
getName(),
182 llvm::raw_fd_ostream Out(origFE.
getName(), EC, llvm::sys::fs::OF_None);
184 return report(EC.message(),
Diag);
186 llvm::MemoryBuffer *mem = I->second.get<llvm::MemoryBuffer *>();
187 Out.write(mem->getBufferStart(), mem->getBufferSize());
196 llvm::function_ref<
void(StringRef, StringRef)> CaptureFile,
197 llvm::function_ref<
void(StringRef,
const llvm::MemoryBufferRef &)>
198 CaptureBuffer)
const {
199 for (
auto &Mapping : FromToMappings) {
202 CaptureFile(Mapping.first.getName(), FE.getName());
206 Mapping.first.getName(),
207 Mapping.second.get<llvm::MemoryBuffer *>()->getMemBufferRef());
212 for (MappingsTy::const_iterator
213 I = FromToMappings.begin(), E = FromToMappings.end(); I != E; ++I) {
218 llvm::MemoryBuffer *mem = I->second.get<llvm::MemoryBuffer *>();
227 std::unique_ptr<llvm::MemoryBuffer> memBuf) {
234 std::unique_ptr<llvm::MemoryBuffer> memBuf) {
235 Target &targ = FromToMappings[file];
237 targ = memBuf.release();
241 Target &targ = FromToMappings[file];
244 ToFromMappings.insert({newfile, file});
253 auto I = ToFromMappings.find(*
File);
254 if (I != ToFromMappings.end()) {
256 assert(FromToMappings.contains(*
File) &&
"Original file not in mappings!");
261void FileRemapper::resetTarget(
Target &targ) {
265 if (llvm::MemoryBuffer *oldmem = targ.dyn_cast<llvm::MemoryBuffer *>()) {
269 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.
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())