GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/receiver/catalog_merge_tool_impl.h
Date: 2024-04-28 02:33:07
Exec Total Coverage
Lines: 131 178 73.6%
Branches: 136 345 39.4%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4
5 #ifndef CVMFS_RECEIVER_CATALOG_MERGE_TOOL_IMPL_H_
6 #define CVMFS_RECEIVER_CATALOG_MERGE_TOOL_IMPL_H_
7
8 #include <string>
9
10 #include "catalog.h"
11 #include "crypto/hash.h"
12 #include "lease_path_util.h"
13 #include "manifest.h"
14 #include "options.h"
15 #include "upload.h"
16 #include "util/exception.h"
17 #include "util/logging.h"
18 #include "util/posix.h"
19 #include "util/raii_temp_dir.h"
20
21 43 inline PathString MakeRelative(const PathString& path) {
22 43 std::string rel_path;
23
1/2
✓ Branch 1 taken 43 times.
✗ Branch 2 not taken.
43 std::string abs_path = path.ToString();
24
3/4
✓ Branch 1 taken 43 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 41 times.
✓ Branch 4 taken 2 times.
43 if (abs_path[0] == '/') {
25
1/2
✓ Branch 1 taken 41 times.
✗ Branch 2 not taken.
41 rel_path = abs_path.substr(1);
26 } else {
27
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 rel_path = abs_path;
28 }
29
1/2
✓ Branch 1 taken 43 times.
✗ Branch 2 not taken.
86 return PathString(rel_path);
30 43 }
31
32 3 inline void SplitHardlink(catalog::DirectoryEntry* entry) {
33
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (entry->linkcount() > 1) {
34 LogCvmfs(kLogReceiver, kLogSyslogErr,
35 "CatalogMergeTool - Hardlink found: %s. Hardlinks are not "
36 "supported when publishing through repository gateway and "
37 "will be split.", entry->name().c_str());
38 entry->set_linkcount(1);
39 }
40 3 }
41
42 3 inline void AbortIfHardlinked(const catalog::DirectoryEntry& entry) {
43
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (entry.linkcount() > 1) {
44 PANIC(kLogSyslogErr,
45 "CatalogMergeTool - Removal of file %s with linkcount > 1 is "
46 "not supported. Aborting",
47 entry.name().c_str());
48 }
49 3 }
50
51 namespace receiver {
52
53 template <typename RwCatalogMgr, typename RoCatalogMgr>
54 2 bool CatalogMergeTool<RwCatalogMgr, RoCatalogMgr>::Run(
55 const Params& params, std::string* new_manifest_path, uint64_t *final_rev) {
56
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 UniquePtr<upload::Spooler> spooler;
57
2/4
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
4 perf::StatisticsTemplate stats_tmpl("publish", statistics_);
58
4/8
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
2 counters_ = new perf::FsCounters(stats_tmpl);
59
60
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 UniquePtr<RaiiTempDir> raii_temp_dir(RaiiTempDir::Create(temp_dir_prefix_));
61
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (needs_setup_) {
62
2/4
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
4 upload::SpoolerDefinition definition(
63 2 params.spooler_configuration, params.hash_alg, params.compression_alg,
64 2 params.generate_legacy_bulk_chunks, params.use_file_chunking,
65
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 params.min_chunk_size, params.avg_chunk_size, params.max_chunk_size,
66 "dummy_token", "dummy_key");
67
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 spooler = upload::Spooler::Construct(definition, &stats_tmpl);
68
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 const std::string temp_dir = raii_temp_dir->dir();
69
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
4 output_catalog_mgr_ = new RwCatalogMgr(
70 2 manifest_->catalog_hash(), repo_path_, temp_dir, spooler.weak_ref(),
71 2 download_manager_, params.enforce_limits, params.nested_kcatalog_limit,
72 2 params.root_kcatalog_limit, params.file_mbyte_limit, statistics_,
73
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 params.use_autocatalogs, params.max_weight, params.min_weight);
74
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 output_catalog_mgr_->Init();
75 2 }
76
77
3/6
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
2 bool ret = CatalogDiffTool<RoCatalogMgr>::Run(PathString(""));
78
79
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 ret &= CreateNewManifest(new_manifest_path);
80
81 2 *final_rev = manifest_->revision();
82
83
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 output_catalog_mgr_.Destroy();
84
85 2 return ret;
86 2 }
87
88 template <typename RwCatalogMgr, typename RoCatalogMgr>
89 8 bool CatalogMergeTool<RwCatalogMgr, RoCatalogMgr>::IsIgnoredPath(
90 const PathString& path) {
91
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 const PathString rel_path = MakeRelative(path);
92
93 // Ignore any paths that are not either within the lease path or
94 // above the lease path
95
2/4
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
8 return !(IsSubPath(lease_path_, rel_path) ||
96
0/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
8 IsSubPath(rel_path, lease_path_));
97 8 }
98
99 template <typename RwCatalogMgr, typename RoCatalogMgr>
100 27 bool CatalogMergeTool<RwCatalogMgr, RoCatalogMgr>::IsReportablePath(
101 const PathString& path) {
102
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 const PathString rel_path = MakeRelative(path);
103
104 // Do not report any changes occurring outside the lease path (which
105 // will be due to other concurrent writers)
106
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
54 return IsSubPath(lease_path_, rel_path);
107 27 }
108
109 template <typename RwCatalogMgr, typename RoCatalogMgr>
110 2 void CatalogMergeTool<RwCatalogMgr, RoCatalogMgr>::ReportAddition(
111 const PathString& path, const catalog::DirectoryEntry& entry,
112 const XattrList& xattrs, const FileChunkList& chunks) {
113
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 const PathString rel_path = MakeRelative(path);
114
115
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 const std::string parent_path =
116
3/8
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
6 std::strchr(rel_path.c_str(), '/') ? GetParentPath(rel_path).c_str() : "";
117
118
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
2 if (entry.IsDirectory()) {
119
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 output_catalog_mgr_->AddDirectory(entry, xattrs, parent_path);
120
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (entry.IsNestedCatalogMountpoint()) {
121 output_catalog_mgr_->CreateNestedCatalog(std::string(rel_path.c_str()));
122 }
123 1 perf::Inc(counters_->n_directories_added);
124
2/6
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
1 } else if (entry.IsRegular() || entry.IsLink()) {
125
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 catalog::DirectoryEntry modified_entry = entry;
126
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 SplitHardlink(&modified_entry);
127 1 const catalog::DirectoryEntryBase* base_entry =
128 static_cast<const catalog::DirectoryEntryBase*>(&modified_entry);
129
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (entry.IsChunkedFile()) {
130 assert(!chunks.IsEmpty());
131 output_catalog_mgr_->AddChunkedFile(*base_entry, xattrs, parent_path,
132 chunks);
133 } else {
134
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 output_catalog_mgr_->AddFile(*base_entry, xattrs, parent_path);
135 }
136
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (entry.IsLink()) {
137 perf::Inc(counters_->n_symlinks_added);
138 } else {
139 1 perf::Inc(counters_->n_files_added);
140 }
141
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 perf::Xadd(counters_->sz_added_bytes, static_cast<int64_t>(entry.size()));
142 1 }
143 2 }
144
145 template <typename RwCatalogMgr, typename RoCatalogMgr>
146 3 void CatalogMergeTool<RwCatalogMgr, RoCatalogMgr>::ReportRemoval(
147 const PathString& path, const catalog::DirectoryEntry& entry) {
148
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 const PathString rel_path = MakeRelative(path);
149
150
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
3 if (entry.IsDirectory()) {
151
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (entry.IsNestedCatalogMountpoint()) {
152 output_catalog_mgr_->RemoveNestedCatalog(std::string(rel_path.c_str()),
153 false);
154 }
155
156
2/4
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
1 output_catalog_mgr_->RemoveDirectory(rel_path.c_str());
157 1 perf::Inc(counters_->n_directories_removed);
158
2/6
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
2 } else if (entry.IsRegular() || entry.IsLink()) {
159
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 AbortIfHardlinked(entry);
160
2/4
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
2 output_catalog_mgr_->RemoveFile(rel_path.c_str());
161
162
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (entry.IsLink()) {
163 perf::Inc(counters_->n_symlinks_removed);
164 } else {
165 2 perf::Inc(counters_->n_files_removed);
166 }
167
168
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 perf::Xadd(counters_->sz_removed_bytes, static_cast<int64_t>(entry.size()));
169 }
170 3 }
171
172 template <typename RwCatalogMgr, typename RoCatalogMgr>
173 3 bool CatalogMergeTool<RwCatalogMgr, RoCatalogMgr>::ReportModification(
174 const PathString& path, const catalog::DirectoryEntry& entry1,
175 const catalog::DirectoryEntry& entry2, const XattrList& xattrs,
176 const FileChunkList& chunks) {
177
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 const PathString rel_path = MakeRelative(path);
178
179
1/2
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
6 const std::string parent_path =
180
5/8
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
8 std::strchr(rel_path.c_str(), '/') ? GetParentPath(rel_path).c_str() : "";
181
182
4/6
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
4 if (entry1.IsNestedCatalogMountpoint() &&
183 1 entry2.IsNestedCatalogMountpoint()) {
184 // From nested catalog to nested catalog
185 RoCatalogMgr *new_catalog_mgr =
186 CatalogDiffTool<RoCatalogMgr>::GetNewCatalogMgr();
187 PathString mountpoint;
188 shash::Any new_hash;
189 uint64_t new_size;
190 const bool found = new_catalog_mgr->LookupNested(path, &mountpoint,
191 &new_hash, &new_size);
192 if (!found || !new_size) {
193 PANIC(kLogSyslogErr,
194 "CatalogMergeTool - nested catalog %s not found. Aborting",
195 rel_path.c_str());
196 }
197 output_catalog_mgr_->SwapNestedCatalog(rel_path.ToString(), new_hash,
198 new_size);
199 return false; // skip recursion into nested catalog mountpoints
200
6/6
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 2 times.
3 } else if (entry1.IsDirectory() && entry2.IsDirectory()) {
201 // From directory to directory
202 1 const catalog::DirectoryEntryBase* base_entry =
203 static_cast<const catalog::DirectoryEntryBase*>(&entry2);
204
2/4
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
1 output_catalog_mgr_->TouchDirectory(*base_entry, xattrs, rel_path.c_str());
205
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
2 if (!entry1.IsNestedCatalogMountpoint() &&
206 1 entry2.IsNestedCatalogMountpoint()) {
207 output_catalog_mgr_->CreateNestedCatalog(std::string(rel_path.c_str()));
208
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 } else if (entry1.IsNestedCatalogMountpoint() &&
209 !entry2.IsNestedCatalogMountpoint()) {
210 output_catalog_mgr_->RemoveNestedCatalog(std::string(rel_path.c_str()));
211 }
212 1 perf::Inc(counters_->n_directories_changed);
213
5/8
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
2 } else if ((entry1.IsRegular() || entry1.IsLink()) && entry2.IsDirectory()) {
214 // From file to directory
215 AbortIfHardlinked(entry1);
216 output_catalog_mgr_->RemoveFile(rel_path.c_str());
217 output_catalog_mgr_->AddDirectory(entry2, xattrs, parent_path);
218 if (entry2.IsNestedCatalogMountpoint()) {
219 output_catalog_mgr_->CreateNestedCatalog(std::string(rel_path.c_str()));
220 }
221 if (entry1.IsLink()) {
222 perf::Inc(counters_->n_symlinks_removed);
223 } else {
224 perf::Inc(counters_->n_files_removed);
225 }
226 perf::Xadd(counters_->sz_removed_bytes,
227 static_cast<int64_t>(entry1.size()));
228 perf::Inc(counters_->n_directories_added);
229
230
6/8
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 1 times.
2 } else if (entry1.IsDirectory() && (entry2.IsRegular() || entry2.IsLink())) {
231 // From directory to file
232
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (entry1.IsNestedCatalogMountpoint()) {
233 // we merge the nested catalog with its parent, it will be the recursive
234 // procedure that will take care of deleting all the files.
235
2/4
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
1 output_catalog_mgr_->RemoveNestedCatalog(std::string(rel_path.c_str()),
236 /* merge = */ true);
237 }
238
239
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 catalog::DirectoryEntry modified_entry = entry2;
240
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 SplitHardlink(&modified_entry);
241 1 const catalog::DirectoryEntryBase* base_entry =
242 static_cast<const catalog::DirectoryEntryBase*>(&modified_entry);
243
244
2/4
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
1 output_catalog_mgr_->RemoveDirectory(rel_path.c_str());
245
246
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (entry2.IsChunkedFile()) {
247 assert(!chunks.IsEmpty());
248 output_catalog_mgr_->AddChunkedFile(*base_entry, xattrs, parent_path,
249 chunks);
250 } else {
251
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 output_catalog_mgr_->AddFile(*base_entry, xattrs, parent_path);
252 }
253
254 1 perf::Inc(counters_->n_directories_removed);
255
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (entry2.IsLink()) {
256 1 perf::Inc(counters_->n_symlinks_added);
257 } else {
258 perf::Inc(counters_->n_files_added);
259 }
260
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 perf::Xadd(counters_->sz_added_bytes, static_cast<int64_t>(entry2.size()));
261
262
3/8
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
3 } else if ((entry1.IsRegular() || entry1.IsLink()) &&
263
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 (entry2.IsRegular() || entry2.IsLink())) {
264 // From file to file
265
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 AbortIfHardlinked(entry1);
266
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 catalog::DirectoryEntry modified_entry = entry2;
267
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 SplitHardlink(&modified_entry);
268 1 const catalog::DirectoryEntryBase* base_entry =
269 static_cast<const catalog::DirectoryEntryBase*>(&modified_entry);
270
2/4
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
1 output_catalog_mgr_->RemoveFile(rel_path.c_str());
271
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (entry2.IsChunkedFile()) {
272 assert(!chunks.IsEmpty());
273 output_catalog_mgr_->AddChunkedFile(*base_entry, xattrs, parent_path,
274 chunks);
275 } else {
276
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 output_catalog_mgr_->AddFile(*base_entry, xattrs, parent_path);
277 }
278
279
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
1 if (entry1.IsRegular() && entry2.IsRegular()) {
280 1 perf::Inc(counters_->n_files_changed);
281 } else if (entry1.IsRegular() && entry2.IsLink()) {
282 perf::Inc(counters_->n_files_removed);
283 perf::Inc(counters_->n_symlinks_added);
284 } else if (entry1.IsLink() && entry2.IsRegular()) {
285 perf::Inc(counters_->n_symlinks_removed);
286 perf::Inc(counters_->n_files_added);
287 } else {
288 perf::Inc(counters_->n_symlinks_changed);
289 }
290 1 perf::Xadd(counters_->sz_removed_bytes,
291
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 static_cast<int64_t>(entry1.size()));
292
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 perf::Xadd(counters_->sz_added_bytes, static_cast<int64_t>(entry2.size()));
293 1 }
294 3 return true;
295 3 }
296
297 template <typename RwCatalogMgr, typename RoCatalogMgr>
298 2 bool CatalogMergeTool<RwCatalogMgr, RoCatalogMgr>::CreateNewManifest(
299 std::string* new_manifest_path) {
300
2/4
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
2 if (!output_catalog_mgr_->Commit(false, 0, manifest_)) {
301 LogCvmfs(kLogReceiver, kLogSyslogErr,
302 "CatalogMergeTool - Could not commit output catalog");
303 return false;
304 }
305
306
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 const std::string new_path = CreateTempPath(temp_dir_prefix_, 0600);
307
308
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
2 if (!manifest_->Export(new_path)) {
309 LogCvmfs(kLogReceiver, kLogSyslogErr,
310 "CatalogMergeTool - Could not export new manifest");
311 }
312
313
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 *new_manifest_path = new_path;
314
315 2 return true;
316 2 }
317
318 } // namespace receiver
319
320 #endif // CVMFS_RECEIVER_CATALOG_MERGE_TOOL_IMPL_H_
321