CernVM-FS  2.10.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 "logging.h"
22 #include "publish/except.h"
23 #include "publish/repository.h"
24 #include "publish/settings.h"
25 #include "sanitizer.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_) {
92  LogCvmfs(kLogCvmfs, kLogStdout, "%s %s %s +%" PRIu64, operation.c_str(),
93  PrintEntryType(entry).c_str(), path.c_str(), entry.size());
94  } else {
95  LogCvmfs(kLogCvmfs, kLogStdout, "%s %s %s +%" PRIu64 " bytes",
96  path.c_str(), operation.c_str(),
97  PrintEntryType(entry).c_str(), entry.size());
98  }
99  }
100 
101 
102  virtual void OnRemove(const std::string &path,
103  const catalog::DirectoryEntry &entry)
104  {
105  std::string operation = machine_readable_ ? "R" : "remove";
106  if (machine_readable_) {
107  LogCvmfs(kLogCvmfs, kLogStdout, "%s %s %s -%" PRIu64, operation.c_str(),
108  PrintEntryType(entry).c_str(), path.c_str(), entry.size());
109  } else {
110  LogCvmfs(kLogCvmfs, kLogStdout, "%s %s %s -%" PRIu64 " bytes",
111  path.c_str(), operation.c_str(),
112  PrintEntryType(entry).c_str(), entry.size());
113  }
114  }
115 
116 
117  virtual void OnModify(const std::string &path,
118  const catalog::DirectoryEntry &entry_from,
119  const catalog::DirectoryEntry &entry_to)
120  {
122  entry_from.CompareTo(entry_to);
123  if (ignore_timediff_) {
124  diff = diff & ~catalog::DirectoryEntryBase::Difference::kMtime;
125  if (diff == 0)
126  return;
127  }
128 
129  std::string type_from = PrintEntryType(entry_from);
130  std::string type_to = PrintEntryType(entry_to);
131  std::string type = type_from;
132  if (type_from != type_to) {
133  type += machine_readable_ ? type_to : ("->" + type_to);
134  }
135 
136  std::string operation = machine_readable_ ? "M" : "modify";
137  if (machine_readable_) {
138  LogCvmfs(kLogCvmfs, kLogStdout, "%s%s %s %s", operation.c_str(),
139  PrintDifferences(diff).c_str(), type.c_str(), path.c_str());
140  } else {
141  LogCvmfs(kLogCvmfs, kLogStdout, "%s %s %s%s", path.c_str(),
142  operation.c_str(), type.c_str(), PrintDifferences(diff).c_str());
143  }
144  }
145 
146  private:
148  std::vector<std::string> result_list;
150  result_list.push_back(machine_readable_ ? "N" : "name");
152  result_list.push_back(machine_readable_ ? "I" : "link-count");
154  result_list.push_back(machine_readable_ ? "S" : "size");
156  result_list.push_back(machine_readable_ ? "M" : "mode");
158  result_list.push_back(machine_readable_ ? "T" : "timestamp");
160  result_list.push_back(machine_readable_ ? "L" : "symlink-target");
162  result_list.push_back(machine_readable_ ? "C" : "content");
164  result_list.push_back(machine_readable_ ? "G" : "hardlink-group");
165  if (diff &
167  {
168  result_list.push_back(machine_readable_ ? "N" : "nested-catalog");
169  }
171  result_list.push_back(machine_readable_ ? "P" : "chunked-file");
173  result_list.push_back(machine_readable_ ? "X" : "xattrs");
175  result_list.push_back(machine_readable_ ? "E" : "external-file");
177  result_list.push_back(machine_readable_ ? "B" : "bind-mountpoint");
179  result_list.push_back(machine_readable_ ? "H" : "hidden");
181  result_list.push_back(machine_readable_ ? "D" : "direct-io");
182 
183  return machine_readable_ ? ("[" + JoinStrings(result_list, "") + "]")
184  : (" [" + JoinStrings(result_list, ", ") + "]");
185  }
186 
187  std::string PrintEntryType(const catalog::DirectoryEntry &entry) {
188  if (entry.IsRegular()) return machine_readable_ ? "F" : "file";
189  else if (entry.IsLink()) return machine_readable_ ? "S" : "symlink";
190  else if (entry.IsDirectory()) return machine_readable_ ? "D" : "directory";
191  else
192  return machine_readable_ ? "U" : "unknown";
193  }
194 
198 }; // class DiffReporter
199 
200 } // anonymous namespace
201 
202 
203 namespace publish {
204 
205 int CmdDiff::Main(const Options &options) {
206  SettingsBuilder builder;
207 
208  if (options.Has("worktree")) {
210  options.plain_args().empty() ? "" : options.plain_args()[0].value_str));
211  settings->SetIsSilent(true);
212  settings->GetTransaction()->SetDryRun(true);
213  settings->GetTransaction()->SetPrintChangeset(true);
214  Publisher publisher(*settings);
215  publisher.Sync();
216  return 0;
217  }
218 
220  options.plain_args().empty() ? "" : options.plain_args()[0].value_str);
221 
222  std::string from = options.GetStringDefault("from", "trunk-previous");
223  std::string to = options.GetStringDefault("to", "trunk");
224 
225  if (options.Has("keychain")) {
226  settings.GetKeychain()->SetKeychainDir(options.GetString("keychain"));
227  }
228  Repository repository(settings);
229 
230  DiffReporter diff_reporter(options.Has("header"),
231  options.Has("machine-readable"),
232  options.Has("ignore-timediff"));
233  repository.Diff(from, to, &diff_reporter);
234 
235  return 0;
236 }
237 
238 } // namespace publish
SettingsKeychain * GetKeychain()
Definition: settings.h:375
#define LogCvmfs(source, mask,...)
Definition: logging.h:20
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:581
virtual void OnModify(const std::string &path, const catalog::DirectoryEntry &entry_from, const catalog::DirectoryEntry &entry_to)
Definition: cmd_diff.cc:117
virtual void OnAdd(const std::string &path, const catalog::DirectoryEntry &entry)
Definition: cmd_diff.cc:87
bool IsDirectory() const
static const unsigned int kChecksum
Repository(const SettingsRepository &settings)
Definition: repository.cc:63
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:113
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:318
const SettingsPublisher & settings() const
Definition: repository.h:314
static const unsigned int kDirectIoFlag
std::string PrintDifferences(catalog::DirectoryEntryBase::Differences diff)
Definition: cmd_diff.cc:147
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
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:425
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
Publisher(const SettingsPublisher &settings)
Definition: repository.cc:634
virtual int Main(const Options &options)
Definition: cmd_diff.cc:205
static const unsigned int kChunkedFileFlag
static const unsigned int kSymlink
static const unsigned int kSize
static const unsigned int kMode
static const unsigned int kBindMountpointFlag
std::string PrintEntryType(const catalog::DirectoryEntry &entry)
Definition: cmd_diff.cc:187
virtual void OnRemove(const std::string &path, const catalog::DirectoryEntry &entry)
Definition: cmd_diff.cc:102
unsigned int Differences