Skip to content

Commit

Permalink
rollup merge of rust-lang#23283: brson/rpathfix
Browse files Browse the repository at this point in the history
Fix regression in -C rpath that causes failures with symlinks

The new `relative_from` method no longer supports the case on unix
where both paths are absolute, which `-C rpath` depended on. This
version fixes the problem by copying the old path_relative_from
function into the rpath module.

Fixes rust-lang#23140

After experimenting with the new `relative_from` function on `Path` I'm not sure what it's use case is. It no longer even figures out that the relative path from `/foo/bar` to `/foo/baz/qux` is `../baz/qux`.
  • Loading branch information
alexcrichton committed Mar 23, 2015
2 parents 67e516c + 9ec9bc6 commit e98d4d9
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 15 deletions.
58 changes: 43 additions & 15 deletions src/librustc_back/rpath.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,30 +99,58 @@ fn get_rpath_relative_to_output(config: &mut RPathConfig, lib: &Path) -> String
lib.pop();
let mut output = (config.realpath)(&cwd.join(&config.out_filename)).unwrap();
output.pop();
let relative = relativize(&lib, &output);
let relative = path_relative_from(&lib, &output)
.expect(&format!("couldn't create relative path from {:?} to {:?}", output, lib));
// FIXME (#9639): This needs to handle non-utf8 paths
format!("{}/{}", prefix,
relative.to_str().expect("non-utf8 component in path"))
}

fn relativize(path: &Path, rel: &Path) -> PathBuf {
let mut res = PathBuf::new("");
let mut cur = rel;
while !path.starts_with(cur) {
res.push("..");
match cur.parent() {
Some(p) => cur = p,
None => panic!("can't create relative paths across filesystems"),
// This routine is adapted from the *old* Path's `path_relative_from`
// function, which works differently from the new `relative_from` function.
// In particular, this handles the case on unix where both paths are
// absolute but with only the root as the common directory.
fn path_relative_from(path: &Path, base: &Path) -> Option<PathBuf> {
use std::path::Component;

if path.is_absolute() != base.is_absolute() {
if path.is_absolute() {
Some(PathBuf::new(path))
} else {
None
}
} else {
let mut ita = path.components();
let mut itb = base.components();
let mut comps: Vec<Component> = vec![];
loop {
match (ita.next(), itb.next()) {
(None, None) => break,
(Some(a), None) => {
comps.push(a);
comps.extend(ita.by_ref());
break;
}
(None, _) => comps.push(Component::ParentDir),
(Some(a), Some(b)) if comps.is_empty() && a == b => (),
(Some(a), Some(b)) if b == Component::CurDir => comps.push(a),
(Some(_), Some(b)) if b == Component::ParentDir => return None,
(Some(a), Some(_)) => {
comps.push(Component::ParentDir);
for _ in itb {
comps.push(Component::ParentDir);
}
comps.push(a);
comps.extend(ita.by_ref());
break;
}
}
}
Some(comps.iter().map(|c| c.as_os_str()).collect())
}
match path.relative_from(cur) {
Some(s) => { res.push(s); res }
None => panic!("couldn't create relative path from {:?} to {:?}",
rel, path),
}

}


fn get_install_prefix_rpath(config: &mut RPathConfig) -> String {
let path = (config.get_install_prefix_lib_path)();
let path = env::current_dir().unwrap().join(&path);
Expand Down
3 changes: 3 additions & 0 deletions src/libstd/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1243,6 +1243,9 @@ impl Path {
}

/// Returns a path that, when joined onto `base`, yields `self`.
///
/// If `base` is not a prefix of `self` (i.e. `starts_with`
/// returns false), then `relative_from` returns `None`.
#[unstable(feature = "path_relative_from", reason = "see #23284")]
pub fn relative_from<'a, P: ?Sized>(&'a self, base: &'a P) -> Option<&Path> where
P: AsPath
Expand Down

0 comments on commit e98d4d9

Please sign in to comment.