Make more options constants and protect git files by prefix

This commit is contained in:
Robin Gottschalk 2025-02-05 21:55:52 +01:00
parent ef2cc1db23
commit f1e025e059
3 changed files with 28 additions and 18 deletions

View File

@ -17,4 +17,16 @@ This script automates the process of backing up your Obsidian vault to a Git rep
## Installation ## Installation
- Create target repo folder and initialize an empty git repository - Create target repo folder and initialize an empty git repository
- Link repository to remote and set upstream branch (git push working) - Set up git lfs for attachments
- `$ git lfs install`
- `.gitattributes`
```
*.pdf filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.jpg filter=lfs diff=lfs merge=lfs -text
*.jpeg filter=lfs diff=lfs merge=lfs -text
*.webp filter=lfs diff=lfs merge=lfs -text
*.avif filter=lfs diff=lfs merge=lfs -text
*.svg filter=lfs diff=lfs merge=lfs -text
```
- Link repository to origin as remote

View File

@ -4,20 +4,19 @@ use std::path::{Path, PathBuf};
pub fn sync_directory( pub fn sync_directory(
source: &Path, source: &Path,
target: &Path, target: &Path,
protect: Option<&str>, // Will not get touched in target (file or directory at top level) protect_prefix: Option<&str>, // Will not get touched in target (file or directory at top level)
) -> Result<(), Box<dyn std::error::Error>> { ) -> Result<(), Box<dyn std::error::Error>> {
// Ensure the target directory exists // Ensure the target directory exists
fs::create_dir_all(target)?; fs::create_dir_all(target)?;
// Gather all paths in the source and target directories // Gather all paths in the source and target directories
let filter = |entry: Result<fs::DirEntry, std::io::Error>| { let filter = |entry: Result<fs::DirEntry, std::io::Error>| {
entry.ok().and_then(|entry| { entry
if entry.file_name().to_str() != protect { .ok()
Some(entry.path()) .and_then(|entry| match (entry.file_name().to_str(), protect_prefix) {
} else { (Some(name), Some(prefix)) if name.starts_with(prefix) => None,
None _ => Some(entry.path()),
} })
})
}; };
let mut source_entries: Vec<PathBuf> = fs::read_dir(source)?.filter_map(filter).collect(); let mut source_entries: Vec<PathBuf> = fs::read_dir(source)?.filter_map(filter).collect();
let mut target_entries: Vec<PathBuf> = fs::read_dir(target)?.filter_map(filter).collect(); let mut target_entries: Vec<PathBuf> = fs::read_dir(target)?.filter_map(filter).collect();

View File

@ -15,8 +15,11 @@ use winit::{
mod filesync; mod filesync;
mod git; mod git;
const SOURCE_VAULT: &str = "D:\\test\\obsidian-vault-source"; // syncthing vault folder const PROTECT_PREFIX: &str = ".git"; // only at first directory level
const REPO_VAULT: &str = "D:\\test\\obsidian-vault-test"; // git repo folder const SOURCE_VAULT: &str = "D:\\Cloud\\Syncthing\\obsidian-vault"; // syncthing vault folder
const REPO_VAULT: &str =
"C:\\Users\\robin\\AppData\\Roaming\\obsidian-git-backup\\obsidian-vault-clone"; // git repo folder
const GIT_COMMIT_DELAY_AFTER_FILE_CHANGE: Duration = Duration::from_secs(5 * 60); // 5 min
#[derive(Debug)] #[derive(Debug)]
enum UserEvent { enum UserEvent {
@ -31,7 +34,6 @@ struct App {
menu_backup_now: Option<MenuItem>, menu_backup_now: Option<MenuItem>,
menu_exit: Option<MenuItem>, menu_exit: Option<MenuItem>,
last_change_time: Option<Instant>, last_change_time: Option<Instant>,
duration_threshold: Duration,
current_change_count: usize, current_change_count: usize,
} }
@ -74,7 +76,7 @@ impl App {
self.last_change_time = Some(Instant::now()); self.last_change_time = Some(Instant::now());
let source = Path::new(SOURCE_VAULT); let source = Path::new(SOURCE_VAULT);
let target = Path::new(REPO_VAULT); let target = Path::new(REPO_VAULT);
filesync::sync_directory(source, target, Some(".git")) filesync::sync_directory(source, target, Some(PROTECT_PREFIX))
.expect("Directories could not be synced"); .expect("Directories could not be synced");
self.current_change_count = self.current_change_count =
git::current_change_count(target).expect("Changes could not get counted using git"); git::current_change_count(target).expect("Changes could not get counted using git");
@ -92,10 +94,7 @@ impl App {
impl ApplicationHandler<UserEvent> for App { impl ApplicationHandler<UserEvent> for App {
fn resumed(&mut self, _event_loop: &ActiveEventLoop) { fn resumed(&mut self, _event_loop: &ActiveEventLoop) {
self.create_tray_icon_menu(); self.create_tray_icon_menu();
// Set the duration threshold (e.g., 5 minutes)
self.last_change_time = None; self.last_change_time = None;
self.duration_threshold = Duration::from_secs(15);
} }
fn user_event(&mut self, event_loop: &ActiveEventLoop, event: UserEvent) { fn user_event(&mut self, event_loop: &ActiveEventLoop, event: UserEvent) {
@ -127,7 +126,7 @@ impl ApplicationHandler<UserEvent> for App {
// Backup changes if last file change time exceeded threshold // Backup changes if last file change time exceeded threshold
if let Some(last_change_time) = self.last_change_time { if let Some(last_change_time) = self.last_change_time {
if now.duration_since(last_change_time) > self.duration_threshold { if now.duration_since(last_change_time) > GIT_COMMIT_DELAY_AFTER_FILE_CHANGE {
println!("---> Backup triggered by file change"); println!("---> Backup triggered by file change");
self.start_backup(); self.start_backup();
} }
@ -150,7 +149,7 @@ fn main() {
// Sync folder and check for changes to back up // Sync folder and check for changes to back up
let source_dir = Path::new(SOURCE_VAULT); let source_dir = Path::new(SOURCE_VAULT);
let repo_dir = Path::new(REPO_VAULT); let repo_dir = Path::new(REPO_VAULT);
filesync::sync_directory(source_dir, repo_dir, Some(".git")) filesync::sync_directory(source_dir, repo_dir, Some(PROTECT_PREFIX))
.expect("Directories could not be synced"); .expect("Directories could not be synced");
git::backup_changes(repo_dir).expect("Changes could not be pushed"); git::backup_changes(repo_dir).expect("Changes could not be pushed");