aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/tools/runfiles/runfiles.cc
diff options
context:
space:
mode:
authorGravatar Laszlo Csomor <laszlocsomor@google.com>2018-02-28 06:48:18 -0800
committerGravatar Copybara-Service <copybara-piper@google.com>2018-02-28 06:49:53 -0800
commite7d9e1f8aae459ec71cdb31f988661f4c3975ca8 (patch)
treeb9e4f36d4ad55fe8a45aba0667db010fae9e8e95 /src/tools/runfiles/runfiles.cc
parent51275462a5f63d34e176e76ef372e91b25ecee56 (diff)
runfiles,C++: implement manifest-based runfiles
Implement a manifest-based Runfiles object, add tests and test utils (MockFile). Subsequent commits will add more feataures: - creating list of envvars to pass to child processes - automatic Runfiles creation based on argv[0] and the envvars of this process See https://github.com/bazelbuild/bazel/issues/4460 Change-Id: I4376ede3ac00241688ff16a36ed596fb08f13a72 PiperOrigin-RevId: 187318502
Diffstat (limited to 'src/tools/runfiles/runfiles.cc')
-rw-r--r--src/tools/runfiles/runfiles.cc83
1 files changed, 82 insertions, 1 deletions
diff --git a/src/tools/runfiles/runfiles.cc b/src/tools/runfiles/runfiles.cc
index 9ff1f3f4c5..1de2f1a1f4 100644
--- a/src/tools/runfiles/runfiles.cc
+++ b/src/tools/runfiles/runfiles.cc
@@ -13,9 +13,14 @@
// limitations under the License.
#include "tools/runfiles/runfiles.h"
+#include <fstream>
+#include <map>
+#include <sstream>
+
namespace bazel {
namespace runfiles {
+using std::map;
using std::string;
namespace {
@@ -39,7 +44,31 @@ class RunfilesImpl : public Runfiles {
virtual ~RunfilesImpl() {}
};
-// TODO(laszlocsomor): derive a ManifestBased class from RunfilesImpl.
+// Runfiles implementation that parses a runfiles-manifest to look up runfiles.
+class ManifestBased : public RunfilesImpl {
+ public:
+ // Returns a new `ManifestBased` instance.
+ // Reads the file at `manifest_path` to build a map of the runfiles.
+ // Returns nullptr upon failure.
+ static ManifestBased* Create(const string& manifest_path, string* error);
+
+ string RlocationChecked(const string& path) const override;
+
+ private:
+ ManifestBased(const string& manifest_path, map<string, string>&& runfiles_map)
+ : manifest_path_(manifest_path), runfiles_map_(runfiles_map) {}
+
+ ManifestBased(const ManifestBased&) = delete;
+ ManifestBased(ManifestBased&&) = delete;
+ ManifestBased& operator=(const ManifestBased&) = delete;
+ ManifestBased& operator=(ManifestBased&&) = delete;
+
+ static bool ParseManifest(const string& path, map<string, string>* result,
+ string* error);
+
+ const string manifest_path_;
+ const map<string, string> runfiles_map_;
+};
// Runfiles implementation that appends runfiles paths to the runfiles root.
class DirectoryBased : public RunfilesImpl {
@@ -77,6 +106,53 @@ string RunfilesImpl::Rlocation(const string& path) const {
return RlocationChecked(path);
}
+ManifestBased* ManifestBased::Create(const string& manifest_path,
+ string* error) {
+ map<string, string> runfiles;
+ return ParseManifest(manifest_path, &runfiles, error)
+ ? new ManifestBased(manifest_path, std::move(runfiles))
+ : nullptr;
+}
+
+string ManifestBased::RlocationChecked(const string& path) const {
+ const auto value = runfiles_map_.find(path);
+ return std::move(value == runfiles_map_.end() ? string() : value->second);
+}
+
+bool ManifestBased::ParseManifest(const string& path,
+ map<string, string>* result, string* error) {
+ std::ifstream stm(path);
+ if (!stm.is_open()) {
+ if (error) {
+ std::ostringstream err;
+ err << "ERROR: " << __FILE__ << "(" << __LINE__
+ << "): cannot open runfiles manifest \"" << path << "\"";
+ *error = err.str();
+ }
+ return false;
+ }
+ string line;
+ std::getline(stm, line);
+ size_t line_count = 1;
+ while (!line.empty()) {
+ string::size_type idx = line.find_first_of(' ');
+ if (idx == string::npos) {
+ if (error) {
+ std::ostringstream err;
+ err << "ERROR: " << __FILE__ << "(" << __LINE__
+ << "): bad runfiles manifest entry in \"" << path << "\" line #"
+ << line_count << ": \"" << line << "\"";
+ *error = err.str();
+ }
+ return false;
+ }
+ (*result)[line.substr(0, idx)] = line.substr(idx + 1);
+ std::getline(stm, line);
+ ++line_count;
+ }
+ return true;
+}
+
string DirectoryBased::RlocationChecked(const string& path) const {
return std::move(runfiles_path_ + "/" + path);
}
@@ -89,6 +165,11 @@ bool TestOnly_IsAbsolute(const string& path) { return IsAbsolute(path); }
} // namespace testing
+Runfiles* Runfiles::CreateManifestBased(const string& manifest_path,
+ string* error) {
+ return ManifestBased::Create(manifest_path, error);
+}
+
Runfiles* Runfiles::CreateDirectoryBased(const string& directory_path,
string* error) {
// Note: `error` is intentionally unused because we don't expect any errors