CernVM-FS  2.13.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
cmd_diff.cc
Go to the documentation of this file.
1 
6 #include "cmd_diff.h"
7 
8 #ifndef __STDC_FORMAT_MACROS
9 #define __STDC_FORMAT_MACROS
10 #endif
11 
12 #include <inttypes.h>
13 
14 #include <cassert>
15 #include <string>
16 #include <vector>
17 
18 #include "catalog_counters.h"
19 #include "directory_entry.h"
20 #include "history.h"
21 #include "publish/except.h"
22 #include "publish/repository.h"
23 #include "publish/settings.h"
24 #include "sanitizer.h"
25 #include "util/logging.h"
26 #include "util/pointer.h"
27 #include "util/string.h"
28 
29 namespace {
30 
31 class DiffReporter : public publish::DiffListener {
32  public:
33  DiffReporter(bool show_header, bool machine_readable, bool ignore_timediff)
34  : show_header_(show_header)
35  , machine_readable_(machine_readable)
36  , ignore_timediff_(ignore_timediff) { }
37  virtual ~DiffReporter() { }
38 
39 
40  virtual void OnInit(const history::History::Tag &from_tag,
41  const history::History::Tag &to_tag) {
42  if (!show_header_)
43  return;
44 
45  if (machine_readable_) {
46  LogCvmfs(
48  "# line descriptor: A - add, R - remove, M - modify, "
49  "S - statistics; modify flags: S - size, M - mode, T - timestamp, "
50  "C - content, L - symlink target; entry types: F - regular file, "
51  "S - symbolic link, D - directory, N - nested catalog");
52  } else {
54  "DELTA: %s/r%" PRIu64 " (%s) --> %s/r%" PRIu64 " (%s)",
55  from_tag.name.c_str(), from_tag.revision,
56  StringifyTime(from_tag.timestamp, true).c_str(),
57  to_tag.name.c_str(), to_tag.revision,
58  StringifyTime(to_tag.timestamp, true).c_str());
59  }
60  }
61 
62 
63  virtual void OnStats(const catalog::DeltaCounters &delta) {
64  const std::string operation = machine_readable_ ? "S " : "d(";
65  const std::string type_file = machine_readable_ ? "F" : "# regular files):";
66  const std::string type_symlink = machine_readable_ ? "S" : "# symlinks):";
67  const std::string type_directory =
68  machine_readable_ ? "D" : "# directories):";
69  const std::string type_catalog = machine_readable_ ? "N" : "# catalogs):";
70  const int64_t diff_file =
71  delta.self.regular_files + delta.subtree.regular_files;
72  const int64_t diff_symlink = delta.self.symlinks + delta.subtree.symlinks;
73  const int64_t diff_catalog =
74  delta.self.nested_catalogs + delta.subtree.nested_catalogs;
75  // Nested catalogs make internally two directory entries
76  const int64_t diff_directory =
77  delta.self.directories + delta.subtree.directories - diff_catalog;
78  LogCvmfs(kLogCvmfs, kLogStdout, "%s%s %" PRId64, operation.c_str(),
79  type_file.c_str(), diff_file);
80  LogCvmfs(kLogCvmfs, kLogStdout, "%s%s %" PRId64, operation.c_str(),
81  type_symlink.c_str(), diff_symlink);
82  LogCvmfs(kLogCvmfs, kLogStdout, "%s%s %" PRId64, operation.c_str(),
83  type_directory.c_str(), diff_directory);
84  LogCvmfs(kLogCvmfs, kLogStdout, "%s%s %" PRId64, operation.c_str(),
85  type_catalog.c_str(), diff_catalog);
86  }
87 
88 
89  virtual void OnAdd(const std::string &path,
90  const catalog::DirectoryEntry &entry) {
91  const std::string operation = machine_readable_ ? "A" : "add";
92  if (machine_readable_) {
94  operation.c_str(), PrintEntryType(entry).c_str(), path.c_str());
95  if (!entry.IsDirectory()) {
96  LogCvmfs(kLogCvmfs, kLogStdout, " +%" PRIu64, entry.size());
97  } else {
99  }
100  } else {
101  LogCvmfs(kLogCvmfs, kLogStdout, "%s %s %s +%" PRIu64 " bytes",
102  path.c_str(), operation.c_str(), PrintEntryType(entry).c_str(),
103  entry.size());
104  }
105  }
106 
107 
108  virtual void OnRemove(const std::string &path,
109  const catalog::DirectoryEntry &entry) {
110  const std::string operation = machine_readable_ ? "R" : "remove";
111  if (machine_readable_) {
113  operation.c_str(), PrintEntryType(entry).c_str(), path.c_str());
114  if (!entry.IsDirectory()) {
115  LogCvmfs(kLogCvmfs, kLogStdout, " -%" PRIu64, entry.size());
116  } else {
118  }
119  } else {
120  LogCvmfs(kLogCvmfs, kLogStdout, "%s %s %s -%" PRIu64 " bytes",
121  path.c_str(), operation.c_str(), PrintEntryType(entry).c_str(),
122  entry.size());
123  }
124  }
125 
126 
127  virtual void OnModify(const std::string &path,
128  const catalog::DirectoryEntry &entry_from,
129  const catalog::DirectoryEntry &entry_to) {
131  entry_to);
132  if (ignore_timediff_) {
133  diff = diff & ~catalog::DirectoryEntryBase::Difference::kMtime;
134  if (diff == 0)
135  return;
136  }
137  if (entry_from.IsDirectory() || entry_to.IsDirectory()) {
138  diff = diff & ~catalog::DirectoryEntryBase::Difference::kSize;
139  if (diff == 0)
140  return;
141  }
142 
143  const std::string type_from = PrintEntryType(entry_from);
144  const std::string type_to = PrintEntryType(entry_to);
145  std::string type = type_from;
146  if (type_from != type_to) {
147  type += machine_readable_ ? type_to : ("->" + type_to);
148  }
149 
150  const std::string operation = machine_readable_ ? "M" : "modify";
151  if (machine_readable_) {
152  LogCvmfs(kLogCvmfs, kLogStdout, "%s%s %s %s", operation.c_str(),
153  PrintDifferences(diff).c_str(), type.c_str(), path.c_str());
154  } else {
155  LogCvmfs(kLogCvmfs, kLogStdout, "%s %s %s%s", path.c_str(),
156  operation.c_str(), type.c_str(), PrintDifferences(diff).c_str());
157  }
158  }
159 
160  private:
162  std::vector<std::string> result_list;
164  result_list.push_back(machine_readable_ ? "N" : "name");
166  result_list.push_back(machine_readable_ ? "I" : "link-count");
168  result_list.push_back(machine_readable_ ? "S" : "size");
170  result_list.push_back(machine_readable_ ? "M" : "mode");
172  result_list.push_back(machine_readable_ ? "T" : "timestamp");
174  result_list.push_back(machine_readable_ ? "L" : "symlink-target");
176  result_list.push_back(machine_readable_ ? "C" : "content");
178  result_list.push_back(machine_readable_ ? "G" : "hardlink-group");
179  if (diff
181  kNestedCatalogTransitionFlags) {
182  result_list.push_back(machine_readable_ ? "N" : "nested-catalog");
183  }
185  result_list.push_back(machine_readable_ ? "P" : "chunked-file");
187  result_list.push_back(machine_readable_ ? "X" : "xattrs");
189  result_list.push_back(machine_readable_ ? "E" : "external-file");
191  result_list.push_back(machine_readable_ ? "B" : "bind-mountpoint");
193  result_list.push_back(machine_readable_ ? "H" : "hidden");
195  result_list.push_back(machine_readable_ ? "D" : "direct-io");
197  result_list.push_back(machine_readable_ ? "U" : "uid");
199  result_list.push_back(machine_readable_ ? "R" : "gid");
200 
201  return machine_readable_ ? ("[" + JoinStrings(result_list, "") + "]")
202  : (" [" + JoinStrings(result_list, ", ") + "]");
203  }
204 
205  std::string PrintEntryType(const catalog::DirectoryEntry &entry) {
206  if (entry.IsRegular())
207  return machine_readable_ ? "F" : "file";
208  else if (entry.IsLink())
209  return machine_readable_ ? "S" : "symlink";
210  else if (entry.IsDirectory())
211  return machine_readable_ ? "D" : "directory";
212  else
213  return machine_readable_ ? "U" : "unknown";
214  }
215 
219 }; // class DiffReporter
220 
221 } // anonymous namespace
222 
223 
224 namespace publish {
225 
226 int CmdDiff::Main(const Options &options) {
227  SettingsBuilder builder;
228 
229  if (options.Has("worktree")) {
231  options.plain_args().empty() ? "" : options.plain_args()[0].value_str));
232  settings->SetIsSilent(true);
233  settings->GetTransaction()->SetDryRun(true);
234  settings->GetTransaction()->SetPrintChangeset(true);
235  Publisher publisher(*settings);
236  publisher.Sync();
237  return 0;
238  }
239 
241  options.plain_args().empty() ? "" : options.plain_args()[0].value_str);
242 
243  const std::string from = options.GetStringDefault("from", "trunk-previous");
244  const std::string to = options.GetStringDefault("to", "trunk");
245 
246  if (options.Has("keychain")) {
247  settings.GetKeychain()->SetKeychainDir(options.GetString("keychain"));
248  }
249  Repository repository(settings);
250 
251  DiffReporter diff_reporter(options.Has("header"),
252  options.Has("machine-readable"),
253  options.Has("ignore-timediff"));
254  repository.Diff(from, to, &diff_reporter);
255 
256  return 0;
257 }
258 
259 } // namespace publish
SettingsKeychain * GetKeychain()
Definition: settings.h:373
static const unsigned int kHardlinkGroup
Differences CompareTo(const DirectoryEntry &other) const
std::string GetStringDefault(const std::string &key, const std::string &default_value) const
Definition: command.h:118
static const unsigned int kHiddenFlag
SettingsPublisher * CreateSettingsPublisher(const std::string &ident, bool needs_managed=false)
Definition: settings.cc:573
virtual void OnModify(const std::string &path, const catalog::DirectoryEntry &entry_from, const catalog::DirectoryEntry &entry_to)
Definition: cmd_diff.cc:127
virtual void OnAdd(const std::string &path, const catalog::DirectoryEntry &entry)
Definition: cmd_diff.cc:89
bool IsDirectory() const
static const unsigned int kChecksum
void SetKeychainDir(const std::string &keychain_dir)
Definition: settings.cc:229
bool Has(const std::string &key) const
Definition: command.h:108
std::string name
Definition: history.h:92
std::string GetString(const std::string &key) const
Definition: command.h:115
DiffReporter(bool show_header, bool machine_readable, bool ignore_timediff)
Definition: cmd_diff.cc:33
uint64_t size() const
string JoinStrings(const vector< string > &strings, const string &joint)
Definition: string.cc:356
static const unsigned int kGid
const SettingsPublisher & settings() const
Definition: repository.h:316
static const unsigned int kDirectIoFlag
std::string PrintDifferences(catalog::DirectoryEntryBase::Differences diff)
Definition: cmd_diff.cc:161
const std::vector< Argument > & plain_args() const
Definition: command.h:128
virtual void OnInit(const history::History::Tag &from_tag, const history::History::Tag &to_tag)
Definition: cmd_diff.cc:40
string StringifyTime(const time_t seconds, const bool utc)
Definition: string.cc:104
Repository(const SettingsRepository &settings, const bool exists=true)
Definition: repository.cc:49
bool IsLink() const
static const unsigned int kExternalFileFlag
bool IsRegular() const
static const unsigned int kHasXattrsFlag
static const unsigned int kName
SettingsRepository CreateSettingsRepository(const std::string &ident)
Definition: settings.cc:416
virtual void OnStats(const catalog::DeltaCounters &delta)
Definition: cmd_diff.cc:63
static const unsigned int kLinkcount
static const unsigned int kMtime
virtual int Main(const Options &options)
Definition: cmd_diff.cc:226
static const unsigned int kChunkedFileFlag
static const unsigned int kSymlink
static const unsigned int kSize
static const unsigned int kMode
Publisher(const SettingsPublisher &settings, const bool exists=true)
Definition: repository.cc:619
uint64_t revision
Definition: history.h:95
static const unsigned int kBindMountpointFlag
std::string PrintEntryType(const catalog::DirectoryEntry &entry)
Definition: cmd_diff.cc:205
virtual void OnRemove(const std::string &path, const catalog::DirectoryEntry &entry)
Definition: cmd_diff.cc:108
unsigned int Differences
static const unsigned int kUid
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)
Definition: logging.cc:545