shtola

ssg in rust
git clone https://tilde.team/~marisa/repo/shtola.git
Log | Files | Refs | LICENSE

commit 45bf7a260bf2258801f7b87d1c6982af37fd14f0
parent 0cd309e12a696fdf847dd2389f95e428c52a60fc
Author: marisa <mokou@posteo.de>
Date:   Wed, 27 Nov 2019 14:56:46 +0100

Add logging support for shtola

Diffstat:
MCargo.lock | 112+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mshtola-markdown/src/lib.rs | 5++++-
Mshtola/Cargo.toml | 3+++
Ashtola/examples/simple.rs | 28++++++++++++++++++++++++++++
Mshtola/src/lib.rs | 30+++++++++++++++++++++++++++---
5 files changed, 174 insertions(+), 4 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -26,6 +26,11 @@ dependencies = [ ] [[package]] +name = "autocfg" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "bitflags" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -73,6 +78,16 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "chrono" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "clap" version = "2.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -121,6 +136,18 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "env_logger" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "fake-simd" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -151,6 +178,14 @@ dependencies = [ ] [[package]] +name = "humantime" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "im" version = "13.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -199,6 +234,23 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "num-integer" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-traits" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "opaque-debug" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -248,6 +300,16 @@ dependencies = [ ] [[package]] +name = "pretty_env_logger" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "proc-macro2" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -256,6 +318,11 @@ dependencies = [ ] [[package]] +name = "quick-error" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "quote" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -264,6 +331,11 @@ dependencies = [ ] [[package]] +name = "redox_syscall" +version = "0.1.56" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "regex" version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -358,6 +430,7 @@ dependencies = [ "im 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "pathdiff 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pretty_env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -396,6 +469,14 @@ dependencies = [ ] [[package]] +name = "termcolor" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "textwrap" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -412,6 +493,16 @@ dependencies = [ ] [[package]] +name = "time" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "twoway" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -507,6 +598,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "wincolor" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "yaml-rust" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -518,6 +618,7 @@ dependencies = [ "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" +"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" "checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" "checksum block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" @@ -525,15 +626,18 @@ dependencies = [ "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +"checksum chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "31850b4a4d6bae316f7a09e691c944c28299298837edc0a03f755618c23cbc01" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum comrak 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ea4c29f52463abf5c7a3ae33dd9b404e2031af82f547cfe65bfac17ba785ea2e" "checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" "checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e" "checksum entities 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b5320ae4c3782150d900b79807611a59a99fc9a1d61d686faafc24b93fc8d7ca" +"checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" "checksum globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "925aa2cac82d8834e2b2a4415b6f6879757fb5c0928fc445ae76461a12eed8f2" +"checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" "checksum im 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8db49f8bc08d5cc4e2bb0f7d25a6d1db2c79bc6f7d7c86c96c657eb3d214125f" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" @@ -542,14 +646,19 @@ dependencies = [ "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" +"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" +"checksum num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4" "checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" "checksum pathdiff 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a3bf70094d203e07844da868b634207e71bfab254fe713171fae9a6e751ccf31" "checksum pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e4fb201c5c22a55d8b24fef95f78be52738e5e1361129be1b5e862ecdb6894a" "checksum pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" "checksum pest_generator 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9fcf299b5712d06ee128a556c94709aaa04512c4dffb8ead07c5c998447fc0" "checksum pest_meta 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "df43fd99896fd72c485fe47542c7b500e4ac1e8700bf995544d1317a60ded547" +"checksum pretty_env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "717ee476b1690853d222af4634056d830b5197ffd747726a9a1eee6da9f49074" "checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" +"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" +"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" "checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" "checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" @@ -564,8 +673,10 @@ dependencies = [ "checksum sized-chunks 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f01db57d7ee89c8e053245deb77040a6cc8508311f381c88749c33d4b9b78785" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" "checksum syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "661641ea2aa15845cddeb97dad000d22070bb5c1fb456b96c1cba883ec691e92" +"checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" +"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" "checksum twoway 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6b40075910de3a912adbd80b5d8bad6ad10a23eeb1f5bf9d4006839e899ba5bc" "checksum typed-arena 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9b2228007eba4120145f785df0f6c92ea538f5a3635a612ecf4e334c8c1446d" "checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" @@ -581,4 +692,5 @@ dependencies = [ "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +"checksum wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96f5016b18804d24db43cebf3c77269e7569b8954a8464501c216cc5e070eaa9" "checksum yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d" diff --git a/shtola-markdown/src/lib.rs b/shtola-markdown/src/lib.rs @@ -44,5 +44,8 @@ fn it_works() { s.register(plugin()); let r = s.build().unwrap(); let file: &ShFile = r.files.get(&PathBuf::from("hello.html")).unwrap(); - assert_eq!(std::str::from_utf8(&file.content).unwrap(), "<h1>Hello!</h1>\n<p>What's going <em>on</em>?</p>\n") + assert_eq!( + std::str::from_utf8(&file.content).unwrap(), + "<h1>Hello!</h1>\n<p>What's going <em>on</em>?</p>\n" + ) } diff --git a/shtola/Cargo.toml b/shtola/Cargo.toml @@ -19,3 +19,6 @@ pathdiff = "0.1.0" globset = "0.4.4" serde_json = "1.0.41" serde_yaml = "0.8.11" + +[dev_dependencies] +pretty_env_logger = "0.3.1" diff --git a/shtola/examples/simple.rs b/shtola/examples/simple.rs @@ -0,0 +1,28 @@ +use shtola::{HashMap, ShFile, Shtola, IR}; +use std::path::PathBuf; + +fn main() { + pretty_env_logger::init(); + let mut s = Shtola::new(); + s.source("fixtures/simple"); + s.destination("fixtures/dest_write"); + s.clean(true); + let mw = Box::new(|ir: IR| { + let mut update_hash: HashMap<PathBuf, ShFile> = HashMap::new(); + for (k, v) in &ir.files { + update_hash.insert( + k.into(), + ShFile { + frontmatter: v.frontmatter.clone(), + content: "hello".into(), + }, + ); + } + IR { + files: update_hash.union(ir.files), + ..ir + } + }); + s.register(mw); + s.build().unwrap(); +} diff --git a/shtola/src/lib.rs b/shtola/src/lib.rs @@ -27,7 +27,8 @@ //! } //! ``` -use globset::{Glob, GlobSetBuilder, GlobSet}; +use globset::{Glob, GlobSet, GlobSetBuilder}; +use log::{debug, info, trace}; use pathdiff::diff_paths; use serde_json::json; use std::default::Default; @@ -37,6 +38,7 @@ use std::path::PathBuf; use walkdir::WalkDir; pub use im::HashMap; +pub use log; pub use serde_json as json; pub use ware::Ware; @@ -123,8 +125,13 @@ impl Shtola { /// - Runs the middleware chain, executing all plugins /// - Writes the result back to the destination directory pub fn build(&mut self) -> Result<IR, std::io::Error> { + info!("Starting Shtola"); + trace!("Starting IR config: {:?}", self.ir.config); if self.ir.config.clean { + info!("Cleaning before build..."); + debug!("Removing {:?}", &self.ir.config.destination); fs::remove_dir_all(&self.ir.config.destination)?; + debug!("Recreating {:?}", &self.ir.config.destination); fs::create_dir_all(&self.ir.config.destination) .expect("Unable to recreate destination directory!"); } @@ -133,12 +140,19 @@ impl Shtola { for item in &self.ir.config.ignores { builder.add(Glob::new(item).unwrap()); } + trace!("Globs: {:?}", &builder); let set = builder.build().unwrap(); + trace!("Globset: {:?}", &set); + info!("Reading files..."); let files = read_dir(&self.ir.config.source, self.ir.config.frontmatter, set)?; + trace!("Files: {:?}", &files); self.ir.files = files; + info!("Running plugins..."); let result_ir = self.ware.run(self.ir.clone()); + trace!("Result IR: {:?}", &result_ir); write_dir(result_ir.clone(), &self.ir.config.destination)?; + info!("Build done!"); Ok(result_ir) } } @@ -211,7 +225,10 @@ impl ShFile { /// } /// ``` pub fn empty() -> ShFile { - ShFile { frontmatter: json!(null), content: Vec::new() } + ShFile { + frontmatter: json!(null), + content: Vec::new(), + } } } @@ -225,6 +242,7 @@ fn read_dir( .into_iter() .filter_entry(|e| { let path = diff_paths(e.path(), source).unwrap(); + trace!("Read Filter: {:?} matches? {}", &path, set.is_match(&path)); !set.is_match(path) }) .filter(|e| !e.as_ref().ok().unwrap().file_type().is_dir()); @@ -233,9 +251,14 @@ fn read_dir( let path = entry.path(); let file: ShFile; let mut content = String::new(); + debug!("Reading file at {:?}", &path); fs::File::open(path)?.read_to_string(&mut content)?; if frontmatter { let (matter, content) = frontmatter::lexer(&content); + if matter.len() > 0 { + debug!("Lexing frontmatter for {:?}", &path); + trace!("Frontmatter: {:?}", &matter); + } let json = frontmatter::to_json(&matter); file = ShFile { frontmatter: json, @@ -255,7 +278,8 @@ fn read_dir( fn write_dir(ir: IR, dest: &PathBuf) -> Result<(), std::io::Error> { for (path, file) in ir.files { - let dest_path = dest.join(path); + let dest_path = dest.join(&path); + debug!("Writing {:?} to {:?}", &path, &dest_path); fs::create_dir_all(dest_path.parent().unwrap()) .expect("Unable to create destination subdirectory!"); fs::File::create(dest_path)?.write_all(&file.content)?;