From bb47728d64b736a5b94a06e79f120727d30111b1 Mon Sep 17 00:00:00 2001 From: Abdelilah El Aissaoui Date: Wed, 11 Oct 2023 20:36:48 +0200 Subject: [PATCH] Probe files and directory checks are now executed in the Rust part to reduce the communication overhead between both parts --- rs/src/gitnuro.udl | 2 +- rs/src/watch_directory.rs | 36 ++++++++++++++++--- .../gitnuro/git/FileChangesWatcher.kt | 20 +++++------ .../gitnuro/viewmodels/TabViewModel.kt | 1 - 4 files changed, 40 insertions(+), 19 deletions(-) diff --git a/rs/src/gitnuro.udl b/rs/src/gitnuro.udl index 2162f52..a045861 100644 --- a/rs/src/gitnuro.udl +++ b/rs/src/gitnuro.udl @@ -1,6 +1,6 @@ namespace gitnuro { [Throws=WatcherInitError] - void watch_directory(string path, WatchDirectoryNotifier checker); + void watch_directory(string path, string git_dir_path, WatchDirectoryNotifier checker); }; callback interface WatchDirectoryNotifier { diff --git a/rs/src/watch_directory.rs b/rs/src/watch_directory.rs index 24d85b1..56ccdcd 100644 --- a/rs/src/watch_directory.rs +++ b/rs/src/watch_directory.rs @@ -12,6 +12,7 @@ const WATCH_TIMEOUT: u64 = 500; pub fn watch_directory( path: String, + git_dir_path: String, notifier: Box, ) -> Result<(), WatcherInitError> { // Create a channel to receive the events. @@ -56,7 +57,7 @@ pub fn watch_directory( println!("Sending single file event to Kotlin side"); notifier.detected_change(paths_cached.to_vec()); } - } else { + } else if !paths_cached.is_empty() { println!("Sending batched events to Kotlin side"); notifier.detected_change(paths_cached.to_vec()); } @@ -66,13 +67,18 @@ pub fn watch_directory( match rx.recv_timeout(Duration::from_millis(WATCH_TIMEOUT)) { Ok(e) => { - if let Some(mut paths) = get_paths_from_event_result(&e) { - paths_cached.append(&mut paths); + if let Some(paths) = get_paths_from_event_result(&e, &git_dir_path) { + let mut paths_without_dirs: Vec = paths + .into_iter() + .collect(); + + paths_cached.append(&mut paths_without_dirs); last_update = SystemTime::now() .duration_since(UNIX_EPOCH) .expect("We need a TARDIS to fix this") .as_millis(); + println!("Event: {e:?}"); } } @@ -91,14 +97,34 @@ pub fn watch_directory( Ok(()) } -pub fn get_paths_from_event_result(event_result: &Result) -> Option> { +pub fn get_paths_from_event_result(event_result: &Result, git_dir_path: &str) -> Option> { match event_result { Ok(event) => { let events: Vec = event .paths .clone() .into_iter() - .filter_map(|path| path.into_os_string().into_string().ok()) + .filter_map(|path| { + // Directories are not tracked by Git so we don't care about them (just about their content) + // We won't be able to check if it's a dir if it has been deleted but that's good enough + if path.is_dir() { + println!("Ignoring directory {path:#?}"); + None + } else { + let path_str = path.into_os_string() + .into_string() + .ok()?; + + // JGit may create .probe-UUID files for its internal stuff, we don't care about it + let probe_prefix = format!("{git_dir_path}.probe-"); + if path_str.starts_with(probe_prefix.as_str()) { + println!("Ignoring .probe file"); + None + } else { + Some(path_str) + } + } + }) .collect(); if events.is_empty() { diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/git/FileChangesWatcher.kt b/src/main/kotlin/com/jetpackduba/gitnuro/git/FileChangesWatcher.kt index 5cdf638..177f3ce 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/git/FileChangesWatcher.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/git/FileChangesWatcher.kt @@ -26,8 +26,10 @@ class FileChangesWatcher @Inject constructor( suspend fun watchDirectoryPath( repository: Repository, - pathStr: String ) = withContext(Dispatchers.IO) { + val workspacePath = repository.workTree.absolutePath + val gitRepoPath = repository.directory.absolutePath + systemSeparator + var ignoreRules = getIgnoreRulesUseCase(repository) val gitDirIgnoredFiles = listOf( Constants.COMMIT_EDITMSG, @@ -41,7 +43,7 @@ class FileChangesWatcher @Inject constructor( } override fun detectedChange(paths: List) = runBlocking { - val hasGitIgnoreChanged = paths.any { it == "$pathStr$systemSeparator.gitignore" } + val hasGitIgnoreChanged = paths.any { it == "$workspacePath$systemSeparator.gitignore" } if (hasGitIgnoreChanged) { ignoreRules = getIgnoreRulesUseCase(repository) @@ -53,19 +55,13 @@ class FileChangesWatcher @Inject constructor( } val isGitIgnoredFile = gitDirIgnoredFiles.any { ignoredFile -> - "$pathStr$systemSeparator.git$systemSeparator$ignoredFile" == path + "$workspacePath$systemSeparator.git$systemSeparator$ignoredFile" == path } - // JGit may create .probe-UUID files for its internal stuff, we should not care about it - val onlyProbeFiles = paths.all { it.contains("$systemSeparator.git$systemSeparator.probe-") } - - // Ignore it if the change is the directory itself - val isGitDir = paths.count() == 1 && paths.first() == "$pathStr$systemSeparator.git$systemSeparator" - - matchesAnyIgnoreRule || isGitIgnoredFile || onlyProbeFiles || isGitDir + matchesAnyIgnoreRule || isGitIgnoredFile } - val hasGitDirChanged = paths.any { it.startsWith("$pathStr$systemSeparator.git$systemSeparator") } + val hasGitDirChanged = paths.any { it.startsWith("$workspacePath$systemSeparator.git$systemSeparator") } if (!areAllPathsIgnored) { _changesNotifier.emit(hasGitDirChanged) @@ -73,6 +69,6 @@ class FileChangesWatcher @Inject constructor( } } - watchDirectory(pathStr, checker) + watchDirectory(workspacePath, gitRepoPath, checker) } } \ No newline at end of file diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/TabViewModel.kt b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/TabViewModel.kt index 0caf766..4a3a0be 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/TabViewModel.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/TabViewModel.kt @@ -241,7 +241,6 @@ class TabViewModel @Inject constructor( try { fileChangesWatcher.watchDirectoryPath( repository = git.repository, - pathStr = git.repository.workTree.absolutePath, ) } catch (ex: WatcherInitException) { val message = when (ex) {