Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat:] Add Watch Feature to Monitor Input Folder for Changes #60

Merged
merged 11 commits into from
Oct 24, 2024

Conversation

SkySingh04
Copy link
Contributor

@SkySingh04 SkySingh04 commented Oct 21, 2024

Description

This PR introduces the --watch flag to the marmite project, allowing it to monitor the input_folder for any changes and rebuild the site when changes are detected. This feature was inspired by similar implementations in static site generators like Zola and Cobalt.

Key features added:

  • The --watch flag enables the program to watch the input_folder and trigger site rebuilds upon file changes.
  • The --watch --serve option allows simultaneous file watching and serving the site via an HTTP server.
  • Hotwatch is used to handle file changes and triggers the rebuild in a background thread.

Changes

  1. Added --watch flag support to enable file system monitoring for changes.
  2. Wrapped input_folder in an Arc to share it across threads, ensuring thread safety.
  3. Introduced a file watcher (hotwatch) that triggers site regeneration when changes are detected in input_folder.
  4. Modified the function to build the site on-the-fly when a change is detected.

Known Issues:

Currently, there are still some lifetime errors due to Rust's ownership system, specifically around borrowing input_folder. The error:

[E0373] closure may outlive the current function, but it borrows `input_folder`, which is owned by the current function.
  • I am still working on resolving these lifetime issues by ensuring input_folder is safely shared and accessible within the file-watching closure.
  • The site is successfully built when initially executed, and file watching works but further testing is needed for the edge cases.

Next Steps:

  • Finalize lifetime management for input_folder within closures.
  • Ensure the server starts and restarts correctly when using --watch --serve.
  • Add additional tests and documentation for this feature.

Feel free to review the implementation so far, and I’ll continue working on the remaining issues!

Checklist:

  • Fix lifetime and borrowing issues.
  • Ensure compatibility with --serve.
  • Update documentation.

Related Issue : #34

@rochacbruno
Copy link
Owner

That's great @SkySingh04

There was a major refactor on the weekend, so now the code is better separated in modules.

The bad part is that you gonna need to rebase / resolve conflicts.

The good part is that you can now rely on site::generate(...) as the only function will need to respawn on changes.

@rochacbruno
Copy link
Owner

It looks like some tipe of Locking mechanism will be required

[2024-10-23T10:02:30Z INFO  marmite::site] Site generated at: /tmp/site/
[2024-10-23T10:02:30Z INFO  marmite::site] Watching for changes in folder: example
[2024-10-23T10:02:35Z INFO  marmite::site] Change detected. Rebuilding site...
[2024-10-23T10:02:35Z ERROR marmite::site] Error: Duplicate slug found: 'what-is-marmite-static-site-generator' - try setting any of `title`, `slug` as a unique text, or leave both empty so filename will be assumed.

The thread sleeps for one sec, and then another suddenly tries to rebuild using the shared site_data

I guess that, before rebuilding it is going to be needed to cleanup the site_data.posts and site_data.pages to an empty Vec::new()

Then apply some Mutex on the site_data

Initially

let site_data = Arc::new(Mutex::new(Data::new(config_str)));
let site_data_clone = Arc::clone(&site_data);

Then on the closure

let mut site_data = site_data.lock().unwrap();  // lock to prevent race condition.
site_data.posts = Vec::new();
site_data.pages = Vec::new();
collect_content(&content_dir, &mut site_data);
detect_slug_collision(&site_data);

// Sort posts by date (newest first)
site_data.posts.sort_by(|a, b| b.date.cmp(&a.date));
// Sort pages on title
site_data.pages.sort_by(|a, b| a.title.cmp(&b.title));

This change will probably spawn some adjusts on other places to get site_date.site out of the Arc.

BTW:

I added a justfile

cargo install just
just check # check for linting errors
just fix  # attempt to fix clippy problems

@SkySingh04
Copy link
Contributor Author

@rochacbruno Your requested changes have been made

@rochacbruno
Copy link
Owner

@SkySingh04 that's great, I executed cargo fmt and I will merge it and then the compatibility with --serve can come in another PR, is that ok?

@rochacbruno
Copy link
Owner

For the --serve to work I think I know what should be done, the loop with sleep must be replaced with a server::start when --serve is true.

@rochacbruno rochacbruno merged commit 7a19696 into rochacbruno:main Oct 24, 2024
1 check passed
@SkySingh04
Copy link
Contributor Author

Sure @rochacbruno , I can raise a PR for that as well ✅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants