From f88bc8e727141cf90b5053d92cf3b3a84d88ae59 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Sat, 28 Nov 2020 14:08:28 +0200 Subject: refactor: split into library and program --- src/bin/summain.rs | 27 +++++++++++++++++++++ src/lib.rs | 43 ++++++++++++++++++++++++++++++++++ src/main.rs | 69 ------------------------------------------------------ 3 files changed, 70 insertions(+), 69 deletions(-) create mode 100644 src/bin/summain.rs delete mode 100644 src/main.rs diff --git a/src/bin/summain.rs b/src/bin/summain.rs new file mode 100644 index 0000000..f25b857 --- /dev/null +++ b/src/bin/summain.rs @@ -0,0 +1,27 @@ +use anyhow::Context; +use std::fs::symlink_metadata; +use std::path::{Path, PathBuf}; +use structopt::StructOpt; +use summain::Entry; + +fn main() -> anyhow::Result<()> { + let mut opt = Opt::from_args(); + opt.pathnames[..].sort(); + for pathname in opt.pathnames { + report(&pathname).with_context(|| format!("{}", pathname.display()))? + } + Ok(()) +} + +#[derive(StructOpt, Debug)] +struct Opt { + #[structopt(parse(from_os_str))] + pathnames: Vec, +} + +fn report(pathname: &Path) -> anyhow::Result<()> { + let m = symlink_metadata(pathname)?; + let e = Entry::new(pathname, m); + println!("{}", serde_yaml::to_string(&e)?); + Ok(()) +} diff --git a/src/lib.rs b/src/lib.rs index 8b13789..bdf5bed 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1 +1,44 @@ +use serde::Serialize; +use std::fs::Metadata; +use std::os::linux::fs::MetadataExt; +use std::path::{Path, PathBuf}; +#[derive(Serialize, Debug)] +pub struct Entry { + path: PathBuf, + atime: i64, + atime_nsec: i64, + #[serde(with = "mode")] + mode: u32, + mtime: i64, + mtime_nsec: i64, + nlink: u64, + size: Option, +} + +impl Entry { + pub fn new(path: &Path, m: Metadata) -> Self { + Self { + path: path.to_path_buf(), + atime: m.st_atime(), + atime_nsec: m.st_atime_nsec(), + mode: m.st_mode(), + mtime: m.st_mtime(), + mtime_nsec: m.st_mtime_nsec(), + nlink: m.st_nlink(), + size: if m.is_dir() { None } else { Some(m.st_size()) }, + } + } +} + +mod mode { + use serde::{self, Serializer}; + + pub fn serialize(mode: &u32, serializer: S) -> Result + where + S: Serializer, + { + let s = unix_mode::to_string(*mode); + serializer.serialize_str(&s) + } +} diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index fd23eb8..0000000 --- a/src/main.rs +++ /dev/null @@ -1,69 +0,0 @@ -use anyhow::Context; -use serde::Serialize; -use std::fs::symlink_metadata; -use std::fs::Metadata; -use std::os::linux::fs::MetadataExt; -use std::path::{Path, PathBuf}; -use structopt::StructOpt; - -fn main() -> anyhow::Result<()> { - let mut opt = Opt::from_args(); - opt.pathnames[..].sort(); - for pathname in opt.pathnames { - report(&pathname).with_context(|| format!("{}", pathname.display()))? - } - Ok(()) -} - -#[derive(StructOpt, Debug)] -struct Opt { - #[structopt(parse(from_os_str))] - pathnames: Vec, -} - -#[derive(Serialize, Debug)] -struct Entry { - path: PathBuf, - atime: i64, - atime_nsec: i64, - #[serde(with = "mode")] - mode: u32, - mtime: i64, - mtime_nsec: i64, - nlink: u64, - size: Option, -} - -impl Entry { - fn new(path: &Path, m: Metadata) -> Self { - Self { - path: path.to_path_buf(), - atime: m.st_atime(), - atime_nsec: m.st_atime_nsec(), - mode: m.st_mode(), - mtime: m.st_mtime(), - mtime_nsec: m.st_mtime_nsec(), - nlink: m.st_nlink(), - size: if m.is_dir() { None } else { Some(m.st_size()) }, - } - } -} - -fn report(pathname: &Path) -> anyhow::Result<()> { - let m = symlink_metadata(pathname)?; - let e = Entry::new(pathname, m); - println!("{}", serde_yaml::to_string(&e)?); - Ok(()) -} - -mod mode { - use serde::{self, Serializer}; - - pub fn serialize(mode: &u32, serializer: S) -> Result - where - S: Serializer, - { - let s = unix_mode::to_string(*mode); - serializer.serialize_str(&s) - } -} -- cgit v1.2.1 From 93a26490391605a2edeacec06f84b2463d31b0d6 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Sat, 28 Nov 2020 14:30:48 +0200 Subject: doc: add doc comments Also, rename struct to ManifestEntry. --- src/bin/summain.rs | 4 ++-- src/lib.rs | 44 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/bin/summain.rs b/src/bin/summain.rs index f25b857..056bc8b 100644 --- a/src/bin/summain.rs +++ b/src/bin/summain.rs @@ -2,7 +2,7 @@ use anyhow::Context; use std::fs::symlink_metadata; use std::path::{Path, PathBuf}; use structopt::StructOpt; -use summain::Entry; +use summain::ManifestEntry; fn main() -> anyhow::Result<()> { let mut opt = Opt::from_args(); @@ -21,7 +21,7 @@ struct Opt { fn report(pathname: &Path) -> anyhow::Result<()> { let m = symlink_metadata(pathname)?; - let e = Entry::new(pathname, m); + let e = ManifestEntry::new(pathname, m); println!("{}", serde_yaml::to_string(&e)?); Ok(()) } diff --git a/src/lib.rs b/src/lib.rs index bdf5bed..eacce62 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,10 +1,44 @@ +//! File manifests. +//! +//! This crate defines the [`ManifestEntry`] struct to represent an +//! entry in a file manifest. The entry contains data about each file. +//! A manifest can be produced of some data, and later, a new manifest +//! can be produced and compared with the original. If the manifests +//! have changed, the data has changed. If they haven't changed, the +//! data has probably not changed. +//! +//! Such manifests can be used, for example, to verify that data that +//! has been restored from a backup is the same as what was backed up. +//! +//! This crate uses Linux metadata of files. +//! +//! ~~~ +//! let m = std::fs::metadata(".").unwrap(); +//! let e = summain::ManifestEntry(m); +//! println!("{}", serde_yaml::to_string(e).unwrap()); +//! ~~~ +//! +//! The output is something like: +//! +//! ~~~yaml +//! path: "." +//! atime: 1606565868 +//! atime_nsec: 824368155 +//! mode: drwxrwxr-x +//! mtime: 1606565867 +//! mtime_nsec: 500355545 +//! nlink: 6 +//! size: ~ +//! ~~~ + use serde::Serialize; use std::fs::Metadata; use std::os::linux::fs::MetadataExt; use std::path::{Path, PathBuf}; +/// An entry in a file manifest. #[derive(Serialize, Debug)] -pub struct Entry { +pub struct ManifestEntry { path: PathBuf, atime: i64, atime_nsec: i64, @@ -16,7 +50,13 @@ pub struct Entry { size: Option, } -impl Entry { +impl ManifestEntry { + /// Create a new manifest entry. + /// + /// The pathname of the file and the metadata are passed in by the + /// caller. This function doesn't query the system for it. + /// + /// The structure can be serialized using serde. pub fn new(path: &Path, m: Metadata) -> Self { Self { path: path.to_path_buf(), -- cgit v1.2.1