diff options
author | Laszlo Csomor <laszlocsomor@google.com> | 2018-05-22 05:01:41 -0700 |
---|---|---|
committer | Copybara-Service <copybara-piper@google.com> | 2018-05-22 05:02:42 -0700 |
commit | c29f34fa81a16abdfc1b5aad03f76d36ce8793ba (patch) | |
tree | 10dc1e3270e93e4e3af667735164cd91f9606194 /tools | |
parent | a1ae44a71a6a43aa9d27888d9cf53d4baa0816e3 (diff) |
runfiles,python: add a method to discover runfiles
The new method discovers the runfiles manifest and
runfiles directory using the values of the
RUNFILES_MANIFEST_FILE and RUNFILES_DIR envvars
(if specified), and if needed, also looks for them
next to sys.argv[0].
This commit is a copy of https://github.com/bazelbuild/bazel/commit/9f2b052d93bfd188687f28fe6771f390d3626936
ported from C++ to Python.
See https://github.com/bazelbuild/bazel/issues/4460
Change-Id: I6916366ca73575703fe39ce69020eec3b54457bf
Closes #5233.
Change-Id: I6916366ca73575703fe39ce69020eec3b54457bf
PiperOrigin-RevId: 197544480
Diffstat (limited to 'tools')
-rw-r--r-- | tools/python/runfiles/runfiles.py | 51 | ||||
-rw-r--r-- | tools/python/runfiles/runfiles_test.py | 87 |
2 files changed, 138 insertions, 0 deletions
diff --git a/tools/python/runfiles/runfiles.py b/tools/python/runfiles/runfiles.py index 1053319eca..e80a7d19a9 100644 --- a/tools/python/runfiles/runfiles.py +++ b/tools/python/runfiles/runfiles.py @@ -219,3 +219,54 @@ class _DirectoryBased(object): # pick up RUNFILES_DIR. "JAVA_RUNFILES": self._runfiles_root, } + + +def _PathsFrom(argv0, runfiles_mf, runfiles_dir, is_runfiles_manifest, + is_runfiles_directory): + """Discover runfiles manifest and runfiles directory paths. + + Args: + argv0: string; the value of sys.argv[0] + runfiles_mf: string; the value of the RUNFILES_MANIFEST_FILE environment + variable + runfiles_dir: string; the value of the RUNFILES_DIR environment variable + is_runfiles_manifest: lambda(string):bool; returns true if the argument is + the path of a runfiles manifest file + is_runfiles_directory: lambda(string):bool; returns true if the argument is + the path of a runfiles directory + + Returns: + (string, string) pair, first element is the path to the runfiles manifest, + second element is the path to the runfiles directory. If the first element + is non-empty, then is_runfiles_manifest returns true for it. Same goes for + the second element and is_runfiles_directory respectively. If both elements + are empty, then this function could not find a manifest or directory for + which is_runfiles_manifest or is_runfiles_directory returns true. + """ + mf_alid = is_runfiles_manifest(runfiles_mf) + dir_valid = is_runfiles_directory(runfiles_dir) + + if not mf_alid and not dir_valid: + runfiles_mf = argv0 + ".runfiles/MANIFEST" + runfiles_dir = argv0 + ".runfiles" + mf_alid = is_runfiles_manifest(runfiles_mf) + dir_valid = is_runfiles_directory(runfiles_dir) + if not mf_alid: + runfiles_mf = argv0 + ".runfiles_manifest" + mf_alid = is_runfiles_manifest(runfiles_mf) + + if not mf_alid and not dir_valid: + return ("", "") + + if not mf_alid: + runfiles_mf = runfiles_dir + "/MANIFEST" + mf_alid = is_runfiles_manifest(runfiles_mf) + if not mf_alid: + runfiles_mf = runfiles_dir + "_manifest" + mf_alid = is_runfiles_manifest(runfiles_mf) + + if not dir_valid: + runfiles_dir = runfiles_mf[:-9] # "_manifest" or "/MANIFEST" + dir_valid = is_runfiles_directory(runfiles_dir) + + return (runfiles_mf if mf_alid else "", runfiles_dir if dir_valid else "") diff --git a/tools/python/runfiles/runfiles_test.py b/tools/python/runfiles/runfiles_test.py index f8373054c8..1212bbaad8 100644 --- a/tools/python/runfiles/runfiles_test.py +++ b/tools/python/runfiles/runfiles_test.py @@ -167,6 +167,93 @@ class RunfilesTest(unittest.TestCase): else: self.assertEqual(r.Rlocation("/foo"), "/foo") + def testPathsFromEnvvars(self): + # Both envvars have a valid value. + mf, dr = runfiles._PathsFrom("argv0", "mock1/MANIFEST", "mock2", + lambda path: path == "mock1/MANIFEST", + lambda path: path == "mock2") + self.assertEqual(mf, "mock1/MANIFEST") + self.assertEqual(dr, "mock2") + + # RUNFILES_MANIFEST_FILE is invalid but RUNFILES_DIR is good and there's a + # runfiles manifest in the runfiles directory. + mf, dr = runfiles._PathsFrom("argv0", "mock1/MANIFEST", "mock2", + lambda path: path == "mock2/MANIFEST", + lambda path: path == "mock2") + self.assertEqual(mf, "mock2/MANIFEST") + self.assertEqual(dr, "mock2") + + # RUNFILES_MANIFEST_FILE is invalid but RUNFILES_DIR is good, but there's no + # runfiles manifest in the runfiles directory. + mf, dr = runfiles._PathsFrom("argv0", "mock1/MANIFEST", "mock2", + lambda path: False, + lambda path: path == "mock2") + self.assertEqual(mf, "") + self.assertEqual(dr, "mock2") + + # RUNFILES_DIR is invalid but RUNFILES_MANIFEST_FILE is good, and it is in + # a valid-looking runfiles directory. + mf, dr = runfiles._PathsFrom("argv0", "mock1/MANIFEST", "mock2", + lambda path: path == "mock1/MANIFEST", + lambda path: path == "mock1") + self.assertEqual(mf, "mock1/MANIFEST") + self.assertEqual(dr, "mock1") + + # RUNFILES_DIR is invalid but RUNFILES_MANIFEST_FILE is good, but it is not + # in any valid-looking runfiles directory. + mf, dr = runfiles._PathsFrom("argv0", "mock1/MANIFEST", "mock2", + lambda path: path == "mock1/MANIFEST", + lambda path: False) + self.assertEqual(mf, "mock1/MANIFEST") + self.assertEqual(dr, "") + + # Both envvars are invalid, but there's a manifest in a runfiles directory + # next to argv0, however there's no other content in the runfiles directory. + mf, dr = runfiles._PathsFrom("argv0", "mock1/MANIFEST", "mock2", + lambda path: path == "argv0.runfiles/MANIFEST", + lambda path: False) + self.assertEqual(mf, "argv0.runfiles/MANIFEST") + self.assertEqual(dr, "") + + # Both envvars are invalid, but there's a manifest next to argv0. There's + # no runfiles tree anywhere. + mf, dr = runfiles._PathsFrom("argv0", "mock1/MANIFEST", "mock2", + lambda path: path == "argv0.runfiles_manifest", + lambda path: False) + self.assertEqual(mf, "argv0.runfiles_manifest") + self.assertEqual(dr, "") + + # Both envvars are invalid, but there's a valid manifest next to argv0, and + # a valid runfiles directory (without a manifest in it). + mf, dr = runfiles._PathsFrom("argv0", "mock1/MANIFEST", "mock2", + lambda path: path == "argv0.runfiles_manifest", + lambda path: path == "argv0.runfiles") + self.assertEqual(mf, "argv0.runfiles_manifest") + self.assertEqual(dr, "argv0.runfiles") + + # Both envvars are invalid, but there's a valid runfiles directory next to + # argv0, though no manifest in it. + mf, dr = runfiles._PathsFrom("argv0", "mock1/MANIFEST", "mock2", + lambda path: False, + lambda path: path == "argv0.runfiles") + self.assertEqual(mf, "") + self.assertEqual(dr, "argv0.runfiles") + + # Both envvars are invalid, but there's a valid runfiles directory next to + # argv0 with a valid manifest in it. + mf, dr = runfiles._PathsFrom("argv0", "mock1/MANIFEST", "mock2", + lambda path: path == "argv0.runfiles/MANIFEST", + lambda path: path == "argv0.runfiles") + self.assertEqual(mf, "argv0.runfiles/MANIFEST") + self.assertEqual(dr, "argv0.runfiles") + + # Both envvars are invalid and there's no runfiles directory or manifest + # next to the argv0. + mf, dr = runfiles._PathsFrom("argv0", "mock1/MANIFEST", "mock2", + lambda path: False, lambda path: False) + self.assertEqual(mf, "") + self.assertEqual(dr, "") + @staticmethod def IsWindows(): return os.name == "nt" |