about summary refs log tree commit diff
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs63
1 files changed, 30 insertions, 33 deletions
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())
 	}
 }