Skip to content

Commit 9dbc37f

Browse files
fmeumcopybara-github
authored andcommitted
Add support for --incompatible_compact_repo_mapping_manifest
Copybara Import from #417 BEGIN_PUBLIC Add support for `--incompatible_compact_repo_mapping_manifest` (#417) Closes #417 END_PUBLIC COPYBARA_INTEGRATE_REVIEW=#417 from fmeum:compact-repo-mapping 09aaf16 PiperOrigin-RevId: 804917692 Change-Id: I2399ee18d785cfaba5cbe1d0502bb1a805fe992e
1 parent 2a71690 commit 9dbc37f

File tree

2 files changed

+90
-32
lines changed

2 files changed

+90
-32
lines changed

cc/runfiles/runfiles.cc

Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -46,37 +46,17 @@ using std::vector;
4646

4747
namespace {
4848

49-
bool starts_with(const string& s, const char* prefix) {
50-
if (!prefix || !*prefix) {
51-
return true;
52-
}
53-
if (s.empty()) {
54-
return false;
55-
}
56-
return s.find(prefix) == 0;
49+
bool starts_with(const string& s, const string& prefix) {
50+
return s.compare(0, prefix.size(), prefix) == 0;
5751
}
5852

59-
bool contains(const string& s, const char* substr) {
60-
if (!substr || !*substr) {
61-
return true;
62-
}
63-
if (s.empty()) {
64-
return false;
65-
}
53+
bool contains(const string& s, const string& substr) {
6654
return s.find(substr) != string::npos;
6755
}
6856

6957
bool ends_with(const string& s, const string& suffix) {
70-
if (suffix.empty()) {
71-
return true;
72-
}
73-
if (s.empty()) {
74-
return false;
75-
}
76-
if (suffix.size() > s.size()) {
77-
return false;
78-
}
79-
return s.rfind(suffix) == s.size() - suffix.size();
58+
return s.size() >= suffix.size() &&
59+
s.compare(s.size() - suffix.size(), suffix.size(), suffix) == 0;
8060
}
8161

8262
bool IsReadableFile(const string& path) {
@@ -232,13 +212,27 @@ string Runfiles::Rlocation(const string& path,
232212
return RlocationUnchecked(path, runfiles_map_, directory_);
233213
}
234214
string target_apparent = path.substr(0, first_slash);
235-
auto target =
236-
repo_mapping_.find(std::make_pair(source_repo, target_apparent));
237-
if (target == repo_mapping_.cend()) {
238-
return RlocationUnchecked(path, runfiles_map_, directory_);
215+
auto lookup_key = std::make_pair(target_apparent, source_repo);
216+
auto lower_bound = repo_mapping_.lower_bound(lookup_key);
217+
if (lower_bound->first == lookup_key) {
218+
return RlocationUnchecked(lower_bound->second + path.substr(first_slash),
219+
runfiles_map_, directory_);
220+
}
221+
// Since the asterisk sorts before any other valid character in a repo name,
222+
// the previous element may be a prefix match.
223+
if (lower_bound != repo_mapping_.begin()) {
224+
std::pair<string, string> key;
225+
string value;
226+
std::tie(key, value) = *std::prev(lower_bound);
227+
if (key.first == target_apparent &&
228+
ends_with(key.second, "*") &&
229+
starts_with(
230+
source_repo, key.second.substr( 0, key.second.size() - 1))) {
231+
return RlocationUnchecked(
232+
value + path.substr(first_slash), runfiles_map_, directory_);
233+
}
239234
}
240-
return RlocationUnchecked(target->second + path.substr(first_slash),
241-
runfiles_map_, directory_);
235+
return RlocationUnchecked(path, runfiles_map_, directory_);
242236
}
243237

244238
string Runfiles::RlocationUnchecked(const string& path,
@@ -360,12 +354,17 @@ bool ParseRepoMapping(const string& path,
360354
return false;
361355
}
362356

357+
// If the source repo ends with an asterisk, the line is supposed to match
358+
// any name that starts with the prefix up to the asterisk. Since an
359+
// asterisk sorts before any other valid character in a repo name, we can
360+
// insert the line as is and search for a lower bound if we store the
361+
// apparent target repo name first in the map key.
363362
string source = line.substr(0, first_comma);
364363
string target_apparent =
365364
line.substr(first_comma + 1, second_comma - (first_comma + 1));
366365
string target = line.substr(second_comma + 1);
367366

368-
(*result)[std::make_pair(source, target_apparent)] = target;
367+
(*result)[std::make_pair(target_apparent, source)] = target;
369368
std::getline(stm, line);
370369
++line_count;
371370
}

tests/runfiles/runfiles_test.cc

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,40 @@ TEST_F(RunfilesTest, ManifestBasedRlocationWithRepoMapping_fromOtherRepo) {
717717
EXPECT_EQ(r->Rlocation("protobuf"), "");
718718
}
719719

720+
TEST_F(RunfilesTest, ManifestBasedRlocationWithRepoMapping_fromExtensionRepo) {
721+
string uid = LINE_AS_STRING();
722+
unique_ptr<MockFile> rm(
723+
MockFile::Create("foo" + uid + ".runfiles/_repo_mapping",
724+
{",config.json,config.json+1.2.3", ",my_module,_main",
725+
",my_protobuf,protobuf+3.19.2", ",my_workspace,_main",
726+
"my_module++ext+*,my_module,my_module+",
727+
"my_module++ext+*,repo1,my_module++ext+repo1"}));
728+
ASSERT_TRUE(rm != nullptr);
729+
unique_ptr<MockFile> mf(MockFile::Create(
730+
"foo" + uid + ".runfiles_manifest",
731+
{"_repo_mapping " + rm->Path(), "config.json /etc/config.json",
732+
"protobuf+3.19.2/foo/runfile C:/Actual Path\\protobuf\\runfile",
733+
"_main/bar/runfile /the/path/./to/other//other runfile.txt",
734+
"protobuf+3.19.2/bar/dir E:\\Actual Path\\Directory",
735+
"my_module+/foo /the/path/to/my_module+/runfile",
736+
"my_module++ext+repo1/foo /the/path/to/my_module++ext+repo1/runfile",
737+
"repo2+/foo /the/path/to/repo2+/runfile"}));
738+
ASSERT_TRUE(mf != nullptr);
739+
string argv0(mf->Path().substr(
740+
0, mf->Path().size() - string(".runfiles_manifest").size()));
741+
742+
string error;
743+
unique_ptr<Runfiles> r(Runfiles::Create(argv0, /*runfiles_manifest_file=*/"",
744+
/*runfiles_dir=*/"",
745+
"my_module++ext+repo1", &error));
746+
ASSERT_TRUE(r != nullptr);
747+
EXPECT_TRUE(error.empty());
748+
749+
EXPECT_EQ(r->Rlocation("my_module/foo"), "/the/path/to/my_module+/runfile");
750+
EXPECT_EQ(r->Rlocation("repo1/foo"), "/the/path/to/my_module++ext+repo1/runfile");
751+
EXPECT_EQ(r->Rlocation("repo2+/foo"), "/the/path/to/repo2+/runfile");
752+
}
753+
720754
TEST_F(RunfilesTest, DirectoryBasedRlocationWithRepoMapping_fromMain) {
721755
string uid = LINE_AS_STRING();
722756
unique_ptr<MockFile> rm(
@@ -858,6 +892,31 @@ TEST_F(RunfilesTest,
858892
EXPECT_EQ(r->Rlocation("config.json"), dir + "/config.json");
859893
}
860894

895+
TEST_F(RunfilesTest, DirectoryBasedRlocationWithRepoMapping_fromExtensionRepo) {
896+
string uid = LINE_AS_STRING();
897+
unique_ptr<MockFile> rm(
898+
MockFile::Create("foo" + uid + ".runfiles/_repo_mapping",
899+
{",config.json,config.json+1.2.3", ",my_module,_main",
900+
",my_protobuf,protobuf+3.19.2", ",my_workspace,_main",
901+
"my_module++ext+*,my_module,my_module+",
902+
"my_module++ext+*,repo1,my_module++ext+repo1"}));
903+
ASSERT_TRUE(rm != nullptr);
904+
string dir = rm->DirName();
905+
string argv0(dir.substr(0, dir.size() - string(".runfiles").size()));
906+
907+
string error;
908+
unique_ptr<Runfiles> r(Runfiles::Create(argv0, /*runfiles_manifest_file=*/"",
909+
/*runfiles_dir=*/"",
910+
/*source_repository=*/"", &error));
911+
r = r->WithSourceRepository("my_module++ext+repo1");
912+
ASSERT_TRUE(r != nullptr);
913+
EXPECT_TRUE(error.empty());
914+
915+
EXPECT_EQ(r->Rlocation("my_module/foo"), dir + "/my_module+/foo");
916+
EXPECT_EQ(r->Rlocation("repo1/foo"), dir + "/my_module++ext+repo1/foo");
917+
EXPECT_EQ(r->Rlocation("repo2+/foo"), dir + "/repo2+/foo");
918+
}
919+
861920
TEST_F(RunfilesTest, InvalidRepoMapping) {
862921
string uid = LINE_AS_STRING();
863922
unique_ptr<MockFile> rm(

0 commit comments

Comments
 (0)