diff options
-rw-r--r-- | readme.md | 9 | ||||
-rw-r--r-- | src/main.rs | 63 |
2 files changed, 38 insertions, 34 deletions
diff --git a/readme.md b/readme.md index 522ffe6..5345195 100644 --- a/readme.md +++ b/readme.md @@ -14,4 +14,11 @@ varying ways to make a CSV, it's described in detail below. - `mtime`: time file was last modified - `atime`: time file was last accessed - if the `path` contains a comma (`,`) or a backslash (`\`), it is escape with a backslash -- if any one of the time cannot be attained, the field is left empty. \ No newline at end of file +- if any one of the time cannot be attained, the field is left empty. + +**behavior:** +prints a row for the current directory, a row for each file, and +then goes into each directory recursively. + +this results in reading the directory twice as to not cache the +directory listings in memory. \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index f49422d..0dc9899 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,28 +5,19 @@ use std::{ use camino::{Utf8Path, Utf8PathBuf}; -// CSV definition: -// a row may contain any data, but comma are escaped with a backslash -// and blackslash are escaped, too. there is no header. if a time -// cannot be attained due to an error, it is left blank -// data is in the format: path, creation-time, modification-time -// the path is relative to the given path - fn main() { // currently only accepts one argument, the path to the directory it will // recurse through and make the csv for. // spits the csv on stdout let path: Utf8PathBuf = std::env::args().nth(1).unwrap().parse().unwrap(); - - // behavior: - // reads directories twice. we're trying to be memory efficient rather than - // computationally. i'm not quite sure why. - // first pass: read and output file information - // second pass: read and outut directory information process(&path, &path) } +/// Loop through the provided directory printing CSV rows. The `root_path` is +/// used to make printed paths relative to it. +/// +/// Does two passes: First pass prints files. Second pass recurs, printing directories. fn process(root_path: &Utf8Path, path: &Utf8Path) { //TODO: do not panic, please let this_meta = std::fs::metadata(&path).unwrap(); @@ -59,26 +50,27 @@ fn process(root_path: &Utf8Path, path: &Utf8Path) { } fn row<P: AsRef<Utf8Path>>(root: &Utf8Path, path: P, times: &Times) { - let relative = path.as_ref().strip_prefix(root).unwrap(); + let relative = path + .as_ref() + .strip_prefix(root) + .expect("row wasn't relative to the root; what happened?"); + + /// Returns an owned string with the duration formatted as seconds, or a + /// borrowed empty string + fn time_string(time: Option<Duration>) -> String { + time.map(|d| d.as_secs().to_string()).unwrap_or_default() + } println!( "{},{},{},{}", escape(relative), - times - .created() - .map(|d| d.as_secs().to_string()) - .unwrap_or_default(), - times - .modified() - .map(|d| d.as_secs().to_string()) - .unwrap_or_default(), - times - .accessed() - .map(|d| d.as_secs().to_string()) - .unwrap_or_default() + time_string(times.created()), + time_string(times.modified()), + time_string(times.accessed()) ); } +/// Blackslash-escape comma and backslash fn escape<S: AsRef<str>>(raw: S) -> String { let raw = raw.as_ref(); @@ -103,6 +95,8 @@ struct Times { } impl Times { + /// Get the btime, mtime, atime from the Metadata. If a time cannot + /// be attained, leave a None in it's place pub fn metadata(meta: &Metadata) -> Self { Self { created: meta.created().ok(), @@ -111,19 +105,22 @@ impl Times { } } - // EPOCH created + /// The time since the Unix Epoch the file was created pub fn created(&self) -> Option<Duration> { - self.created - .map(|st| st.duration_since(SystemTime::UNIX_EPOCH).unwrap()) + Self::from_epoch(self.created.as_ref()) } + /// The time since the Unix Epoch the file was last modified pub fn modified(&self) -> Option<Duration> { - self.modified - .map(|st| st.duration_since(SystemTime::UNIX_EPOCH).unwrap()) + Self::from_epoch(self.modified.as_ref()) } + /// The time since the Unix Epoch the file was last accessed pub fn accessed(&self) -> Option<Duration> { - self.accessed - .map(|st| st.duration_since(SystemTime::UNIX_EPOCH).unwrap()) + Self::from_epoch(self.accessed.as_ref()) + } + + fn from_epoch(maybe_time: Option<&SystemTime>) -> Option<Duration> { + maybe_time.map(|st| st.duration_since(SystemTime::UNIX_EPOCH).unwrap()) } } |