2009-08-03 05:12:16 +00:00
|
|
|
//===- FileUpdate.cpp - Conditionally update a file -----------------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// FileUpdate is a utility for conditionally updating a file from its input
|
|
|
|
// based on whether the input differs from the output. It is used to avoid
|
|
|
|
// unnecessary modifications in a build system.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "llvm/Support/CommandLine.h"
|
|
|
|
#include "llvm/Support/MemoryBuffer.h"
|
|
|
|
#include "llvm/Support/PrettyStackTrace.h"
|
2010-10-07 20:32:40 +00:00
|
|
|
#include "llvm/Support/ToolOutputFile.h"
|
2010-11-29 18:33:08 +00:00
|
|
|
#include "llvm/Support/Signals.h"
|
2010-12-09 17:48:55 +00:00
|
|
|
#include "llvm/Support/system_error.h"
|
2009-08-03 05:12:16 +00:00
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
static cl::opt<bool>
|
|
|
|
Quiet("quiet", cl::desc("Don't print unnecessary status information"),
|
|
|
|
cl::init(false));
|
|
|
|
|
|
|
|
static cl::opt<std::string>
|
|
|
|
InputFilename("input-file", cl::desc("Input file (defaults to stdin)"),
|
|
|
|
cl::init("-"), cl::value_desc("filename"));
|
|
|
|
|
|
|
|
static cl::opt<std::string>
|
|
|
|
OutputFilename(cl::Positional, cl::desc("<output-file>"), cl::Required);
|
|
|
|
|
|
|
|
int main(int argc, char **argv) {
|
|
|
|
sys::PrintStackTraceOnErrorSignal();
|
|
|
|
PrettyStackTraceProgram X(argc, argv);
|
|
|
|
cl::ParseCommandLineOptions(argc, argv);
|
|
|
|
|
2010-08-20 16:56:11 +00:00
|
|
|
if (OutputFilename == "-") {
|
|
|
|
errs() << argv[0] << ": error: Can't update standard output\n";
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2009-08-03 05:12:16 +00:00
|
|
|
// Get the input data.
|
2010-12-09 17:48:55 +00:00
|
|
|
error_code ec;
|
2009-08-03 05:12:16 +00:00
|
|
|
MemoryBuffer *In =
|
2010-12-09 17:48:55 +00:00
|
|
|
MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), ec);
|
2009-08-03 05:12:16 +00:00
|
|
|
if (In == 0) {
|
|
|
|
errs() << argv[0] << ": error: Unable to get input '"
|
2010-12-09 17:48:55 +00:00
|
|
|
<< InputFilename << "': " << ec.message() << '\n';
|
2009-08-03 05:12:16 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the output data.
|
2010-12-09 17:48:55 +00:00
|
|
|
MemoryBuffer *Out = MemoryBuffer::getFile(OutputFilename.c_str(), ec);
|
2009-08-03 05:12:16 +00:00
|
|
|
|
|
|
|
// If the output exists and the contents match, we are done.
|
|
|
|
if (Out && In->getBufferSize() == Out->getBufferSize() &&
|
|
|
|
memcmp(In->getBufferStart(), Out->getBufferStart(),
|
|
|
|
Out->getBufferSize()) == 0) {
|
|
|
|
if (!Quiet)
|
2010-08-20 16:54:27 +00:00
|
|
|
errs() << argv[0] << ": Not updating '" << OutputFilename
|
2009-08-03 05:12:16 +00:00
|
|
|
<< "', contents match input.\n";
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
delete Out;
|
|
|
|
|
|
|
|
// Otherwise, overwrite the output.
|
|
|
|
if (!Quiet)
|
2010-08-20 16:54:27 +00:00
|
|
|
errs() << argv[0] << ": Updating '" << OutputFilename
|
2009-08-03 05:12:16 +00:00
|
|
|
<< "', contents changed.\n";
|
2010-12-09 17:48:55 +00:00
|
|
|
std::string ErrorStr;
|
2010-08-20 16:54:27 +00:00
|
|
|
tool_output_file OutStream(OutputFilename.c_str(), ErrorStr,
|
|
|
|
raw_fd_ostream::F_Binary);
|
2009-08-03 05:12:16 +00:00
|
|
|
if (!ErrorStr.empty()) {
|
|
|
|
errs() << argv[0] << ": Unable to write output '"
|
|
|
|
<< OutputFilename << "': " << ErrorStr << '\n';
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2010-09-01 14:20:41 +00:00
|
|
|
OutStream.os().write(In->getBufferStart(), In->getBufferSize());
|
2009-08-03 05:12:16 +00:00
|
|
|
|
2010-08-20 16:54:27 +00:00
|
|
|
// Declare success.
|
|
|
|
OutStream.keep();
|
2009-08-03 05:12:16 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|