FileUpdate.cpp revision 3ff9563c3e391954b2e224afcf8b2b0fcc3888aa
105084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar//===- FileUpdate.cpp - Conditionally update a file -----------------------===//
205084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar//
305084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar//                     The LLVM Compiler Infrastructure
405084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar//
505084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar// This file is distributed under the University of Illinois Open Source
605084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar// License. See LICENSE.TXT for details.
705084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar//
805084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar//===----------------------------------------------------------------------===//
905084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar//
1005084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar// FileUpdate is a utility for conditionally updating a file from its input
1105084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar// based on whether the input differs from the output. It is used to avoid
1205084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar// unnecessary modifications in a build system.
1305084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar//
1405084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar//===----------------------------------------------------------------------===//
1505084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar
1605084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar#include "llvm/Support/CommandLine.h"
1705084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar#include "llvm/Support/MemoryBuffer.h"
183ff9563c3e391954b2e224afcf8b2b0fcc3888aaMichael J. Spencer#include "llvm/ADT/OwningPtr.h"
1905084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar#include "llvm/Support/PrettyStackTrace.h"
20e4f1a9b8a272ff7452759019ee7774e9dbdf1568Dan Gohman#include "llvm/Support/ToolOutputFile.h"
215fae2f1dbb8345e6fc3232f4732acaf9b64edd90Michael J. Spencer#include "llvm/Support/Signals.h"
227a8aab3997e48aabe819de43b369d441ec4f533aMichael J. Spencer#include "llvm/Support/system_error.h"
2305084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbarusing namespace llvm;
2405084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar
2505084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbarstatic cl::opt<bool>
2605084716c13b4ea79ea29528dcb3c3f8a5271638Daniel DunbarQuiet("quiet", cl::desc("Don't print unnecessary status information"),
2705084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar      cl::init(false));
2805084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar
2905084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbarstatic cl::opt<std::string>
3005084716c13b4ea79ea29528dcb3c3f8a5271638Daniel DunbarInputFilename("input-file", cl::desc("Input file (defaults to stdin)"),
3105084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar              cl::init("-"), cl::value_desc("filename"));
3205084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar
3305084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbarstatic cl::opt<std::string>
3405084716c13b4ea79ea29528dcb3c3f8a5271638Daniel DunbarOutputFilename(cl::Positional, cl::desc("<output-file>"), cl::Required);
3505084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar
3605084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbarint main(int argc, char **argv) {
3705084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar  sys::PrintStackTraceOnErrorSignal();
3805084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar  PrettyStackTraceProgram X(argc, argv);
3905084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar  cl::ParseCommandLineOptions(argc, argv);
4005084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar
41e7b67d0e94df497791207618194e1db545ac3721Dan Gohman  if (OutputFilename == "-") {
42e7b67d0e94df497791207618194e1db545ac3721Dan Gohman    errs() << argv[0] << ": error: Can't update standard output\n";
43e7b67d0e94df497791207618194e1db545ac3721Dan Gohman    return 1;
44e7b67d0e94df497791207618194e1db545ac3721Dan Gohman  }
45e7b67d0e94df497791207618194e1db545ac3721Dan Gohman
4605084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar  // Get the input data.
473ff9563c3e391954b2e224afcf8b2b0fcc3888aaMichael J. Spencer  OwningPtr<MemoryBuffer> In;
483ff9563c3e391954b2e224afcf8b2b0fcc3888aaMichael J. Spencer  if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), In)) {
4905084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar    errs() << argv[0] << ": error: Unable to get input '"
507a8aab3997e48aabe819de43b369d441ec4f533aMichael J. Spencer           << InputFilename << "': " << ec.message() << '\n';
5105084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar    return 1;
5205084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar  }
5305084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar
5405084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar  // Get the output data.
553ff9563c3e391954b2e224afcf8b2b0fcc3888aaMichael J. Spencer  OwningPtr<MemoryBuffer> Out;
563ff9563c3e391954b2e224afcf8b2b0fcc3888aaMichael J. Spencer  MemoryBuffer::getFile(OutputFilename.c_str(), Out);
5705084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar
5805084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar  // If the output exists and the contents match, we are done.
5905084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar  if (Out && In->getBufferSize() == Out->getBufferSize() &&
6005084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar      memcmp(In->getBufferStart(), Out->getBufferStart(),
6105084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar             Out->getBufferSize()) == 0) {
6205084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar    if (!Quiet)
637a4575e26e58da743cf6c921aadd0d5499717a68Dan Gohman      errs() << argv[0] << ": Not updating '" << OutputFilename
6405084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar             << "', contents match input.\n";
6505084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar    return 0;
6605084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar  }
6705084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar
6805084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar  // Otherwise, overwrite the output.
6905084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar  if (!Quiet)
707a4575e26e58da743cf6c921aadd0d5499717a68Dan Gohman    errs() << argv[0] << ": Updating '" << OutputFilename
7105084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar           << "', contents changed.\n";
727a8aab3997e48aabe819de43b369d441ec4f533aMichael J. Spencer  std::string ErrorStr;
737a4575e26e58da743cf6c921aadd0d5499717a68Dan Gohman  tool_output_file OutStream(OutputFilename.c_str(), ErrorStr,
747a4575e26e58da743cf6c921aadd0d5499717a68Dan Gohman                             raw_fd_ostream::F_Binary);
7505084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar  if (!ErrorStr.empty()) {
7605084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar    errs() << argv[0] << ": Unable to write output '"
7705084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar           << OutputFilename << "': " << ErrorStr << '\n';
7805084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar    return 1;
7905084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar  }
8005084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar
81d4c454317a38d65957edebe62bfc69fc8d9885e8Dan Gohman  OutStream.os().write(In->getBufferStart(), In->getBufferSize());
8205084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar
837a4575e26e58da743cf6c921aadd0d5499717a68Dan Gohman  // Declare success.
847a4575e26e58da743cf6c921aadd0d5499717a68Dan Gohman  OutStream.keep();
8505084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar
8605084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar  return 0;
8705084716c13b4ea79ea29528dcb3c3f8a5271638Daniel Dunbar}
88