"registry 0.1.0",
"rustc-serialize 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"semver 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
- "tar 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tar 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"tempdir 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"term 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"threadpool 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "tar"
-version = "0.2.10"
+version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
[[package]]
name = "tempdir"
#![deny(unused)]
-#![feature(fs_time)]
+#![feature(metadata_ext)]
#![cfg_attr(test, deny(warnings))]
#[cfg(test)] extern crate hamcrest;
use std::path::{Path, PathBuf};
use core::{Package, Target, Profile};
-use util;
+use util::{self, MTime};
use util::{CargoResult, Fresh, Dirty, Freshness, internal, profile, ChainError};
use super::Kind;
#[derive(Clone)]
enum LocalFingerprint {
Precalculated(String),
- MtimeBased(Option<u64>, PathBuf),
+ MtimeBased(Option<MTime>, PathBuf),
}
impl Fingerprint {
LocalFingerprint::MtimeBased(Some(n), _) if !force => n.to_string(),
LocalFingerprint::MtimeBased(_, ref p) => {
debug!("resolving: {}", p.display());
- try!(fs::metadata(p)).modified().to_string()
+ try!(MTime::of(p)).to_string()
}
};
debug!("inputs: {} {} {:?}", known, self.extra, deps);
Ok(old_fingerprint == new_fingerprint)
}
-fn calculate_target_mtime(dep_info: &Path) -> CargoResult<Option<u64>> {
+fn calculate_target_mtime(dep_info: &Path) -> CargoResult<Option<MTime>> {
macro_rules! fs_try {
($e:expr) => (match $e { Ok(e) => e, Err(..) => return Ok(None) })
}
Some(Ok(line)) => line,
_ => return Ok(None),
};
- let mtime = try!(fs::metadata(dep_info)).modified();
+ let mtime = try!(MTime::of(dep_info));
let pos = try!(line.find(": ").chain_error(|| {
internal(format!("dep-info not in an understood format: {}",
dep_info.display()))
file.push(' ');
file.push_str(deps.next().unwrap())
}
- match fs::metadata(&cwd.join(&file)) {
- Ok(ref stat) if stat.modified() <= mtime => {}
- Ok(ref stat) => {
- info!("stale: {} -- {} vs {}", file, stat.modified(), mtime);
+ match MTime::of(&cwd.join(&file)) {
+ Ok(file_mtime) if file_mtime <= mtime => {}
+ Ok(file_mtime) => {
+ info!("stale: {} -- {} vs {}", file, file_mtime, mtime);
return Ok(None)
}
_ => { info!("stale: {} -- missing", file); return Ok(None) }
use core::{Package, PackageId, Summary, SourceId, Source, Dependency, Registry};
use ops;
-use util::{self, CargoResult, internal, internal_error, human, ChainError, Config};
+use util::{self, CargoResult, internal, internal_error, human, ChainError};
+use util::{MTime, Config};
pub struct PathSource<'a, 'b: 'a> {
id: SourceId,
return Err(internal_error("BUG: source was not updated", ""));
}
- let mut max = 0;
+ let mut max = MTime::zero();
for file in try!(self.list_files(pkg)).iter() {
// An fs::stat error here is either because path is a
// broken symlink, a permissions error, or a race
// condition where this path was rm'ed - either way,
// we can ignore the error and treat the path's mtime
// as 0.
- let mtime = fs::metadata(&file).map(|s| s.modified()).unwrap_or(0);
+ let mtime = MTime::of(&file).unwrap_or(MTime::zero());
warn!("{} {}", mtime, file.display());
max = cmp::max(max, mtime);
}
pub use self::to_semver::ToSemver;
pub use self::vcs::{GitRepo, HgRepo};
pub use self::sha256::Sha256;
+pub use self::mtime::MTime;
pub mod config;
pub mod errors;
mod dependency_queue;
mod sha256;
mod vcs;
+mod mtime;
--- /dev/null
+use std::fmt;
+use std::fs;
+use std::io;
+use std::path::Path;
+
+/// A helper structure to represent the modification time of a file.
+///
+/// The actual value contined within is platform-specific and does not have the
+/// same meaning across platforms, but comparisons and stringification can be
+/// significant among platforms.
+#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Copy, Clone)]
+pub struct MTime {
+ seconds: u64,
+ nanos: u32,
+}
+
+impl MTime {
+ pub fn zero() -> MTime {
+ MTime { seconds: 0, nanos: 0 }
+ }
+
+ pub fn of(p: &Path) -> io::Result<MTime> {
+ let metadata = try!(fs::metadata(p));
+ Ok(MTime::from(&metadata))
+ }
+}
+
+impl<'a> From<&'a fs::Metadata> for MTime {
+ #[cfg(unix)]
+ fn from(meta: &'a fs::Metadata) -> MTime {
+ use std::os::unix::prelude::*;
+ let raw = meta.as_raw();
+ // FIXME: currently there is a bug in the standard library where the
+ // nanosecond accessor is just accessing the seconds again, once
+ // that bug is fixed this should take nanoseconds into account.
+ MTime { seconds: raw.mtime() as u64, nanos: 0 }
+ }
+
+ #[cfg(windows)]
+ fn from(meta: &'a fs::Metadata) -> MTime {
+ use std::os::windows::prelude::*;
+
+ // Windows write times are in 100ns intervals, so do a little math to
+ // get it into the right representation.
+ let time = meta.last_write_time();
+ MTime {
+ seconds: time / (1_000_000_000 / 100),
+ nanos: ((time % (1_000_000_000 / 100)) * 100) as u32,
+ }
+ }
+}
+
+impl fmt::Display for MTime {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}.{:09}s", self.seconds, self.nanos)
+ }
+}