]>
Commit | Line | Data |
---|---|---|
1 | use std::fs::{copy, create_dir_all, read_dir, remove_dir_all, write}; | |
2 | use std::io::{Result, Error, ErrorKind}; | |
3 | use std::path::PathBuf; | |
4 | use super::{sync_down::SyncDown, generate::Generate, sync_up::SyncUp}; | |
5 | use crate::configuration::Configuration; | |
6 | use crate::constants::METADATA_FILENAME; | |
7 | use crate::metadata::Metadata; | |
8 | ||
9 | pub struct Update; | |
10 | ||
11 | impl Update { | |
12 | pub fn new() -> Self { | |
13 | Update | |
14 | } | |
15 | ||
16 | fn copy_post(&self, source: &PathBuf, target: &PathBuf) -> Result<()> { | |
17 | let post_name = source.file_name() | |
18 | .ok_or_else(|| Error::new(ErrorKind::InvalidInput, "Could not get post filename."))?; | |
19 | ||
20 | let target_post = target.join(post_name); | |
21 | copy(source, target_post)?; | |
22 | Ok(()) | |
23 | } | |
24 | ||
25 | fn write_metadata(&self, metadata: &Metadata, metadata_location: &PathBuf) -> Result<()> { | |
26 | let serialized_metadata = metadata.serialize(); | |
27 | write(metadata_location, serialized_metadata)?; | |
28 | Ok(()) | |
29 | } | |
30 | ||
31 | fn archive(&self, source: &PathBuf, target: &PathBuf) -> Result<()> { | |
32 | let entries = read_dir(source)?; | |
33 | for entry in entries { | |
34 | let entry = entry?; | |
35 | let entry_type = entry.file_type()?; | |
36 | let entry_name = entry.file_name(); | |
37 | let entry_source = entry.path(); | |
38 | let entry_target = target.join(entry_name); | |
39 | ||
40 | if entry_type.is_dir() { | |
41 | self.archive(&entry_source, &entry_target)?; | |
42 | } else { | |
43 | copy(&entry_source, &entry_target)?; | |
44 | } | |
45 | } | |
46 | ||
47 | Ok(()) | |
48 | } | |
49 | } | |
50 | ||
51 | impl super::Command for Update { | |
52 | fn before_dependencies(&self) -> Vec<Box<dyn super::Command>> { | |
53 | vec![Box::new(SyncDown::new())] | |
54 | } | |
55 | ||
56 | fn execute(&self, input: Option<&String>, configuration: &Configuration, _: &String) -> Result<()> { | |
57 | let input = input.expect("You must provide a path to a post"); | |
58 | let post_location = PathBuf::from(input); | |
59 | if !post_location.exists() { | |
60 | return Err(Error::new(ErrorKind::NotFound, "The path provided does not exist")); | |
61 | } | |
62 | ||
63 | // Step 1. Write into the ephemeral posts | |
64 | ||
65 | create_dir_all(&configuration.posts_directory)?; | |
66 | ||
67 | let first_post_path = configuration.posts_directory.join("0"); | |
68 | let metadata_file_path = first_post_path.join(METADATA_FILENAME); | |
69 | let metadata = Metadata::read_or_create(&metadata_file_path); | |
70 | ||
71 | let _ = remove_dir_all(&first_post_path); | |
72 | create_dir_all(&first_post_path)?; | |
73 | ||
74 | self.copy_post(&post_location, &first_post_path)?; | |
75 | self.write_metadata(&metadata, &metadata_file_path)?; | |
76 | ||
77 | // Step 2. Write into the archive | |
78 | ||
79 | create_dir_all(&configuration.archive_directory)?; | |
80 | ||
81 | let post_archive_path = configuration.archive_directory.join(metadata.id); | |
82 | let _ = remove_dir_all(&post_archive_path); | |
83 | create_dir_all(&post_archive_path)?; | |
84 | ||
85 | self.archive(&first_post_path, &post_archive_path)?; | |
86 | return Ok(()) | |
87 | } | |
88 | ||
89 | fn after_dependencies(&self) -> Vec<Box<dyn super::Command>> { | |
90 | vec![ | |
91 | Box::new(Generate::new()), | |
92 | Box::new(SyncUp::new()) | |
93 | ] | |
94 | } | |
95 | ||
96 | fn command(&self) -> &'static str { | |
97 | "update" | |
98 | } | |
99 | ||
100 | fn help(&self) -> &'static str { | |
101 | "<path_to_post>\t\tUpdates latest blog post" | |
102 | } | |
103 | } | |
104 |