Skip to content

Commit

Permalink
fix: rebuild when config changes
Browse files Browse the repository at this point in the history
  • Loading branch information
rochacbruno committed Nov 23, 2024
1 parent e6da771 commit 34ac046
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 41 deletions.
8 changes: 4 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ mod tera_functions;

fn main() {
let args = cli::Cli::parse();
let input_folder = args.input_folder;
let input_folder = Arc::new(args.input_folder);
let output_folder = Arc::new(args.output_folder);
let serve = args.serve;
let watch = args.watch;
Expand All @@ -28,9 +28,9 @@ fn main() {
}

let config_path = if args.config.starts_with('.') || args.config.starts_with('/') {
PathBuf::new().join(args.config)
Arc::new(PathBuf::new().join(args.config))
} else {
input_folder.join(args.config)
Arc::new(input_folder.join(args.config))
};

let env = Env::default().default_filter_or(match verbose {
Expand Down Expand Up @@ -75,6 +75,6 @@ fn main() {
// Serve the site if the flag was provided
if serve && !watch {
info!("Starting built-in HTTP server...");
server::start(bind_address, &output_folder);
server::start(bind_address, Arc::clone(&output_folder));
}
}
4 changes: 2 additions & 2 deletions src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::sync::Arc;
use std::{fs::File, path::Path};
use tiny_http::{Header, Response, Server};

pub fn start(bind_address: &str, output_folder: &Arc<PathBuf>) {
pub fn start(bind_address: &str, output_folder: Arc<PathBuf>) {
let server = Server::http(bind_address).unwrap();

info!(
Expand All @@ -14,7 +14,7 @@ pub fn start(bind_address: &str, output_folder: &Arc<PathBuf>) {
);

for request in server.incoming_requests() {
let response = match handle_request(&request, output_folder) {
let response = match handle_request(&request, output_folder.as_path()) {
Ok(response) => response,
Err(err) => {
error!("Error handling request: {}", err);
Expand Down
87 changes: 52 additions & 35 deletions src/site.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,15 @@ impl Data {
self.author.sort_all();
self.stream.sort_all();
}

pub fn clear_all(&mut self) {
self.posts.clear();
self.pages.clear();
self.tag.map.clear();
self.archive.map.clear();
self.author.map.clear();
self.stream.map.clear();
}
}

#[derive(Serialize, Deserialize, Clone)]
Expand All @@ -70,83 +79,91 @@ struct BuildInfo {
}

pub fn generate(
config_path: &std::path::PathBuf,
input_folder: &std::path::Path,
config_path: &Arc<std::path::PathBuf>,
input_folder: &Arc<std::path::PathBuf>,
output_folder: &Arc<std::path::PathBuf>,
watch: bool,
serve: bool,
bind_address: &str,
) {
let config_str = fs::read_to_string(config_path).unwrap_or_else(|e| {
info!(
"Unable to read '{}', assuming defaults.: {}",
&config_path.display(),
e
);
String::new()
});
if config_str.is_empty() {
info!("Config loaded from: defaults");
} else {
info!("Config loaded from: {}", config_path.display());
}
let moved_input_folder = Arc::clone(input_folder);
let moved_output_folder = Arc::clone(output_folder);
let moved_config_path = Arc::clone(config_path);

let rebuild = {
let start_time = std::time::Instant::now();
let site_data = Arc::new(Mutex::new(Data::new(&config_str)));
let content_dir = {
let site_data = site_data.lock().unwrap();
Some(input_folder.join(site_data.site.content_path.clone()))
}
.filter(|path| path.is_dir()) // Take if exists
.unwrap_or_else(|| input_folder.to_path_buf()); // Fallback to input_folder if not
let output_folder = Arc::clone(output_folder);
let input_folder = input_folder.to_path_buf();

move || {
let start_time = std::time::Instant::now();

let config_str = fs::read_to_string(moved_config_path.as_path()).unwrap_or_else(|e| {
info!(
"Unable to read '{}', assuming defaults.: {}",
&moved_config_path.display(),
e
);
String::new()
});
if config_str.is_empty() {
info!("Config loaded from: defaults");
} else {
info!("Config loaded from: {}", moved_config_path.display());
}

let site_data = Arc::new(Mutex::new(Data::new(&config_str)));
let content_dir = {
let site_data = site_data.lock().unwrap();
Some(moved_input_folder.join(site_data.site.content_path.clone()))
}
.filter(|path| path.is_dir()) // Take if exists
.unwrap_or_else(|| moved_input_folder.to_path_buf()); // Fallback to input_folder if not

let mut site_data = site_data.lock().unwrap();
site_data.clear_all();
let fragments = collect_fragments(&content_dir);
collect_content(&content_dir, &mut site_data, &fragments);
site_data.sort_all();
detect_slug_collision(&site_data); // Detect slug collision and warn user
collect_back_links(&mut site_data);

let site_path = site_data.site.site_path.clone();
let output_path = output_folder.join(site_path);
let output_path = moved_output_folder.join(site_path);
if let Err(e) = fs::create_dir_all(&output_path) {
error!("Unable to create output directory: {}", e);
process::exit(1);
}

let tera = initialize_tera(&input_folder, &site_data);
let tera = initialize_tera(&moved_input_folder, &site_data);
if let Err(e) = render_templates(&content_dir, &site_data, &tera, &output_path) {
error!("Failed to render templates: {}", e);
process::exit(1);
}

handle_static_artifacts(&input_folder, &site_data, &output_folder, &content_dir);
handle_static_artifacts(
&moved_input_folder,
&site_data,
&moved_output_folder,
&content_dir,
);

if site_data.site.enable_search {
generate_search_index(&site_data, &output_folder);
generate_search_index(&site_data, &moved_output_folder);
}

let end_time = start_time.elapsed().as_secs_f64();
write_build_info(&output_path, &site_data, &end_time);
debug!("Site generated in {:.2}s", end_time);
info!("Site generated at: {}/", output_folder.display());
info!("Site generated at: {}/", moved_output_folder.display());
}
};

// Initial site generation
rebuild();

// If watch flag is enabled, start hotwatch
if watch {
let mut hotwatch = Hotwatch::new().expect("Failed to initialize hotwatch!");

let watch_folder = Arc::clone(input_folder).as_path().to_path_buf();
// Watch the input folder for changes
hotwatch
.watch(input_folder, move |event: Event| match event.kind {
.watch(watch_folder, move |event: Event| match event.kind {
EventKind::Create(_) | EventKind::Modify(_) | EventKind::Remove(_) => {
info!("Change detected. Rebuilding site...");
rebuild();
Expand All @@ -160,7 +177,7 @@ pub fn generate(
// Keep the thread alive for watching
if serve {
info!("Starting built-in HTTP server...");
server::start(bind_address, output_folder);
server::start(bind_address, Arc::clone(output_folder));
} else {
loop {
std::thread::sleep(std::time::Duration::from_secs(1));
Expand Down

0 comments on commit 34ac046

Please sign in to comment.