Skip to content

Commit 8f28513

Browse files
fmeumcopybara-github
authored andcommitted
Make C++ runfiles library repo mapping aware
Also removes a comment mentioning a `Create` overload that does not exist. Work towards bazelbuild#16124 Closes bazelbuild#16623. PiperOrigin-RevId: 486612245 Change-Id: Ib22cadd354c93eb1e113e27b271c639345c20074
1 parent 3109f81 commit 8f28513

File tree

3 files changed

+526
-54
lines changed

3 files changed

+526
-54
lines changed

tools/cpp/runfiles/runfiles_src.cc

+151-19
Original file line numberDiff line numberDiff line change
@@ -96,25 +96,30 @@ bool IsDirectory(const string& path) {
9696

9797
bool PathsFrom(const std::string& argv0, std::string runfiles_manifest_file,
9898
std::string runfiles_dir, std::string* out_manifest,
99-
std::string* out_directory);
99+
std::string* out_directory, std::string* out_repo_mapping);
100100

101101
bool PathsFrom(const std::string& argv0, std::string runfiles_manifest_file,
102102
std::string runfiles_dir,
103103
std::function<bool(const std::string&)> is_runfiles_manifest,
104104
std::function<bool(const std::string&)> is_runfiles_directory,
105-
std::string* out_manifest, std::string* out_directory);
105+
std::function<bool(const std::string&)> is_repo_mapping,
106+
std::string* out_manifest, std::string* out_directory,
107+
std::string* out_repo_mapping);
106108

107109
bool ParseManifest(const string& path, map<string, string>* result,
108110
string* error);
111+
bool ParseRepoMapping(const string& path,
112+
map<pair<string, string>, string>* result, string* error);
109113

110114
} // namespace
111115

112116
Runfiles* Runfiles::Create(const string& argv0,
113117
const string& runfiles_manifest_file,
114-
const string& runfiles_dir, string* error) {
115-
string manifest, directory;
118+
const string& runfiles_dir,
119+
const string& source_repository, string* error) {
120+
string manifest, directory, repo_mapping;
116121
if (!PathsFrom(argv0, runfiles_manifest_file, runfiles_dir, &manifest,
117-
&directory)) {
122+
&directory, &repo_mapping)) {
118123
if (error) {
119124
std::ostringstream err;
120125
err << "ERROR: " << __FILE__ << "(" << __LINE__
@@ -124,7 +129,7 @@ Runfiles* Runfiles::Create(const string& argv0,
124129
return nullptr;
125130
}
126131

127-
const vector<pair<string, string> > envvars = {
132+
vector<pair<string, string> > envvars = {
128133
{"RUNFILES_MANIFEST_FILE", manifest},
129134
{"RUNFILES_DIR", directory},
130135
// TODO(laszlocsomor): remove JAVA_RUNFILES once the Java launcher can
@@ -138,8 +143,16 @@ Runfiles* Runfiles::Create(const string& argv0,
138143
}
139144
}
140145

146+
map<pair<string, string>, string> mapping;
147+
if (!repo_mapping.empty()) {
148+
if (!ParseRepoMapping(repo_mapping, &mapping, error)) {
149+
return nullptr;
150+
}
151+
}
152+
141153
return new Runfiles(std::move(runfiles), std::move(directory),
142-
std::move(envvars));
154+
std::move(mapping), std::move(envvars),
155+
string(source_repository));
143156
}
144157

145158
bool IsAbsolute(const string& path) {
@@ -169,6 +182,11 @@ string GetEnv(const string& key) {
169182
}
170183

171184
string Runfiles::Rlocation(const string& path) const {
185+
return Rlocation(path, source_repository_);
186+
}
187+
188+
string Runfiles::Rlocation(const string& path,
189+
const string& source_repo) const {
172190
if (path.empty() || starts_with(path, "../") || contains(path, "/..") ||
173191
starts_with(path, "./") || contains(path, "/./") ||
174192
ends_with(path, "/.") || contains(path, "//")) {
@@ -177,6 +195,24 @@ string Runfiles::Rlocation(const string& path) const {
177195
if (IsAbsolute(path)) {
178196
return path;
179197
}
198+
199+
if (repo_mapping_.empty()) {
200+
return RlocationUnchecked(path);
201+
}
202+
string::size_type first_slash = path.find_first_of('/');
203+
if (first_slash == string::npos) {
204+
return RlocationUnchecked(path);
205+
}
206+
string target_apparent = path.substr(0, first_slash);
207+
auto target =
208+
repo_mapping_.find(std::make_pair(source_repo, target_apparent));
209+
if (target == repo_mapping_.cend()) {
210+
return RlocationUnchecked(path);
211+
}
212+
return RlocationUnchecked(target->second + path.substr(first_slash));
213+
}
214+
215+
string Runfiles::RlocationUnchecked(const string& path) const {
180216
const auto exact_match = runfiles_map_.find(path);
181217
if (exact_match != runfiles_map_.end()) {
182218
return exact_match->second;
@@ -238,48 +274,125 @@ bool ParseManifest(const string& path, map<string, string>* result,
238274
return true;
239275
}
240276

277+
bool ParseRepoMapping(const string& path,
278+
map<pair<string, string>, string>* result,
279+
string* error) {
280+
std::ifstream stm(path);
281+
if (!stm.is_open()) {
282+
if (error) {
283+
std::ostringstream err;
284+
err << "ERROR: " << __FILE__ << "(" << __LINE__
285+
<< "): cannot open repository mapping \"" << path << "\"";
286+
*error = err.str();
287+
}
288+
return false;
289+
}
290+
string line;
291+
std::getline(stm, line);
292+
size_t line_count = 1;
293+
while (!line.empty()) {
294+
string::size_type first_comma = line.find_first_of(',');
295+
if (first_comma == string::npos) {
296+
if (error) {
297+
std::ostringstream err;
298+
err << "ERROR: " << __FILE__ << "(" << __LINE__
299+
<< "): bad repository mapping entry in \"" << path << "\" line #"
300+
<< line_count << ": \"" << line << "\"";
301+
*error = err.str();
302+
}
303+
return false;
304+
}
305+
string::size_type second_comma = line.find_first_of(',', first_comma + 1);
306+
if (second_comma == string::npos) {
307+
if (error) {
308+
std::ostringstream err;
309+
err << "ERROR: " << __FILE__ << "(" << __LINE__
310+
<< "): bad repository mapping entry in \"" << path << "\" line #"
311+
<< line_count << ": \"" << line << "\"";
312+
*error = err.str();
313+
}
314+
return false;
315+
}
316+
317+
string source = line.substr(0, first_comma);
318+
string target_apparent =
319+
line.substr(first_comma + 1, second_comma - (first_comma + 1));
320+
string target = line.substr(second_comma + 1);
321+
322+
(*result)[std::make_pair(source, target_apparent)] = target;
323+
std::getline(stm, line);
324+
++line_count;
325+
}
326+
return true;
327+
}
328+
241329
} // namespace
242330

243331
namespace testing {
244332

245333
bool TestOnly_PathsFrom(const string& argv0, string mf, string dir,
246334
function<bool(const string&)> is_runfiles_manifest,
247335
function<bool(const string&)> is_runfiles_directory,
248-
string* out_manifest, string* out_directory) {
336+
function<bool(const string&)> is_repo_mapping,
337+
string* out_manifest, string* out_directory,
338+
string* out_repo_mapping) {
249339
return PathsFrom(argv0, mf, dir, is_runfiles_manifest, is_runfiles_directory,
250-
out_manifest, out_directory);
340+
is_repo_mapping, out_manifest, out_directory,
341+
out_repo_mapping);
251342
}
252343

253344
bool TestOnly_IsAbsolute(const string& path) { return IsAbsolute(path); }
254345

255346
} // namespace testing
256347

257-
Runfiles* Runfiles::Create(const string& argv0, string* error) {
348+
Runfiles* Runfiles::Create(const std::string& argv0,
349+
const std::string& runfiles_manifest_file,
350+
const std::string& runfiles_dir,
351+
std::string* error) {
352+
return Runfiles::Create(argv0, runfiles_manifest_file, runfiles_dir, "",
353+
error);
354+
}
355+
356+
Runfiles* Runfiles::Create(const string& argv0, const string& source_repository,
357+
string* error) {
258358
return Runfiles::Create(argv0, GetEnv("RUNFILES_MANIFEST_FILE"),
259-
GetEnv("RUNFILES_DIR"), error);
359+
GetEnv("RUNFILES_DIR"), source_repository, error);
260360
}
261361

262-
Runfiles* Runfiles::CreateForTest(std::string* error) {
362+
Runfiles* Runfiles::Create(const string& argv0, string* error) {
363+
return Runfiles::Create(argv0, "", error);
364+
}
365+
366+
Runfiles* Runfiles::CreateForTest(const string& source_repository,
367+
std::string* error) {
263368
return Runfiles::Create(std::string(), GetEnv("RUNFILES_MANIFEST_FILE"),
264-
GetEnv("TEST_SRCDIR"), error);
369+
GetEnv("TEST_SRCDIR"), source_repository, error);
370+
}
371+
372+
Runfiles* Runfiles::CreateForTest(std::string* error) {
373+
return Runfiles::CreateForTest("", error);
265374
}
266375

267376
namespace {
268377

269378
bool PathsFrom(const string& argv0, string mf, string dir, string* out_manifest,
270-
string* out_directory) {
271-
return PathsFrom(argv0, mf, dir,
272-
[](const string& path) { return IsReadableFile(path); },
273-
[](const string& path) { return IsDirectory(path); },
274-
out_manifest, out_directory);
379+
string* out_directory, string* out_repo_mapping) {
380+
return PathsFrom(
381+
argv0, mf, dir, [](const string& path) { return IsReadableFile(path); },
382+
[](const string& path) { return IsDirectory(path); },
383+
[](const string& path) { return IsReadableFile(path); }, out_manifest,
384+
out_directory, out_repo_mapping);
275385
}
276386

277387
bool PathsFrom(const string& argv0, string mf, string dir,
278388
function<bool(const string&)> is_runfiles_manifest,
279389
function<bool(const string&)> is_runfiles_directory,
280-
string* out_manifest, string* out_directory) {
390+
function<bool(const string&)> is_repo_mapping,
391+
string* out_manifest, string* out_directory,
392+
string* out_repo_mapping) {
281393
out_manifest->clear();
282394
out_directory->clear();
395+
out_repo_mapping->clear();
283396

284397
bool mfValid = is_runfiles_manifest(mf);
285398
bool dirValid = is_runfiles_directory(dir);
@@ -315,6 +428,21 @@ bool PathsFrom(const string& argv0, string mf, string dir,
315428
dirValid = is_runfiles_directory(dir);
316429
}
317430

431+
string rm;
432+
bool rmValid = false;
433+
434+
if (dirValid && ends_with(dir, ".runfiles")) {
435+
rm = dir.substr(0, dir.size() - 9) + ".repo_mapping";
436+
rmValid = is_repo_mapping(rm);
437+
}
438+
439+
if (!rmValid && mfValid &&
440+
(ends_with(mf, ".runfiles_manifest") ||
441+
ends_with(mf, ".runfiles/MANIFEST"))) {
442+
rm = mf.substr(0, mf.size() - 18) + ".repo_mapping";
443+
rmValid = is_repo_mapping(rm);
444+
}
445+
318446
if (mfValid) {
319447
*out_manifest = mf;
320448
}
@@ -323,6 +451,10 @@ bool PathsFrom(const string& argv0, string mf, string dir,
323451
*out_directory = dir;
324452
}
325453

454+
if (rmValid) {
455+
*out_repo_mapping = rm;
456+
}
457+
326458
return true;
327459
}
328460

0 commit comments

Comments
 (0)