Skip to content

Commit

Permalink
std: Expand the area of std::fs
Browse files Browse the repository at this point in the history
This commit is an implementation of [RFC 1044][rfc] which adds additional
surface area to the `std::fs` module. All new APIs are `#[unstable]` behind
assorted feature names for each one.

[rfc]: rust-lang/rfcs#1044

The new APIs added are:

* `fs::canonicalize` - bindings to `realpath` on unix and
  `GetFinalPathNameByHandle` on windows.
* `fs::symlink_metadata` - similar to `lstat` on unix
* `fs::FileType` and accessor methods as `is_{file,dir,symlink}`
* `fs::Metadata::file_type` - accessor for the raw file type
* `fs::DirEntry::metadata` - acquisition of metadata which is free on Windows
  but requires a syscall on unix.
* `fs::DirEntry::file_type` - access the file type which may not require a
  syscall on most platforms.
* `fs::DirEntry::file_name` - access just the file name without leading
  components.
* `fs::PathExt::symlink_metadata` - convenience method for the top-level
  function.
* `fs::PathExt::canonicalize` - convenience method for the top-level
  function.
* `fs::PathExt::read_link` - convenience method for the top-level
  function.
* `fs::PathExt::read_dir` - convenience method for the top-level
  function.
* `std::os::raw` - type definitions for raw OS/C types available on all
  platforms.
* `std::os::$platform` - new modules have been added for all currently supported
  platforms (e.g. those more specific than just `unix`).
* `std::os::$platform::raw` - platform-specific type definitions. These modules
  are populated with the bare essentials necessary for lowing I/O types into
  their raw representations, and currently largely consist of the `stat`
  definition for unix platforms.

This commit also deprecates `Metadata::{modified, accessed}` in favor of
inspecting the raw representations via the lowering methods of `Metadata`.
  • Loading branch information
alexcrichton committed Apr 28, 2015
1 parent b772ce6 commit 9348700
Show file tree
Hide file tree
Showing 47 changed files with 2,404 additions and 914 deletions.
2 changes: 1 addition & 1 deletion src/librustc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#![feature(path_ext)]
#![feature(str_char)]
#![feature(into_cow)]
#![feature(fs_canonicalize)]
#![feature(slice_patterns)]
#![cfg_attr(test, feature(test))]

Expand Down Expand Up @@ -139,7 +140,6 @@ pub mod plugin;
pub mod lint;

pub mod util {
pub use rustc_back::fs;
pub use rustc_back::sha2;

pub mod common;
Expand Down
7 changes: 4 additions & 3 deletions src/librustc/metadata/creader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ use metadata::decoder;
use metadata::loader;
use metadata::loader::CratePaths;

use std::path::{Path, PathBuf};
use std::path::PathBuf;
use std::rc::Rc;
use std::fs;

use syntax::ast;
use syntax::abi;
use syntax::attr;
Expand All @@ -32,7 +34,6 @@ use syntax::parse;
use syntax::parse::token::InternedString;
use syntax::parse::token;
use syntax::visit;
use util::fs;
use log;

pub struct CrateReader<'a> {
Expand Down Expand Up @@ -322,7 +323,7 @@ impl<'a> CrateReader<'a> {
let source = self.sess.cstore.get_used_crate_source(cnum).unwrap();
if let Some(locs) = self.sess.opts.externs.get(name) {
let found = locs.iter().any(|l| {
let l = fs::realpath(&Path::new(&l[..])).ok();
let l = fs::canonicalize(l).ok();
source.dylib.as_ref().map(|p| &p.0) == l.as_ref() ||
source.rlib.as_ref().map(|p| &p.0) == l.as_ref()
});
Expand Down
3 changes: 1 addition & 2 deletions src/librustc/metadata/filesearch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ use std::fs;
use std::io::prelude::*;
use std::path::{Path, PathBuf};

use util::fs as myfs;
use session::search_paths::{SearchPaths, PathKind};

#[derive(Copy, Clone)]
Expand Down Expand Up @@ -191,7 +190,7 @@ pub fn get_or_default_sysroot() -> PathBuf {
// Follow symlinks. If the resolved path is relative, make it absolute.
fn canonicalize(path: Option<PathBuf>) -> Option<PathBuf> {
path.and_then(|path| {
match myfs::realpath(&path) {
match fs::canonicalize(&path) {
Ok(canon) => Some(canon),
Err(e) => panic!("failed to get realpath: {}", e),
}
Expand Down
10 changes: 5 additions & 5 deletions src/librustc/metadata/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,12 +225,12 @@ use metadata::encoder;
use metadata::filesearch::{FileSearch, FileMatches, FileDoesntMatch};
use syntax::codemap::Span;
use syntax::diagnostic::SpanHandler;
use util::fs;
use util::common;
use rustc_back::target::Target;

use std::cmp;
use std::collections::HashMap;
use std::fs;
use std::io::prelude::*;
use std::io;
use std::path::{Path, PathBuf};
Expand Down Expand Up @@ -430,9 +430,9 @@ impl<'a> Context<'a> {
.or_insert_with(|| (HashMap::new(), HashMap::new()));
let (ref mut rlibs, ref mut dylibs) = *slot;
if rlib {
rlibs.insert(fs::realpath(path).unwrap(), kind);
rlibs.insert(fs::canonicalize(path).unwrap(), kind);
} else {
dylibs.insert(fs::realpath(path).unwrap(), kind);
dylibs.insert(fs::canonicalize(path).unwrap(), kind);
}

FileMatches
Expand Down Expand Up @@ -660,10 +660,10 @@ impl<'a> Context<'a> {
// there's at most one rlib and at most one dylib.
for loc in locs {
if loc.file_name().unwrap().to_str().unwrap().ends_with(".rlib") {
rlibs.insert(fs::realpath(&loc).unwrap(),
rlibs.insert(fs::canonicalize(&loc).unwrap(),
PathKind::ExternFlag);
} else {
dylibs.insert(fs::realpath(&loc).unwrap(),
dylibs.insert(fs::canonicalize(&loc).unwrap(),
PathKind::ExternFlag);
}
}
Expand Down
91 changes: 0 additions & 91 deletions src/librustc_back/fs.rs

This file was deleted.

2 changes: 1 addition & 1 deletion src/librustc_back/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#![feature(path_ext)]
#![feature(step_by)]
#![feature(libc)]
#![feature(fs_canonicalize)]
#![cfg_attr(test, feature(test, rand))]

extern crate syntax;
Expand All @@ -53,7 +54,6 @@ pub mod abi;
pub mod archive;
pub mod tempdir;
pub mod arm;
pub mod fs;
pub mod mips;
pub mod mipsel;
pub mod rpath;
Expand Down
9 changes: 3 additions & 6 deletions src/librustc_back/rpath.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@

use std::collections::HashSet;
use std::env;
use std::io;
use std::path::{Path, PathBuf};
use std::fs;
use syntax::ast;

pub struct RPathConfig<'a> {
Expand All @@ -20,7 +20,6 @@ pub struct RPathConfig<'a> {
pub is_like_osx: bool,
pub has_rpath: bool,
pub get_install_prefix_lib_path: &'a mut FnMut() -> PathBuf,
pub realpath: &'a mut FnMut(&Path) -> io::Result<PathBuf>,
}

pub fn get_rpath_flags(config: &mut RPathConfig) -> Vec<String> {
Expand Down Expand Up @@ -95,11 +94,11 @@ fn get_rpath_relative_to_output(config: &mut RPathConfig, lib: &Path) -> String
};

let cwd = env::current_dir().unwrap();
let mut lib = (config.realpath)(&cwd.join(lib)).unwrap();
let mut lib = fs::canonicalize(&cwd.join(lib)).unwrap_or(cwd.join(lib));
lib.pop();
let mut output = cwd.join(&config.out_filename);
output.pop();
let output = (config.realpath)(&output).unwrap();
let output = fs::canonicalize(&output).unwrap_or(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
Expand Down Expand Up @@ -231,7 +230,6 @@ mod tests {
is_like_osx: true,
out_filename: PathBuf::from("bin/rustc"),
get_install_prefix_lib_path: &mut || panic!(),
realpath: &mut |p| Ok(p.to_path_buf()),
};
let res = get_rpath_relative_to_output(config,
Path::new("lib/libstd.so"));
Expand All @@ -243,7 +241,6 @@ mod tests {
get_install_prefix_lib_path: &mut || panic!(),
has_rpath: true,
is_like_osx: false,
realpath: &mut |p| Ok(p.to_path_buf()),
};
let res = get_rpath_relative_to_output(config,
Path::new("lib/libstd.so"));
Expand Down
38 changes: 32 additions & 6 deletions src/librustc_trans/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use std::ffi::OsString;
use std::fs::{self, PathExt};
use std::io::{self, Read, Write};
use std::mem;
use std::path::{Path, PathBuf};
use std::path::{self, Path, PathBuf};
use std::process::Command;
use std::str;
use flate;
Expand Down Expand Up @@ -916,8 +916,9 @@ fn link_args(cmd: &mut Command,
// stripped away as much as it could. This has not been seen to impact
// link times negatively.
//
// -dead_strip can't be part of the pre_link_args because it's also used for partial
// linking when using multiple codegen units (-r). So we insert it here.
// -dead_strip can't be part of the pre_link_args because it's also used
// for partial linking when using multiple codegen units (-r). So we
// insert it here.
cmd.arg("-Wl,-dead_strip");
}

Expand Down Expand Up @@ -1043,7 +1044,6 @@ fn link_args(cmd: &mut Command,
has_rpath: sess.target.target.options.has_rpath,
is_like_osx: sess.target.target.options.is_like_osx,
get_install_prefix_lib_path: &mut get_install_prefix_lib_path,
realpath: &mut ::util::fs::realpath
};
cmd.args(&rpath::get_rpath_flags(&mut rpath_config));
}
Expand Down Expand Up @@ -1258,7 +1258,7 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session,
}
});
} else {
cmd.arg(cratepath);
cmd.arg(&fix_windows_verbatim_for_gcc(cratepath));
}
}

Expand All @@ -1271,7 +1271,7 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session,
// Just need to tell the linker about where the library lives and
// what its name is
if let Some(dir) = cratepath.parent() {
cmd.arg("-L").arg(dir);
cmd.arg("-L").arg(&fix_windows_verbatim_for_gcc(dir));
}
let filestem = cratepath.file_stem().unwrap().to_str().unwrap();
cmd.arg(&format!("-l{}", unlib(&sess.target, filestem)));
Expand Down Expand Up @@ -1325,3 +1325,29 @@ fn add_upstream_native_libraries(cmd: &mut Command, sess: &Session) {
}
}
}

// Unfortunately, on windows, gcc cannot accept paths of the form `\\?\C:\...`
// (a verbatim path). This form of path is generally pretty rare, but the
// implementation of `fs::canonicalize` currently generates paths of this form,
// meaning that we're going to be passing quite a few of these down to gcc.
//
// For now we just strip the "verbatim prefix" of `\\?\` from the path. This
// will probably lose information in some cases, but there's not a whole lot
// more we can do with a buggy gcc...
fn fix_windows_verbatim_for_gcc(p: &Path) -> PathBuf {
if !cfg!(windows) {
return p.to_path_buf()
}
let mut components = p.components();
let prefix = match components.next() {
Some(path::Component::Prefix(p)) => p,
_ => return p.to_path_buf(),
};
let disk = match prefix.kind() {
path::Prefix::VerbatimDisk(disk) => disk,
_ => return p.to_path_buf(),
};
let mut base = OsString::from(format!("{}:", disk as char));
base.push(components.as_path());
PathBuf::from(base)
}
Loading

0 comments on commit 9348700

Please sign in to comment.