mirror of
https://codeberg.org/icewind/galton.git
synced 2026-06-03 18:34:08 +02:00
symlink support
This commit is contained in:
parent
7500d6ccf4
commit
1269e95b6f
2 changed files with 41 additions and 9 deletions
|
|
@ -8,6 +8,8 @@ use thiserror::Error;
|
|||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct GaltonConfig {
|
||||
#[serde(default)]
|
||||
pub watch: WatchConfig,
|
||||
#[serde(default)]
|
||||
pub rule: Vec<Rule>,
|
||||
}
|
||||
|
|
@ -26,15 +28,26 @@ impl GaltonConfig {
|
|||
}
|
||||
}
|
||||
|
||||
fn normalize_path(path: String) -> String {
|
||||
if let Some(suffix) = path.strip_prefix("~/") {
|
||||
#[derive(Debug, Deserialize, Default)]
|
||||
pub struct WatchConfig {
|
||||
symlink: Option<String>,
|
||||
}
|
||||
|
||||
impl WatchConfig {
|
||||
pub fn symlink(&self) -> Option<String> {
|
||||
self.symlink.as_deref().map(normalize_path)
|
||||
}
|
||||
}
|
||||
|
||||
fn normalize_path<P: Into<String> + AsRef<str>>(path: P) -> String {
|
||||
if let Some(suffix) = path.as_ref().strip_prefix("~/") {
|
||||
let home = home_dir().unwrap_or_default();
|
||||
home.join(suffix)
|
||||
.into_os_string()
|
||||
.into_string()
|
||||
.expect("non utf8 home directory")
|
||||
} else {
|
||||
path
|
||||
path.into()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
31
src/main.rs
31
src/main.rs
|
|
@ -10,6 +10,7 @@ use notify_debouncer_full::notify::{EventKind, RecursiveMode};
|
|||
use notify_debouncer_full::{new_debouncer, DebounceEventResult};
|
||||
use std::fs::{copy, create_dir_all, remove_file, rename};
|
||||
use std::io::ErrorKind;
|
||||
use std::os::unix::fs::symlink;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::mpsc::channel;
|
||||
use std::thread::sleep;
|
||||
|
|
@ -66,6 +67,7 @@ fn main() -> MainResult {
|
|||
}
|
||||
Commands::Watch { path, recursive } => {
|
||||
let rules = config.rule;
|
||||
let symlink = config.watch.symlink();
|
||||
let (tx, rx) = channel();
|
||||
let mut watcher = new_debouncer(Duration::from_secs(1), None, tx)?;
|
||||
watcher.watch(
|
||||
|
|
@ -84,7 +86,7 @@ fn main() -> MainResult {
|
|||
}
|
||||
})?;
|
||||
for res in rx {
|
||||
handle_watch_events(res, &rules);
|
||||
handle_watch_event(res, &rules, symlink.as_deref());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -92,7 +94,7 @@ fn main() -> MainResult {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_watch_events(result: DebounceEventResult, rules: &[Rule]) {
|
||||
fn handle_watch_event(result: DebounceEventResult, rules: &[Rule], link_target: Option<&str>) {
|
||||
match result {
|
||||
Ok(events) => {
|
||||
for event in events {
|
||||
|
|
@ -103,7 +105,22 @@ fn handle_watch_events(result: DebounceEventResult, rules: &[Rule]) {
|
|||
sleep(Duration::from_millis(200));
|
||||
match FileInfo::load(path) {
|
||||
Ok(file) => {
|
||||
handle_file(&file, rules);
|
||||
if let Some(target) = handle_file(&file, rules) {
|
||||
if let Some(link_target) = link_target {
|
||||
match symlink(&target, link_target) {
|
||||
Ok(()) => {
|
||||
info!(
|
||||
to = target,
|
||||
from = link_target,
|
||||
"created symlink"
|
||||
);
|
||||
}
|
||||
Err(error) => {
|
||||
error!(%error, "failed to link target");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(error) => {
|
||||
error!(%error, "failed to load file info");
|
||||
|
|
@ -132,10 +149,10 @@ fn match_file(file: &FileInfo, rules: &[Rule]) -> Option<RuleMatch> {
|
|||
}
|
||||
|
||||
#[instrument(skip_all, fields(file = file.path))]
|
||||
fn handle_file(file: &FileInfo, rules: &[Rule]) {
|
||||
fn handle_file(file: &FileInfo, rules: &[Rule]) -> Option<String> {
|
||||
let Some(result) = match_file(file, rules) else {
|
||||
info!("no matches");
|
||||
return;
|
||||
return None;
|
||||
};
|
||||
|
||||
let parent = result.target.as_deref().unwrap_or_else(|| file.parent());
|
||||
|
|
@ -143,7 +160,7 @@ fn handle_file(file: &FileInfo, rules: &[Rule]) {
|
|||
|
||||
if let Err(error) = create_dir_all(parent) {
|
||||
error!(%error, "failed to create target directory");
|
||||
return;
|
||||
return None;
|
||||
}
|
||||
|
||||
let target = format!("{parent}/{name}");
|
||||
|
|
@ -151,9 +168,11 @@ fn handle_file(file: &FileInfo, rules: &[Rule]) {
|
|||
match cross_storage_move(&file.path, &target) {
|
||||
Ok(()) => {
|
||||
info!(target, "moved file");
|
||||
Some(target)
|
||||
}
|
||||
Err(error) => {
|
||||
info!(target, ?error, "failed to moved file");
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue