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  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 + delta.subtree.directories
75  - 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  std::string operation = machine_readable_ ? "A" : "add";
90  if (machine_readable_) {
92  operation.c_str(), PrintEntryType(entry).c_str(), path.c_str());
93  if (!entry.IsDirectory()) {
94  LogCvmfs(kLogCvmfs, kLogStdout, " +%" PRIu64, entry.size());
95  } else {
97  }
98  } else {
99  LogCvmfs(kLogCvmfs, kLogStdout, "%s %s %s +%" PRIu64 " bytes",
100  path.c_str(), operation.c_str(), PrintEntryType(entry).c_str(),
101  entry.size());
102  }
103  }
104 
105 
106  virtual void OnRemove(const std::string &path,
107  const catalog::DirectoryEntry &entry) {
108  std::string operation = machine_readable_ ? "R" : "remove";
109  if (machine_readable_) {
111  operation.c_str(), PrintEntryType(entry).c_str(), path.c_str());
112  if (!entry.IsDirectory()) {
113  LogCvmfs(kLogCvmfs, kLogStdout, " -%" PRIu64, entry.size());
114  } else {
116  }
117  } else {
118  LogCvmfs(kLogCvmfs, kLogStdout, "%s %s %s -%" PRIu64 " bytes",
119  path.c_str(), operation.c_str(), PrintEntryType(entry).c_str(),
120  entry.size());
121  }
122  }
123 
124 
125  virtual void OnModify(const std::string &path,
126  const catalog::DirectoryEntry &entry_from,
127  const catalog::DirectoryEntry &entry_to) {
129  entry_to);
130  if (ignore_timediff_) {
131  diff = diff & ~catalog::DirectoryEntryBase::Difference::kMtime;
132  if (diff == 0)
133  return;
134  }
135  if (entry_from.IsDirectory() || entry_to.IsDirectory()) {
136  diff = diff & ~catalog::DirectoryEntryBase::Difference::kSize;
137  if (diff == 0)
138  return;
139  }
140 
141  std::string type_from = PrintEntryType(entry_from);
142  std::string type_to = PrintEntryType(entry_to);
143  std::string type = type_from;
144  if (type_from != type_to) {
145  type += machine_readable_ ? type_to : ("->" + type_to);
146  }
147 
148  std::string operation = machine_readable_ ? "M" : "modify";
149  if (machine_readable_) {
150  LogCvmfs(kLogCvmfs, kLogStdout, "%s%s %s %s", operation.c_str(),
151  PrintDifferences(diff).c_str(), type.c_str(), path.c_str());
152  } else {
153  LogCvmfs(kLogCvmfs, kLogStdout, "%s %s %s%s", path.c_str(),
154  operation.c_str(), type.c_str(), PrintDifferences(diff).c_str());
155  }
156  }
157 
158  private:
160  std::vector<std::string> result_list;
162  result_list.push_back(machine_readable_ ? "N" : "name");
164  result_list.push_back(machine_readable_ ? "I" : "link-count");
166  result_list.push_back(machine_readable_ ? "S" : "size");
168  result_list.push_back(machine_readable_ ? "M" : "mode");
170  result_list.push_back(machine_readable_ ? "T" : "timestamp");
172  result_list.push_back(machine_readable_ ? "L" : "symlink-target");
174  result_list.push_back(machine_readable_ ? "C" : "content");
176  result_list.push_back(machine_readable_ ? "G" : "hardlink-group");
177  if (diff
179  kNestedCatalogTransitionFlags) {
180  result_list.push_back(machine_readable_ ? "N" : "nested-catalog");
181  }
183  result_list.push_back(machine_readable_ ? "P" : "chunked-file");
185  result_list.push_back(machine_readable_ ? "X" : "xattrs");
187  result_list.push_back(machine_readable_ ? "E" : "external-file");
189  result_list.push_back(machine_readable_ ? "B" : "bind-mountpoint");
191  result_list.push_back(machine_readable_ ? "H" : "hidden");
193  result_list.push_back(machine_readable_ ? "D" : "direct-io");
195  result_list.push_back(machine_readable_ ? "U" : "uid");
197  result_list.push_back(machine_readable_ ? "R" : "gid");
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())
205  return machine_readable_ ? "F" : "file";
206  else if (entry.IsLink())
207  return machine_readable_ ? "S" : "symlink";
208  else if (entry.IsDirectory())
209  return machine_readable_ ? "D" : "directory";
210  else
211  return machine_readable_ ? "U" : "unknown";
212  }
213 
217 }; // class DiffReporter
218 
219 } // anonymous namespace
220 
221 
222 namespace publish {
223 
224 int CmdDiff::Main(const Options &options) {
225  SettingsBuilder builder;
226 
227  if (options.Has("worktree")) {
229  options.plain_args().empty() ? "" : options.plain_args()[0].value_str));
230  settings->SetIsSilent(true);
231  settings->GetTransaction()->SetDryRun(true);
232  settings->GetTransaction()->SetPrintChangeset(true);
233  Publisher publisher(*settings);
234  publisher.Sync();
235  return 0;
236  }
237 
239  options.plain_args().empty() ? "" : options.plain_args()[0].value_str);
240 
241  std::string from = options.GetStringDefault("from", "trunk-previous");
242  std::string to = options.GetStringDefault("to", "trunk");
243 
244  if (options.Has("keychain")) {
245  settings.GetKeychain()->SetKeychainDir(options.GetString("keychain"));
246  }
247  Repository repository(settings);
248 
249  DiffReporter diff_reporter(options.Has("header"),
250  options.Has("machine-readable"),
251  options.Has("ignore-timediff"));
252  repository.Diff(from, to, &diff_reporter);
253 
254  return 0;
255 }
256 
257 } // 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:572
virtual void OnModify(const std::string &path, const catalog::DirectoryEntry &entry_from, const catalog::DirectoryEntry &entry_to)
Definition: cmd_diff.cc:125
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: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:159
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:415
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:224
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:203
virtual void OnRemove(const std::string &path, const catalog::DirectoryEntry &entry)
Definition: cmd_diff.cc:106
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