From e469367d1fd852a03ba5ab0c47d8dd261291559a Mon Sep 17 00:00:00 2001 From: Nan Jiang Date: Wed, 13 Jun 2018 16:08:15 -0400 Subject: [PATCH] workaround unc path on windows --- Cargo.toml | 2 +- src/lib.rs | 1 + src/manager.rs | 28 +++++++++++++++++++++++++--- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b0f9b585..4f3e2272 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,8 +18,8 @@ lazy_static = "1.0" lmdb = "0.7" ordered-float = "0.5" uuid = "0.5" - serde = "1.0" +url = "1.7.0" # Get rid of failure's dependency on backtrace. Eventually # backtrace will move into Rust core, but we don't need it here. diff --git a/src/lib.rs b/src/lib.rs index 87b56eb0..54fbcade 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,6 +19,7 @@ extern crate lmdb; extern crate ordered_float; extern crate serde; // So we can specify trait bounds. Everything else is bincode. extern crate uuid; +extern crate url; pub use lmdb::{ DatabaseFlags, diff --git a/src/manager.rs b/src/manager.rs index ef7a78ea..e7c51434 100644 --- a/src/manager.rs +++ b/src/manager.rs @@ -12,6 +12,12 @@ use std::collections::{ BTreeMap, }; +use std::io::{ + self, + Error, + ErrorKind, +}; + use std::collections::btree_map::{ Entry, }; @@ -30,6 +36,8 @@ use std::sync::{ RwLock, }; +use url::Url; + use error::{ StoreError, }; @@ -44,6 +52,20 @@ lazy_static! { }; } +// Workaround the UNC path on Windows, see https://github.com/rust-lang/rust/issues/42869. +// Otherwise, `Env::from_env()` will panic with error_no(123). +fn canonicalize_path<'p, P>(path: P) -> io::Result +where P: Into<&'p Path> { + let canonical = path.into().canonicalize()?; + if cfg!(target_os = "windows") { + let url = Url::from_file_path(&canonical) + .map_err(|_e| Error::new(ErrorKind::Other, "URL passing error"))?; + return url.to_file_path() + .map_err(|_e| Error::new(ErrorKind::Other, "path canonicalization error")); + } + Ok(canonical) +} + pub struct Manager { environments: BTreeMap>>, } @@ -62,7 +84,7 @@ impl Manager { /// Return the open env at `path`, returning `None` if it has not already been opened. pub fn get<'p, P>(&self, path: P) -> Result>>, ::std::io::Error> where P: Into<&'p Path> { - let canonical = path.into().canonicalize()?; + let canonical = canonicalize_path(path)?; Ok(self.environments.get(&canonical).cloned()) } @@ -70,7 +92,7 @@ impl Manager { pub fn get_or_create<'p, F, P>(&mut self, path: P, f: F) -> Result>, StoreError> where F: FnOnce(&Path) -> Result, P: Into<&'p Path> { - let canonical = path.into().canonicalize()?; + let canonical = canonicalize_path(path)?; Ok(match self.environments.entry(canonical) { Entry::Occupied(e) => e.get().clone(), Entry::Vacant(e) => { @@ -85,7 +107,7 @@ impl Manager { pub fn get_or_create_with_capacity<'p, F, P>(&mut self, path: P, capacity: c_uint, f: F) -> Result>, StoreError> where F: FnOnce(&Path, c_uint) -> Result, P: Into<&'p Path> { - let canonical = path.into().canonicalize()?; + let canonical = canonicalize_path(path)?; Ok(match self.environments.entry(canonical) { Entry::Occupied(e) => e.get().clone(), Entry::Vacant(e) => {