|
@@ -122,9 +122,10 @@ impl Status {
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
pub enum Error {
|
|
|
- /// Reqwest error (unable to connect), or IO Error std::io::Error
|
|
|
+ /// Reqwest error (unable to connect), or IO Error std::io::Error,
|
|
|
+ /// or std::net::Error.
|
|
|
ReqwestError(reqwest::Error),
|
|
|
- IOError(std::io::Error),
|
|
|
+ IOError(std::io::Error, String),
|
|
|
/// Content-Type wasn't allowed, see Cache.accept.
|
|
|
Unacceptable(String), // Content-Type
|
|
|
/// Content was too big, see Cache.max_size.
|
|
@@ -134,12 +135,14 @@ pub enum Error {
|
|
|
}
|
|
|
|
|
|
// This allows ? to return cache::Error from std::io::Error (see expire)
|
|
|
-
|
|
|
+// What about context information?
|
|
|
+/*
|
|
|
impl From<std::io::Error> for Error {
|
|
|
fn from(e: std::io::Error) -> Self {
|
|
|
Self::IOError(e)
|
|
|
}
|
|
|
}
|
|
|
+*/
|
|
|
|
|
|
impl From<reqwest::Error> for Error {
|
|
|
fn from(e: reqwest::Error) -> Self {
|
|
@@ -151,7 +154,7 @@ impl fmt::Display for Error {
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
match self {
|
|
|
Error::ReqwestError(e) => write!(f, "ReqwestError: {:?}", e),
|
|
|
- Error::IOError(e) => write!(f, "IOError: {:?}", e),
|
|
|
+ Error::IOError(e, context) => write!(f, " Context: {}\nIOError: {:?}", context, e),
|
|
|
Error::Unacceptable(ct) => write!(f, "Content-Type {} not allowed", ct),
|
|
|
Error::TooBig(size) => write!(f, "Content-Size {} too big", size),
|
|
|
Error::HttpErrorStatus(status) => write!(f, "Status Code: {}", status),
|
|
@@ -188,18 +191,21 @@ impl Cache {
|
|
|
if path.exists() {
|
|
|
if !path.is_dir() {
|
|
|
// It exists, but it isn't a directory! What?!
|
|
|
- return Err(Error::IOError(std::io::Error::new(
|
|
|
- std::io::ErrorKind::Other,
|
|
|
- format!(
|
|
|
- "Can't create Cache dir {}, it already exists.",
|
|
|
- dir.display()
|
|
|
+ return Err(Error::IOError(
|
|
|
+ std::io::Error::new(
|
|
|
+ std::io::ErrorKind::Other,
|
|
|
+ format!(
|
|
|
+ "Can't create Cache dir {}, it already exists.",
|
|
|
+ dir.display()
|
|
|
+ ),
|
|
|
),
|
|
|
- )));
|
|
|
+ dir.display().to_string(),
|
|
|
+ ));
|
|
|
}
|
|
|
} else {
|
|
|
match create_dir_all(path) {
|
|
|
Err(e) => {
|
|
|
- return Err(Error::IOError(e));
|
|
|
+ return Err(Error::IOError(e, path.display().to_string()));
|
|
|
}
|
|
|
Ok(_) => {}
|
|
|
}
|
|
@@ -289,59 +295,98 @@ impl Cache {
|
|
|
let now = SystemTime::now();
|
|
|
let mut result: bool = false;
|
|
|
|
|
|
- for file in read_dir(self.directory.as_path())? {
|
|
|
- let file = file?;
|
|
|
- if let Ok(d) = file.metadata() {
|
|
|
- if d.is_file() {
|
|
|
- // Created isn't updated if the file is fetched. Use modified, that updates on fetch.
|
|
|
-
|
|
|
- let filename = String::from(file.file_name().to_str().unwrap());
|
|
|
-
|
|
|
- if filename.ends_with(HEADER_EXT) {
|
|
|
- // This is a header cache file...
|
|
|
- if let Ok(modify) = d.modified() {
|
|
|
- if let Ok(delta) = now.duration_since(modify) {
|
|
|
- // println!("expire {} = modified {}", filename, delta.as_secs());
|
|
|
- if delta > age {
|
|
|
- // println!("Would delete: {} (and .content)", filename);
|
|
|
- let mut filepath = self.directory.join(filename);
|
|
|
- let r = remove_file(&filepath);
|
|
|
- if let Err(e) = r {
|
|
|
- println!("RemoveFile {:?}: {}", filepath, e);
|
|
|
+ if let Ok(files) = read_dir(self.directory.as_path()) {
|
|
|
+ for file in files {
|
|
|
+ if let Ok(file) = file {
|
|
|
+ if let Ok(d) = file.metadata() {
|
|
|
+ if d.is_file() {
|
|
|
+ // Created isn't updated if the file is fetched. Use modified, that updates on fetch.
|
|
|
+
|
|
|
+ let filename = String::from(file.file_name().to_str().unwrap());
|
|
|
+
|
|
|
+ if filename.ends_with(HEADER_EXT) {
|
|
|
+ // This is a header cache file...
|
|
|
+ if let Ok(modify) = d.modified() {
|
|
|
+ if let Ok(delta) = now.duration_since(modify) {
|
|
|
+ // println!("expire {} = modified {}", filename, delta.as_secs());
|
|
|
+ if delta > age {
|
|
|
+ // println!("Would delete: {} (and .content)", filename);
|
|
|
+ let mut filepath = self.directory.join(filename);
|
|
|
+ let r = remove_file(&filepath);
|
|
|
+ if let Err(e) = r {
|
|
|
+ println!("RemoveFile {:?}: {}", filepath, e);
|
|
|
+ }
|
|
|
+ // Also delete content file.
|
|
|
+ Self::remove_from_filename(&mut filepath);
|
|
|
+ let r = remove_file(&filepath);
|
|
|
+ if let Err(e) = r {
|
|
|
+ println!("RemoveFile {:?}: {}", filepath, e);
|
|
|
+ }
|
|
|
+
|
|
|
+ result = true;
|
|
|
+ }
|
|
|
}
|
|
|
- // Also delete content file.
|
|
|
- Self::remove_from_filename(&mut filepath);
|
|
|
- let r = remove_file(&filepath);
|
|
|
- if let Err(e) = r {
|
|
|
- println!("RemoveFile {:?}: {}", filepath, e);
|
|
|
- }
|
|
|
-
|
|
|
- result = true;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- if let Ok(access) = d.accessed() {
|
|
|
- if let Ok(delta) = now.duration_since(access) {
|
|
|
- println!("accessed {:?} = accessed {}", file.file_name(), delta.as_secs());
|
|
|
- if delta > age {
|
|
|
- println!("Expire: {:?}", file.file_name());
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+ for file in read_dir(self.directory.as_path()).ok() {
|
|
|
+ // if let file = file? {
|
|
|
+ // let file = file?;
|
|
|
+ if let Ok(d) = file.metadata() {
|
|
|
+ if d.is_file() {
|
|
|
+ // Created isn't updated if the file is fetched. Use modified, that updates on fetch.
|
|
|
+
|
|
|
+ let filename = String::from(file.file_name().to_str().unwrap());
|
|
|
+
|
|
|
+ if filename.ends_with(HEADER_EXT) {
|
|
|
+ // This is a header cache file...
|
|
|
+ if let Ok(modify) = d.modified() {
|
|
|
+ if let Ok(delta) = now.duration_since(modify) {
|
|
|
+ // println!("expire {} = modified {}", filename, delta.as_secs());
|
|
|
+ if delta > age {
|
|
|
+ // println!("Would delete: {} (and .content)", filename);
|
|
|
+ let mut filepath = self.directory.join(filename);
|
|
|
+ let r = remove_file(&filepath);
|
|
|
+ if let Err(e) = r {
|
|
|
+ println!("RemoveFile {:?}: {}", filepath, e);
|
|
|
+ }
|
|
|
+ // Also delete content file.
|
|
|
+ Self::remove_from_filename(&mut filepath);
|
|
|
+ let r = remove_file(&filepath);
|
|
|
+ if let Err(e) = r {
|
|
|
+ println!("RemoveFile {:?}: {}", filepath, e);
|
|
|
+ }
|
|
|
+
|
|
|
+ result = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ if let Ok(access) = d.accessed() {
|
|
|
+ if let Ok(delta) = now.duration_since(access) {
|
|
|
+ println!("accessed {:?} = accessed {}", file.file_name(), delta.as_secs());
|
|
|
+ if delta > age {
|
|
|
+ println!("Expire: {:?}", file.file_name());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- if let Ok(created) = d.created() {
|
|
|
- if let Ok(delta) = now.duration_since(created) {
|
|
|
- println!("expire {:?} = created {}", file.file_name(), delta.as_secs());
|
|
|
- if delta > age {
|
|
|
- println!("Would delete: {:?}", file.file_name());
|
|
|
- result = true;
|
|
|
+ if let Ok(created) = d.created() {
|
|
|
+ if let Ok(delta) = now.duration_since(created) {
|
|
|
+ println!("expire {:?} = created {}", file.file_name(), delta.as_secs());
|
|
|
+ if delta > age {
|
|
|
+ println!("Would delete: {:?}", file.file_name());
|
|
|
+ result = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ */
|
|
|
}
|
|
|
- }
|
|
|
- }
|
|
|
- */
|
|
|
+ */
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -417,7 +462,7 @@ impl Cache {
|
|
|
match remove_file(&base) {
|
|
|
Err(e) => {
|
|
|
// unlink failed
|
|
|
- return Err(Error::IOError(e));
|
|
|
+ return Err(Error::IOError(e, base.display().to_string()));
|
|
|
}
|
|
|
Ok(_) => {}
|
|
|
}
|
|
@@ -464,7 +509,7 @@ impl Cache {
|
|
|
}
|
|
|
}
|
|
|
Err(e) => {
|
|
|
- return Err(Error::IOError(e));
|
|
|
+ return Err(Error::IOError(e, header_file.to_string_lossy().to_string()));
|
|
|
}
|
|
|
}
|
|
|
};
|
|
@@ -519,7 +564,7 @@ impl Cache {
|
|
|
|
|
|
match save_headermap(header_file.to_str().unwrap(), url, result.headers()) {
|
|
|
Err(e) => {
|
|
|
- return Err(Error::IOError(e));
|
|
|
+ return Err(Error::IOError(e, header_file.to_string_lossy().to_string()));
|
|
|
}
|
|
|
Ok(()) => {}
|
|
|
}
|
|
@@ -532,7 +577,7 @@ impl Cache {
|
|
|
}
|
|
|
},
|
|
|
Err(e) => {
|
|
|
- return Err(Error::IOError(e));
|
|
|
+ return Err(Error::IOError(e, base.to_string_lossy().to_string()));
|
|
|
}
|
|
|
}
|
|
|
|