GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/publish/repository_tags.cc
Date: 2026-10-11 02:40:02
Exec Total Coverage
Lines: 0 55 0.0%
Branches: 0 124 0.0%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4
5
6 #include <unistd.h>
7
8 #include <vector>
9
10 #include "history_sqlite.h"
11 #include "manifest.h"
12 #include "publish/except.h"
13 #include "publish/repository.h"
14 #include "repository_tag.h"
15 #include "sanitizer.h"
16 #include "upload.h"
17 #include "upload_spooler_definition.h"
18 #include "util/logging.h"
19 #include "util/string.h"
20
21 namespace publish {
22
23 ✗ void Publisher::CheckTagName(const std::string &name) {
24 ✗ if (name.empty())
25 ✗ throw EPublish("the empty string is not a valid tag name");
26 ✗ if (name == "trunk")
27 ✗ throw EPublish("'trunk' is not allowed as a custom tag name");
28 ✗ if (name == "trunk-previous")
29 ✗ throw EPublish("'trunk-previous' is not allowed as a custom tag name");
30 ✗ if (!sanitizer::TagSanitizer().IsValid(name))
31 ✗ throw EPublish("invalid tag name: " + name);
32 }
33
34
35 ✗ void Publisher::EditTags(const std::vector<history::History::Tag> &add_tags,
36 const std::vector<std::string> &rm_tags) {
37 ✗ if (settings_.storage().type() == upload::SpoolerDefinition::Gateway) {
38 ✗ EditTagsGateway(add_tags, rm_tags);
39 ✗ return;
40 }
41
42 ✗ if (!in_transaction_.IsSet())
43 ✗ throw EPublish("cannot edit tags outside transaction");
44
45 ✗ for (unsigned i = 0; i < add_tags.size(); ++i) {
46 ✗ const std::string name = add_tags[i].name;
47 ✗ CheckTagName(name);
48 ✗ history_->Insert(add_tags[i]);
49 }
50
51 ✗ for (unsigned i = 0; i < rm_tags.size(); ++i) {
52 ✗ const std::string name = rm_tags[i];
53 ✗ CheckTagName(name);
54 ✗ if (history_->Exists(name)) {
55 ✗ const bool retval = history_->Remove(name);
56 ✗ if (!retval)
57 ✗ throw EPublish("cannot remove tag " + name);
58 }
59 }
60
61 ✗ PushHistory();
62
63 // TODO(jblomer): virtual catalog
64 }
65
66
67 ✗ void Publisher::EditTagsGateway(
68 const std::vector<history::History::Tag> &add_tags,
69 const std::vector<std::string> &rm_tags) {
70 // Validate everything up front so we never acquire a lease for a request that
71 // is bound to be rejected.
72 ✗ RepositoryTag repo_tag;
73 ✗ if (!rm_tags.empty()) {
74 ✗ for (unsigned i = 0; i < rm_tags.size(); ++i)
75 ✗ CheckTagName(rm_tags[i]);
76 ✗ repo_tag.SetDeleteTags(JoinStrings(rm_tags, " "));
77 }
78 ✗ if (!add_tags.empty()) {
79 // The commit protocol carries a single tag to add (tagging the new HEAD).
80 ✗ if (add_tags.size() > 1) {
81 ✗ throw EPublish("adding more than one tag in a single gateway operation "
82 ✗ "is not supported");
83 }
84 ✗ CheckTagName(add_tags[0].name);
85 ✗ if (!add_tags[0].root_hash.IsNull()) {
86 ✗ throw EPublish("tagging a specific root hash is not supported on gateway "
87 ✗ "repositories");
88 }
89 ✗ repo_tag.SetName(add_tags[0].name);
90 ✗ repo_tag.SetDescription(add_tags[0].description);
91 }
92
93 // The tag database is edited by the receiver; the catalog itself does not
94 // change, so the commit carries the current root hash as both the old and
95 // the new hash (an empty catalog diff).
96 ✗ const std::string root_hash = manifest_->catalog_hash().ToString(
97 ✗ true /* with_suffix */);
98
99 // Acquire a gateway lease and write the session token before constructing the
100 // spoolers, which read it.
101 ✗ session_->Acquire();
102 ✗ ConstructSpoolers();
103
104 ✗ spooler_files_->FinalizeSession(false /* commit */);
105 ✗ const bool rvb = spooler_catalogs_->FinalizeSession(
106 true /* commit */, root_hash, root_hash, repo_tag);
107
108 ✗ if (!rvb) {
109 // Leave the lease in place so the Session destructor releases it.
110 ✗ throw EPublish("failed to commit tag changes to the gateway");
111 }
112
113 // A successful commit makes the gateway drop the lease; remove the local
114 // session token and keep the Session object from trying to drop it again.
115 ✗ session_->SetKeepAlive(true);
116 ✗ unlink(session_->token_path().c_str());
117 ✗ unlink(session_->api_version_path().c_str());
118
119 ✗ LogCvmfs(kLogCvmfs, kLogStdout, "Tags updated");
120 }
121
122 } // namespace publish
123