CernVM-FS  2.12.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
cmd_diff.cc
Go to the documentation of this file.
1 
5 #include "cvmfs_config.h"
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  {}
38  virtual ~DiffReporter() {}
39 
40 
41  virtual void OnInit(const history::History::Tag &from_tag,
42  const history::History::Tag &to_tag)
43  {
44  if (!show_header_)
45  return;
46 
47  if (machine_readable_) {
49  "# line descriptor: A - add, R - remove, M - modify, "
50  "S - statistics; modify flags: S - size, M - mode, T - timestamp, "
51  "C - content, L - symlink target; entry types: F - regular file, "
52  "S - symbolic link, D - directory, N - nested catalog");
53  } else {
55  "DELTA: %s/r%" PRIu64 " (%s) --> %s/r%" PRIu64 " (%s)",
56  from_tag.name.c_str(), from_tag.revision,
57  StringifyTime(from_tag.timestamp, true).c_str(),
58  to_tag.name.c_str(), to_tag.revision,
59  StringifyTime(to_tag.timestamp, true).c_str());
60  }
61  }
62 
63 
64  virtual void OnStats(const catalog::DeltaCounters &delta) {
65  std::string operation = machine_readable_ ? "S " : "d(";
66  std::string type_file = machine_readable_ ? "F" : "# regular files):";
67  std::string type_symlink = machine_readable_ ? "S" : "# symlinks):";
68  std::string type_directory = machine_readable_ ? "D" : "# directories):";
69  std::string type_catalog = machine_readable_ ? "N" : "# catalogs):";
70  int64_t diff_file = delta.self.regular_files + delta.subtree.regular_files;
71  int64_t diff_symlink = delta.self.symlinks + delta.subtree.symlinks;
72  int64_t diff_catalog = delta.self.nested_catalogs +
73  delta.subtree.nested_catalogs;
74  // Nested catalogs make internally two directory entries
75  int64_t diff_directory = delta.self.directories +
76  delta.subtree.directories - diff_catalog;
77  LogCvmfs(kLogCvmfs, kLogStdout, "%s%s %" PRId64, operation.c_str(),
78  type_file.c_str(), diff_file);
79  LogCvmfs(kLogCvmfs, kLogStdout, "%s%s %" PRId64, operation.c_str(),
80  type_symlink.c_str(), diff_symlink);
81  LogCvmfs(kLogCvmfs, kLogStdout, "%s%s %" PRId64, operation.c_str(),
82  type_directory.c_str(), diff_directory);
83  LogCvmfs(kLogCvmfs, kLogStdout, "%s%s %" PRId64, operation.c_str(),
84  type_catalog.c_str(), diff_catalog);
85  }
86 
87 
88  virtual void OnAdd(const std::string &path,
89  const catalog::DirectoryEntry &entry)
90  {
91  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(),
103  PrintEntryType(entry).c_str(), entry.size());
104  }
105  }
106 
107 
108  virtual void OnRemove(const std::string &path,
109  const catalog::DirectoryEntry &entry)
110  {
111  std::string operation = machine_readable_ ? "R" : "remove";
112  if (machine_readable_) {
114  operation.c_str(), PrintEntryType(entry).c_str(), path.c_str());
115  if (!entry.IsDirectory()) {
116  LogCvmfs(kLogCvmfs, kLogStdout, " -%" PRIu64, entry.size());
117  } else {
119  }
120  } else {
121  LogCvmfs(kLogCvmfs, kLogStdout, "%s %s %s -%" PRIu64 " bytes",
122  path.c_str(), operation.c_str(),
123  PrintEntryType(entry).c_str(), entry.size());
124  }
125  }
126 
127 
128  virtual void OnModify(const std::string &path,
129  const catalog::DirectoryEntry &entry_from,
130  const catalog::DirectoryEntry &entry_to)
131  {
133  entry_from.CompareTo(entry_to);
134  if (ignore_timediff_) {
135  diff = diff & ~catalog::DirectoryEntryBase::Difference::kMtime;
136  if (diff == 0)
137  return;
138  }
139  if (entry_from.IsDirectory() || entry_to.IsDirectory()) {
140  diff = diff & ~catalog::DirectoryEntryBase::Difference::kSize;
141  if (diff == 0)
142  return;
143  }
144 
145  std::string type_from = PrintEntryType(entry_from);
146  std::string type_to = PrintEntryType(entry_to);
147  std::string type = type_from;
148  if (type_from != type_to) {
149  type += machine_readable_ ? type_to : ("->" + type_to);
150  }
151 
152  std::string operation = machine_readable_ ? "M" : "modify";
153  if (machine_readable_) {
154  LogCvmfs(kLogCvmfs, kLogStdout, "%s%s %s %s", operation.c_str(),
155  PrintDifferences(diff).c_str(), type.c_str(), path.c_str());
156  } else {
157  LogCvmfs(kLogCvmfs, kLogStdout, "%s %s %s%s", path.c_str(),
158  operation.c_str(), type.c_str(), PrintDifferences(diff).c_str());
159  }
160  }
161 
162  private:
164  std::vector<std::string> result_list;
166  result_list.push_back(machine_readable_ ? "N" : "name");
168  result_list.push_back(machine_readable_ ? "I" : "link-count");
170  result_list.push_back(machine_readable_ ? "S" : "size");
172  result_list.push_back(machine_readable_ ? "M" : "mode");
174  result_list.push_back(machine_readable_ ? "T" : "timestamp");
176  result_list.push_back(machine_readable_ ? "L" : "symlink-target");
178  result_list.push_back(machine_readable_ ? "C" : "content");
180  result_list.push_back(machine_readable_ ? "G" : "hardlink-group");
181  if (diff &
183  {
184  result_list.push_back(machine_readable_ ? "N" : "nested-catalog");
185  }
187  result_list.push_back(machine_readable_ ? "P" : "chunked-file");
189  result_list.push_back(machine_readable_ ? "X" : "xattrs");
191  result_list.push_back(machine_readable_ ? "E" : "external-file");
193  result_list.push_back(machine_readable_ ? "B" : "bind-mountpoint");
195  result_list.push_back(machine_readable_ ? "H" : "hidden");
197  result_list.push_back(machine_readable_ ? "D" : "direct-io");
198 
199  return machine_readable_ ? ("[" + JoinStrings(result_list, "") + "]")
200  : (" [" + JoinStrings(result_list, ", ") + "]");
201  }
202 
203  std::string PrintEntryType(const catalog::DirectoryEntry &entry) {
204  if (entry.IsRegular()) return machine_readable_ ? "F" : "file";
205  else if (entry.IsLink()) return machine_readable_ ? "S" : "symlink";
206  else if (entry.IsDirectory()) return machine_readable_ ? "D" : "directory";
207  else
208  return machine_readable_ ? "U" : "unknown";
209  }
210 
214 }; // class DiffReporter
215 
216 } // anonymous namespace
217 
218 
219 namespace publish {
220 
221 int CmdDiff::Main(const Options &options) {
222  SettingsBuilder builder;
223 
224  if (options.Has("worktree")) {
226  options.plain_args().empty() ? "" : options.plain_args()[0].value_str));
227  settings->SetIsSilent(true);
228  settings->GetTransaction()->SetDryRun(true);
229  settings->GetTransaction()->SetPrintChangeset(true);
230  Publisher publisher(*settings);
231  publisher.Sync();
232  return 0;
233  }
234 
236  options.plain_args().empty() ? "" : options.plain_args()[0].value_str);
237 
238  std::string from = options.GetStringDefault("from", "trunk-previous");
239  std::string to = options.GetStringDefault("to", "trunk");
240 
241  if (options.Has("keychain")) {
242  settings.GetKeychain()->SetKeychainDir(options.GetString("keychain"));
243  }
244  Repository repository(settings);
245 
246  DiffReporter diff_reporter(options.Has("header"),
247  options.Has("machine-readable"),
248  options.Has("ignore-timediff"));
249  repository.Diff(from, to, &diff_reporter);
250 
251  return 0;
252 }
253 
254 } // namespace publish
SettingsKeychain * GetKeychain()
Definition: settings.h:377
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:126
static const unsigned int kHiddenFlag
SettingsPublisher * CreateSettingsPublisher(const std::string &ident, bool needs_managed=false)
Definition: settings.cc:594
virtual void OnModify(const std::string &path, const catalog::DirectoryEntry &entry_from, const catalog::DirectoryEntry &entry_to)
Definition: cmd_diff.cc:128
virtual void OnAdd(const std::string &path, const catalog::DirectoryEntry &entry)
Definition: cmd_diff.cc:88
bool IsDirectory() const
static const unsigned int kChecksum
void SetKeychainDir(const std::string &keychain_dir)
Definition: settings.cc:235
bool Has(const std::string &key) const
Definition: command.h:114
std::string name
Definition: history.h:88
std::string GetString(const std::string &key) const
Definition: command.h:123
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:325
const SettingsPublisher & settings() const
Definition: repository.h:317
static const unsigned int kDirectIoFlag
std::string PrintDifferences(catalog::DirectoryEntryBase::Differences diff)
Definition: cmd_diff.cc:163
const std::vector< Argument > & plain_args() const
Definition: command.h:137
virtual void OnInit(const history::History::Tag &from_tag, const history::History::Tag &to_tag)
Definition: cmd_diff.cc:41
string StringifyTime(const time_t seconds, const bool utc)
Definition: string.cc:105
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:438
virtual void OnStats(const catalog::DeltaCounters &delta)
Definition: cmd_diff.cc:64
static const unsigned int kNestedCatalogTransitionFlags
static const unsigned int kLinkcount
static const unsigned int kMtime
virtual int Main(const Options &options)
Definition: cmd_diff.cc:221
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:594
uint64_t revision
Definition: history.h:91
static const unsigned int kBindMountpointFlag
std::string PrintEntryType(const catalog::DirectoryEntry &entry)
Definition: cmd_diff.cc:203
virtual void OnRemove(const std::string &path, const catalog::DirectoryEntry &entry)
Definition: cmd_diff.cc:108
unsigned int Differences
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)
Definition: logging.cc:528