coliru

A minimal, flexible, dotfile installer
git clone https://git.ashermorgan.net/coliru/
Log | Files | Refs | README

commit 9c7272ccc935f78d7b9aa0be5dcbe4ce717dae31
parent 4f6bc1c3897db4caff16f82512f46cbb7ec877e8
Author: Asher Morgan <59518073+ashermorgan@users.noreply.github.com>
Date:   Mon, 17 Jun 2024 14:55:14 -0700

Implement parse_manifest_file function

Diffstat:
MCargo.lock | 112+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MCargo.toml | 2++
Aexamples/1.yml | 14++++++++++++++
Aexamples/2.yml | 14++++++++++++++
Msrc/main.rs | 4+++-
Asrc/manifest.rs | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 229 insertions(+), 1 deletion(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -5,3 +5,115 @@ version = 3 [[package]] name = "coliru" version = "0.0.0" +dependencies = [ + "serde", + "serde_yaml", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "proc-macro2" +version = "1.0.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "serde" +version = "1.0.203" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.203" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + +[[package]] +name = "syn" +version = "2.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" diff --git a/Cargo.toml b/Cargo.toml @@ -4,3 +4,5 @@ version = "0.0.0" edition = "2021" [dependencies] +serde = { version = "1.0", features = ["derive"] } +serde_yaml = "0.9" diff --git a/examples/1.yml b/examples/1.yml @@ -0,0 +1,14 @@ +# Invalid manifest + +steps: + - not_copy: + - src: foo + dst: ~/foo + - src: bar + dst: ~/test/bar + tags: [ a, b ] + + - copy: + - not_src: baz + dst: /baz + tags: [ b, c ] diff --git a/examples/2.yml b/examples/2.yml @@ -0,0 +1,14 @@ +# Valid manifest + +steps: + - copy: + - src: foo + dst: ~/foo + - src: bar + dst: ~/test/bar + tags: [ a, b ] + + - copy: + - src: baz + dst: /baz + tags: [ b, c ] diff --git a/src/main.rs b/src/main.rs @@ -1,3 +1,5 @@ +mod manifest; +mod tags; + fn main() { - println!("Hello, world!"); } diff --git a/src/manifest.rs b/src/manifest.rs @@ -0,0 +1,84 @@ +use serde::{Serialize, Deserialize}; +use serde_yaml; +use std::fs::read_to_string; +use std::path::{Path, PathBuf}; + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +pub struct CopyOptions { + src: PathBuf, + dst: PathBuf, +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +pub struct Step { + copy: Vec<CopyOptions>, + tags: Vec<String>, +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +pub struct Manifest { + steps: Vec<Step>, +} + +/// Parse a coliru YAML manifest file +pub fn parse_manifest_file(path: &Path) -> Result<Manifest, String> { + match read_to_string(path) { + Ok(raw) => match serde_yaml::from_str::<Manifest>(&raw) { + Ok(result) => Ok(result), + Err(why) => Err(why.to_string()), + } + Err(why) => Err(why.to_string()), + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[cfg(target_os = "linux")] + #[test] + fn parse_manifest_file_missing() { + let expected = "No such file or directory (os error 2)"; + let actual = parse_manifest_file(Path::new("examples/0.yml")); + assert_eq!(actual, Err(String::from(expected))); + } + + #[test] + fn parse_manifest_file_invalid() { + let expected = "steps[0]: missing field `copy` at line 4 column 5"; + let actual = parse_manifest_file(Path::new("examples/1.yml")); + assert_eq!(actual, Err(String::from(expected))); + } + + #[test] + fn parse_manifest_file_valid() { + let expected = Manifest { + steps: vec![ + Step { + copy: vec![ + CopyOptions{ + src: PathBuf::from("foo"), + dst: PathBuf::from("~/foo") + }, + CopyOptions{ + src: PathBuf::from("bar"), + dst: PathBuf::from("~/test/bar") + }, + ], + tags: vec![String::from("a"), String::from("b")], + }, + Step { + copy: vec![ + CopyOptions{ + src: PathBuf::from("baz"), + dst: PathBuf::from("/baz") + }, + ], + tags: vec![String::from("b"), String::from("c")], + } + ], + }; + let actual = parse_manifest_file(Path::new("examples/2.yml")); + assert_eq!(actual, Ok(expected)); + } +}