Skip to content

Commit 7294c76

Browse files
committed
More more things to fs_utils file
1 parent 5b3a57b commit 7294c76

4 files changed

Lines changed: 316 additions & 298 deletions

File tree

src/cmd/serve.rs

Lines changed: 22 additions & 217 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@
2222
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2323

2424
use std::cell::Cell;
25-
use std::collections::HashMap;
26-
use std::fs::read_dir;
2725
use std::future::IntoFuture;
2826
use std::net::{IpAddr, SocketAddr, TcpListener};
2927
use std::path::{Path, PathBuf, MAIN_SEPARATOR};
@@ -41,7 +39,6 @@ use mime_guess::from_path as mimetype_from_path;
4139
use time::macros::format_description;
4240
use time::{OffsetDateTime, UtcOffset};
4341

44-
use libs::globset::GlobSet;
4542
use libs::percent_encoding;
4643
use libs::relative_path::{RelativePath, RelativePathBuf};
4744
use libs::serde_json;
@@ -52,23 +49,12 @@ use errors::{anyhow, Context, Error, Result};
5249
use pathdiff::diff_paths;
5350
use site::sass::compile_sass;
5451
use site::{Site, SITE_CONTENT};
55-
use utils::fs::{clean_site_output_folder, copy_file, is_temp_file};
52+
use utils::fs::{clean_site_output_folder, copy_file};
5653

57-
use crate::fs_event_utils::{get_relevant_event_kind, SimpleFSEventKind};
54+
use crate::fs_utils::{filter_events, ChangeKind, SimpleFileSystemEventKind};
5855
use crate::messages;
5956
use std::ffi::OsStr;
6057

61-
#[derive(Clone, Copy, Debug, Hash, PartialEq)]
62-
enum ChangeKind {
63-
Content,
64-
Templates,
65-
Themes,
66-
StaticFiles,
67-
Sass,
68-
Config,
69-
}
70-
impl Eq for ChangeKind {}
71-
7258
#[derive(Debug, PartialEq)]
7359
enum WatchMode {
7460
Required,
@@ -206,7 +192,7 @@ async fn response_error_injector(
206192
.map(|req| {
207193
req.headers()
208194
.get(header::CONTENT_TYPE)
209-
.map(|val| val != &HeaderValue::from_static("text/html"))
195+
.map(|val| val != HeaderValue::from_static("text/html"))
210196
.unwrap_or(true)
211197
})
212198
.unwrap_or(true)
@@ -401,7 +387,7 @@ fn create_new_site(
401387

402388
let mut constructed_base_url = construct_url(&base_url, no_port_append, interface_port);
403389

404-
if !site.config.base_url.ends_with("/") && constructed_base_url != "/" {
390+
if !site.config.base_url.ends_with('/') && constructed_base_url != "/" {
405391
constructed_base_url.truncate(constructed_base_url.len() - 1);
406392
}
407393

@@ -548,7 +534,7 @@ pub fn serve(
548534
&constructed_base_url, &bind_address
549535
);
550536
if open {
551-
if let Err(err) = open::that(format!("{}", &constructed_base_url)) {
537+
if let Err(err) = open::that(&constructed_base_url) {
552538
eprintln!("Failed to open URL in your browser: {}", err);
553539
}
554540
}
@@ -693,66 +679,16 @@ pub fn serve(
693679

694680
loop {
695681
match rx.recv() {
696-
Ok(Ok(mut events)) => {
697-
// Arrange events from oldest to newest.
698-
events.sort_by(|e1, e2| e1.time.cmp(&e2.time));
699-
700-
// Use a map to keep only the last event that occurred for a particular path.
701-
// Map `full_path -> (partial_path, simple_event_kind, change_kind)`.
702-
let mut meaningful_events: HashMap<
703-
PathBuf,
704-
(PathBuf, SimpleFSEventKind, ChangeKind),
705-
> = HashMap::new();
706-
707-
for event in events.iter() {
708-
let simple_kind = get_relevant_event_kind(&event.event.kind);
709-
if simple_kind.is_none() {
710-
continue;
711-
}
712-
713-
// We currently only handle notify events that report a single path per event.
714-
if event.event.paths.len() != 1 {
715-
console::error(&format!(
716-
"Skipping unsupported file system event with multiple paths: {:?}",
717-
event.event.kind
718-
));
719-
continue;
720-
}
721-
let path = event.event.paths[0].clone();
722-
723-
if is_ignored_file(&site.config.ignored_content_globset, &path) {
724-
continue;
725-
}
726-
727-
if is_temp_file(&path) {
728-
continue;
729-
}
730-
731-
// We only care about changes in non-empty folders
732-
if path.is_dir() && is_folder_empty(&path) {
733-
continue;
734-
}
735-
736-
let (change_k, partial_p) = detect_change_kind(&root_dir, &path, &config_path);
737-
meaningful_events.insert(path, (partial_p, simple_kind.unwrap(), change_k));
738-
}
739-
740-
if meaningful_events.is_empty() {
682+
Ok(Ok(events)) => {
683+
let changes = filter_events(
684+
events,
685+
root_dir,
686+
&config_path,
687+
&site.config.ignored_content_globset,
688+
);
689+
if changes.is_empty() {
741690
continue;
742691
}
743-
744-
// Bin changes by change kind to support later iteration over batches of changes.
745-
// Map of change_kind -> (partial_path, full_path, event_kind).
746-
let mut changes: HashMap<
747-
ChangeKind,
748-
Vec<(&PathBuf, &PathBuf, &SimpleFSEventKind)>,
749-
> = HashMap::new();
750-
for (full_path, (partial_path, event_kind, change_kind)) in meaningful_events.iter()
751-
{
752-
let c = changes.entry(*change_kind).or_insert(vec![]);
753-
c.push((partial_path, full_path, event_kind));
754-
}
755-
756692
let format = format_description!("[year]-[month]-[day] [hour]:[minute]:[second]");
757693

758694
for (change_kind, change_group) in changes.iter() {
@@ -774,7 +710,8 @@ pub fn serve(
774710
full_path.display()
775711
));
776712

777-
let can_do_fast_reload = **event_kind != SimpleFSEventKind::Remove;
713+
let can_do_fast_reload =
714+
*event_kind != SimpleFileSystemEventKind::Remove;
778715

779716
if fast_rebuild {
780717
if can_do_fast_reload {
@@ -783,9 +720,9 @@ pub fn serve(
783720
.unwrap_or_else(|| OsStr::new(""))
784721
.to_string_lossy();
785722
let res = if filename == "_index.md" {
786-
site.add_and_render_section(&full_path)
723+
site.add_and_render_section(full_path)
787724
} else if filename.ends_with(".md") {
788-
site.add_and_render_page(&full_path)
725+
site.add_and_render_page(full_path)
789726
} else {
790727
// an asset changed? a folder renamed?
791728
// should we make it smarter so it doesn't reload the whole site?
@@ -816,9 +753,9 @@ pub fn serve(
816753
}
817754
ChangeKind::Templates => {
818755
let partial_paths: Vec<&PathBuf> =
819-
change_group.iter().map(|(p, _, _)| *p).collect();
756+
change_group.iter().map(|(p, _, _)| p).collect();
820757
let full_paths: Vec<&PathBuf> =
821-
change_group.iter().map(|(_, p, _)| *p).collect();
758+
change_group.iter().map(|(_, p, _)| p).collect();
822759
let combined_paths = full_paths
823760
.iter()
824761
.map(|p| p.display().to_string())
@@ -842,11 +779,11 @@ pub fn serve(
842779
}
843780
ChangeKind::StaticFiles => {
844781
for (partial_path, full_path, _) in change_group.iter() {
845-
copy_static(&site, &full_path, &partial_path);
782+
copy_static(&site, full_path, partial_path);
846783
}
847784
}
848785
ChangeKind::Sass => {
849-
let full_paths = change_group.iter().map(|(_, p, _)| *p).collect();
786+
let full_paths = change_group.iter().map(|(_, p, _)| p).collect();
850787
reload_sass(&site, &full_paths);
851788
}
852789
ChangeKind::Themes => {
@@ -875,141 +812,9 @@ pub fn serve(
875812
}
876813
}
877814

878-
fn is_ignored_file(ignored_content_globset: &Option<GlobSet>, path: &Path) -> bool {
879-
match ignored_content_globset {
880-
Some(gs) => gs.is_match(path),
881-
None => false,
882-
}
883-
}
884-
885-
/// Detect what changed from the given path so we have an idea what needs
886-
/// to be reloaded
887-
fn detect_change_kind(pwd: &Path, path: &Path, config_path: &Path) -> (ChangeKind, PathBuf) {
888-
let mut partial_path = PathBuf::from("/");
889-
partial_path.push(path.strip_prefix(pwd).unwrap_or(path));
890-
891-
let change_kind = if partial_path.starts_with("/templates") {
892-
ChangeKind::Templates
893-
} else if partial_path.starts_with("/themes") {
894-
ChangeKind::Themes
895-
} else if partial_path.starts_with("/content") {
896-
ChangeKind::Content
897-
} else if partial_path.starts_with("/static") {
898-
ChangeKind::StaticFiles
899-
} else if partial_path.starts_with("/sass") {
900-
ChangeKind::Sass
901-
} else if path == config_path {
902-
ChangeKind::Config
903-
} else {
904-
unreachable!("Got a change in an unexpected path: {}", partial_path.display());
905-
};
906-
907-
(change_kind, partial_path)
908-
}
909-
910-
/// Check if the directory at path contains any file
911-
fn is_folder_empty(dir: &Path) -> bool {
912-
// Can panic if we don't have the rights I guess?
913-
914-
read_dir(dir).expect("Failed to read a directory to see if it was empty").next().is_none()
915-
}
916-
917815
#[cfg(test)]
918816
mod tests {
919-
use std::path::{Path, PathBuf};
920-
921-
use super::{construct_url, detect_change_kind, is_temp_file, ChangeKind};
922-
923-
#[test]
924-
fn can_recognize_temp_files() {
925-
let test_cases = vec![
926-
Path::new("hello.swp"),
927-
Path::new("hello.swx"),
928-
Path::new(".DS_STORE"),
929-
Path::new("hello.tmp"),
930-
Path::new("hello.html.__jb_old___"),
931-
Path::new("hello.html.__jb_tmp___"),
932-
Path::new("hello.html.__jb_bak___"),
933-
Path::new("hello.html~"),
934-
Path::new("#hello.html"),
935-
Path::new(".index.md.kate-swp"),
936-
];
937-
938-
for t in test_cases {
939-
assert!(is_temp_file(t));
940-
}
941-
}
942-
943-
#[test]
944-
fn can_detect_kind_of_changes() {
945-
let test_cases = vec![
946-
(
947-
(ChangeKind::Templates, PathBuf::from("/templates/hello.html")),
948-
Path::new("/home/vincent/site"),
949-
Path::new("/home/vincent/site/templates/hello.html"),
950-
Path::new("/home/vincent/site/config.toml"),
951-
),
952-
(
953-
(ChangeKind::Themes, PathBuf::from("/themes/hello.html")),
954-
Path::new("/home/vincent/site"),
955-
Path::new("/home/vincent/site/themes/hello.html"),
956-
Path::new("/home/vincent/site/config.toml"),
957-
),
958-
(
959-
(ChangeKind::StaticFiles, PathBuf::from("/static/site.css")),
960-
Path::new("/home/vincent/site"),
961-
Path::new("/home/vincent/site/static/site.css"),
962-
Path::new("/home/vincent/site/config.toml"),
963-
),
964-
(
965-
(ChangeKind::Content, PathBuf::from("/content/posts/hello.md")),
966-
Path::new("/home/vincent/site"),
967-
Path::new("/home/vincent/site/content/posts/hello.md"),
968-
Path::new("/home/vincent/site/config.toml"),
969-
),
970-
(
971-
(ChangeKind::Sass, PathBuf::from("/sass/print.scss")),
972-
Path::new("/home/vincent/site"),
973-
Path::new("/home/vincent/site/sass/print.scss"),
974-
Path::new("/home/vincent/site/config.toml"),
975-
),
976-
(
977-
(ChangeKind::Config, PathBuf::from("/config.toml")),
978-
Path::new("/home/vincent/site"),
979-
Path::new("/home/vincent/site/config.toml"),
980-
Path::new("/home/vincent/site/config.toml"),
981-
),
982-
(
983-
(ChangeKind::Config, PathBuf::from("/config.staging.toml")),
984-
Path::new("/home/vincent/site"),
985-
Path::new("/home/vincent/site/config.staging.toml"),
986-
Path::new("/home/vincent/site/config.staging.toml"),
987-
),
988-
];
989-
990-
for (expected, pwd, path, config_filename) in test_cases {
991-
assert_eq!(expected, detect_change_kind(pwd, path, config_filename));
992-
}
993-
}
994-
995-
#[test]
996-
#[cfg(windows)]
997-
fn windows_path_handling() {
998-
let expected = (ChangeKind::Templates, PathBuf::from("/templates/hello.html"));
999-
let pwd = Path::new(r#"C:\Users\johan\site"#);
1000-
let path = Path::new(r#"C:\Users\johan\site\templates\hello.html"#);
1001-
let config_filename = Path::new(r#"C:\Users\johan\site\config.toml"#);
1002-
assert_eq!(expected, detect_change_kind(pwd, path, config_filename));
1003-
}
1004-
1005-
#[test]
1006-
fn relative_path() {
1007-
let expected = (ChangeKind::Templates, PathBuf::from("/templates/hello.html"));
1008-
let pwd = Path::new("/home/johan/site");
1009-
let path = Path::new("templates/hello.html");
1010-
let config_filename = Path::new("config.toml");
1011-
assert_eq!(expected, detect_change_kind(pwd, path, config_filename));
1012-
}
817+
use super::construct_url;
1013818

1014819
#[test]
1015820
fn test_construct_url_base_url_is_slash() {

0 commit comments

Comments
 (0)