Skip to content

Commit 8da6166

Browse files
levympUebelAndre
andauthored
Update the runfiles library behavior to support an empty RUNFILES_MANIFEST_FILE (#3655)
Instead fallback on a directory based approach. This matches the behavior of rules_python: https://github.com/bazel-contrib/rules_python/blob/79f654686646e2ab213741bc4774ea9d69895b54/python/runfiles/runfiles.py#L458 This addresses #3654. --------- Co-authored-by: UebelAndre <[email protected]>
1 parent d91735d commit 8da6166

File tree

1 file changed

+50
-16
lines changed

1 file changed

+50
-16
lines changed

rust/runfiles/runfiles.rs

Lines changed: 50 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -151,18 +151,21 @@ pub struct Runfiles {
151151
}
152152

153153
impl Runfiles {
154-
/// Creates a manifest based Runfiles object when
155-
/// RUNFILES_MANIFEST_FILE environment variable is present,
156-
/// or a directory based Runfiles object otherwise.
154+
/// Creates a manifest based Runfiles object when RUNFILES_MANIFEST_FILE
155+
/// environment variable is present, with an non-empty value, or a directory
156+
/// based Runfiles object otherwise.
157157
pub fn create() -> Result<Self> {
158-
let mode = if let Some(manifest_file) = std::env::var_os(MANIFEST_FILE_ENV_VAR) {
159-
Self::create_manifest_based(Path::new(&manifest_file))?
160-
} else {
161-
let dir = find_runfiles_dir()?;
162-
let manifest_path = dir.join("MANIFEST");
163-
match manifest_path.exists() {
164-
true => Self::create_manifest_based(&manifest_path)?,
165-
false => Mode::DirectoryBased(dir),
158+
let mode = match std::env::var_os(MANIFEST_FILE_ENV_VAR) {
159+
Some(manifest_file) if !manifest_file.is_empty() => {
160+
Self::create_manifest_based(Path::new(&manifest_file))?
161+
}
162+
_ => {
163+
let dir = find_runfiles_dir()?;
164+
let manifest_path = dir.join("MANIFEST");
165+
match manifest_path.exists() {
166+
true => Self::create_manifest_based(&manifest_path)?,
167+
false => Mode::DirectoryBased(dir),
168+
}
166169
}
167170
};
168171

@@ -266,11 +269,13 @@ fn parse_repo_mapping(path: PathBuf) -> Result<RepoMapping> {
266269

267270
/// Returns the .runfiles directory for the currently executing binary.
268271
pub fn find_runfiles_dir() -> Result<PathBuf> {
269-
assert!(
270-
std::env::var_os(MANIFEST_FILE_ENV_VAR).is_none(),
271-
"Unexpected call when {} exists",
272-
MANIFEST_FILE_ENV_VAR
273-
);
272+
if let Some(value) = std::env::var_os(MANIFEST_FILE_ENV_VAR) {
273+
assert!(
274+
value.is_empty(),
275+
"Unexpected call when {} exists",
276+
MANIFEST_FILE_ENV_VAR
277+
);
278+
}
274279

275280
// If Bazel told us about the runfiles dir, use that without looking further.
276281
if let Some(runfiles_dir) = std::env::var_os(RUNFILES_DIR_ENV_VAR).map(PathBuf::from) {
@@ -480,6 +485,35 @@ mod test {
480485
);
481486
}
482487

488+
/// Tests when MANIFEST_FILE is set to an empty string, RUNFILES_DIR is preferred.
489+
#[test]
490+
fn test_runfiles_manifest_file_empty() {
491+
let runfiles_dir = make_runfiles_like_dir("test_runfiles_manifest_file_empty");
492+
493+
with_mock_env(
494+
[
495+
(MANIFEST_FILE_ENV_VAR, Some("")),
496+
(RUNFILES_DIR_ENV_VAR, Some(runfiles_dir.as_str())),
497+
(TEST_SRCDIR_ENV_VAR, None::<&str>),
498+
],
499+
|| {
500+
let r = Runfiles::create().unwrap();
501+
502+
let d = rlocation!(r, "rules_rust").unwrap();
503+
let f = rlocation!(r, "rules_rust/rust/runfiles/data/sample.txt").unwrap();
504+
assert_eq!(d.join("rust/runfiles/data/sample.txt"), f);
505+
506+
let mut f = File::open(&f)
507+
.unwrap_or_else(|e| panic!("Failed to open file: {}\n{:?}", f.display(), e));
508+
509+
let mut buffer = String::new();
510+
f.read_to_string(&mut buffer).unwrap();
511+
512+
assert_eq!("Example Text!", buffer);
513+
},
514+
);
515+
}
516+
483517
/// Only `TEST_SRCDIR` is set.
484518
#[test]
485519
fn test_env_only_test_srcdir() {

0 commit comments

Comments
 (0)