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 {
54  LogCvmfs(kLogCvmfs, kLogStdout, "DELTA: %s/r%u (%s) --> %s/r%u (%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  std::string operation = machine_readable_ ? "S " : "d(";
65  std::string type_file = machine_readable_ ? "F" : "# regular files):";
66  std::string type_symlink = machine_readable_ ? "S" : "# symlinks):";
67  std::string type_directory = machine_readable_ ? "D" : "# directories):";
68  std::string type_catalog = machine_readable_ ? "N" : "# catalogs):";
69  int64_t diff_file = delta.self.regular_files + delta.subtree.regular_files;
70  int64_t diff_symlink = delta.self.symlinks + delta.subtree.symlinks;
71  int64_t diff_catalog = delta.self.nested_catalogs +
72  delta.subtree.nested_catalogs;
73  // Nested catalogs make internally two directory entries
74  int64_t diff_directory = delta.self.directories +
75  delta.subtree.directories - diff_catalog;
76  LogCvmfs(kLogCvmfs, kLogStdout, "%s%s %" PRId64, operation.c_str(),
77  type_file.c_str(), diff_file);
78  LogCvmfs(kLogCvmfs, kLogStdout, "%s%s %" PRId64, operation.c_str(),
79  type_symlink.c_str(), diff_symlink);
80  LogCvmfs(kLogCvmfs, kLogStdout, "%s%s %" PRId64, operation.c_str(),
81  type_directory.c_str(), diff_directory);
82  LogCvmfs(kLogCvmfs, kLogStdout, "%s%s %" PRId64, operation.c_str(),
83  type_catalog.c_str(), diff_catalog);
84  }
85 
86 
87  virtual void OnAdd(const std::string &path,
88  const catalog::DirectoryEntry &entry)
89  {
90  std::string operation = machine_readable_ ? "A" : "add";
91  if (machine_readable_) {
93  operation.c_str(), PrintEntryType(entry).c_str(), path.c_str());
94  if (!entry.IsDirectory()) {
95  LogCvmfs(kLogCvmfs, kLogStdout, " +%" PRIu64, entry.size());
96  } else {
98  }
99  } else {
100  LogCvmfs(kLogCvmfs, kLogStdout, "%s %s %s +%" PRIu64 " bytes",
101  path.c_str(), operation.c_str(),
102  PrintEntryType(entry).c_str(), entry.size());
103  }
104  }
105 
106 
107  virtual void OnRemove(const std::string &path,
108  const catalog::DirectoryEntry &entry)
109  {
110  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(),
122  PrintEntryType(entry).c_str(), 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)
130  {
132  entry_from.CompareTo(entry_to);
133  if (ignore_timediff_) {
134  diff = diff & ~catalog::DirectoryEntryBase::Difference::kMtime;
135  if (diff == 0)
136  return;
137  }
138  if (entry_from.IsDirectory() || entry_to.IsDirectory()) {
139  diff = diff & ~catalog::DirectoryEntryBase::Difference::kSize;
140  if (diff == 0)
141  return;
142  }
143 
144  std::string type_from = PrintEntryType(entry_from);
145  std::string type_to = PrintEntryType(entry_to);
146  std::string type = type_from;
147  if (type_from != type_to) {
148  type += machine_readable_ ? type_to : ("->" + type_to);
149  }
150 
151  std::string operation = machine_readable_ ? "M" : "modify";
152  if (machine_readable_) {
153  LogCvmfs(kLogCvmfs, kLogStdout, "%s%s %s %s", operation.c_str(),
154  PrintDifferences(diff).c_str(), type.c_str(), path.c_str());
155  } else {
156  LogCvmfs(kLogCvmfs, kLogStdout, "%s %s %s%s", path.c_str(),
157  operation.c_str(), type.c_str(), PrintDifferences(diff).c_str());
158  }
159  }
160 
161  private:
163  std::vector<std::string> result_list;
165  result_list.push_back(machine_readable_ ? "N" : "name");
167  result_list.push_back(machine_readable_ ? "I" : "link-count");
169  result_list.push_back(machine_readable_ ? "S" : "size");
171  result_list.push_back(machine_readable_ ? "M" : "mode");
173  result_list.push_back(machine_readable_ ? "T" : "timestamp");
175  result_list.push_back(machine_readable_ ? "L" : "symlink-target");
177  result_list.push_back(machine_readable_ ? "C" : "content");
179  result_list.push_back(machine_readable_ ? "G" : "hardlink-group");
180  if (diff &
182  {
183  result_list.push_back(machine_readable_ ? "N" : "nested-catalog");
184  }
186  result_list.push_back(machine_readable_ ? "P" : "chunked-file");
188  result_list.push_back(machine_readable_ ? "X" : "xattrs");
190  result_list.push_back(machine_readable_ ? "E" : "external-file");
192  result_list.push_back(machine_readable_ ? "B" : "bind-mountpoint");
194  result_list.push_back(machine_readable_ ? "H" : "hidden");
196  result_list.push_back(machine_readable_ ? "D" : "direct-io");
197 
198  return machine_readable_ ? ("[" + JoinStrings(result_list, "") + "]")
199  : (" [" + JoinStrings(result_list, ", ") + "]");
200  }
201 
202  std::string PrintEntryType(const catalog::DirectoryEntry &entry) {
203  if (entry.IsRegular()) return machine_readable_ ? "F" : "file";
204  else if (entry.IsLink()) return machine_readable_ ? "S" : "symlink";
205  else if (entry.IsDirectory()) return machine_readable_ ? "D" : "directory";
206  else
207  return machine_readable_ ? "U" : "unknown";
208  }
209 
213 }; // class DiffReporter
214 
215 } // anonymous namespace
216 
217 
218 namespace publish {
219 
220 int CmdDiff::Main(const Options &options) {
221  SettingsBuilder builder;
222 
223  if (options.Has("worktree")) {
225  options.plain_args().empty() ? "" : options.plain_args()[0].value_str));
226  settings->SetIsSilent(true);
227  settings->GetTransaction()->SetDryRun(true);
228  settings->GetTransaction()->SetPrintChangeset(true);
229  Publisher publisher(*settings);
230  publisher.Sync();
231  return 0;
232  }
233 
235  options.plain_args().empty() ? "" : options.plain_args()[0].value_str);
236 
237  std::string from = options.GetStringDefault("from", "trunk-previous");
238  std::string to = options.GetStringDefault("to", "trunk");
239 
240  if (options.Has("keychain")) {
241  settings.GetKeychain()->SetKeychainDir(options.GetString("keychain"));
242  }
243  Repository repository(settings);
244 
245  DiffReporter diff_reporter(options.Has("header"),
246  options.Has("machine-readable"),
247  options.Has("ignore-timediff"));
248  repository.Diff(from, to, &diff_reporter);
249 
250  return 0;
251 }
252 
253 } // namespace publish
SettingsKeychain * GetKeychain()
Definition: settings.h:377
#define LogCvmfs(source, mask,...)
Definition: logging.h:25
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:127
virtual void OnAdd(const std::string &path, const catalog::DirectoryEntry &entry)
Definition: cmd_diff.cc:87
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:89
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
unsigned revision
Definition: history.h:92
const SettingsPublisher & settings() const
Definition: repository.h:317
static const unsigned int kDirectIoFlag
std::string PrintDifferences(catalog::DirectoryEntryBase::Differences diff)
Definition: cmd_diff.cc:162
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:63
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:220
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
static const unsigned int kBindMountpointFlag
std::string PrintEntryType(const catalog::DirectoryEntry &entry)
Definition: cmd_diff.cc:202
virtual void OnRemove(const std::string &path, const catalog::DirectoryEntry &entry)
Definition: cmd_diff.cc:107
unsigned int Differences