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

Cleanup get_ignore_patterns and decrease duplications #29

Closed
github-actions bot opened this issue May 9, 2022 · 1 comment
Closed

Cleanup get_ignore_patterns and decrease duplications #29

github-actions bot opened this issue May 9, 2022 · 1 comment
Labels

Comments

@github-actions
Copy link
Contributor

github-actions bot commented May 9, 2022

https://github.com/tami5/XcodeBase.nvim/blob/2d1123e26527e95776e18b4fc28a50013d63ba7c/src/util/watch.rs#L40

//! Function to watch file system
//!
//! Mainly used for creation/removal of files and editing of xcodegen config.
use crate::daemon::DaemonState;
use anyhow::Result;
use notify::{Error, Event, RecommendedWatcher, RecursiveMode, Watcher};
use std::{future::Future, path::PathBuf, sync::Arc, time::SystemTime};
use std::{path::Path, time::Duration};
use tokio::sync::{mpsc, Mutex};
use tokio::task::JoinHandle;
use wax::{Glob, Pattern};

const COMPILE_START_MSG: &str = "echo 'xcodebase: ⚙ Regenerating compilation database ..'";
const COMPILE_SUCC_MESSAGE: &str = "echo 'xcodebase: ✅ Compilation database regenerated.'";

/// HACK: ignore seen paths.
///
/// Sometimes we get event for the same path, particularly
/// `ModifyKind::Name::Any` is omitted twice for the new path
/// and once for the old path.
///
/// This will compare last_seen with path, updates `last_seen` if not match,
/// else returns true.
#[cfg(feature = "async")]
pub async fn should_ignore(last_seen: Arc<Mutex<String>>, path: &str) -> bool {
    // HACK: Always return false for project.yml
    let path = path.to_string();
    if path.contains("project.yml") {
        return false;
    }
    let mut last_seen = last_seen.lock().await;
    if last_seen.to_string() == path {
        return true;
    } else {
        *last_seen = path;
        return false;
    }
}

// TODO: Cleanup get_ignore_patterns and decrease duplications
#[cfg(feature = "daemon")]
pub async fn get_ignore_patterns(state: DaemonState, root: &String) -> Vec<String> {
    let mut patterns: Vec<String> = vec![
        "**/.git/**",
        "**/*.xcodeproj/**",
        "**/.*",
        "**/build/**",
        "**/buildServer.json",
    ]
    .iter()
    .map(|e| e.to_string())
    .collect();

    // Note: Add extra ignore patterns to `ignore` local config requires restarting daemon.
    if let Some(ws) = state.lock().await.workspaces.get(root) {
        if let Some(extra_patterns) = ws.get_ignore_patterns() {
            patterns.extend(extra_patterns);
        }
    }

    patterns
}

pub fn new<F, Fut>(
    root: String,
    state: DaemonState,
    event_handler: F,
) -> JoinHandle<anyhow::Result<()>>
where
    F: Fn(DaemonState, String, PathBuf, Event, Arc<Mutex<String>>, Arc<Mutex<SystemTime>>) -> Fut
        + Send
        + 'static,
    Fut: Future<Output = anyhow::Result<bool>> + Send,
{
    use notify::Config::NoticeEvents;
    let debounce = Arc::new(Mutex::new(SystemTime::now()));

    tokio::spawn(async move {
        let (tx, mut rx) = mpsc::channel(1);
        let mut watcher = RecommendedWatcher::new(move |res: Result<Event, Error>| {
            if let Ok(event) = res {
                if let Err(err) = tx.blocking_send(event) {
                    #[cfg(feature = "logging")]
                    tracing::error!("Fail send event {err}");
                };
            } else {
                tracing::error!("Watch Error: {:?}", res);
            };
        })?;

        // NOTE: should watch for registered directories only?
        watcher.watch(Path::new(&root), RecursiveMode::Recursive)?;
        watcher.configure(NoticeEvents(true))?;

        // HACK: ignore seen paths.
        let last_seen = Arc::new(Mutex::new(String::default()));
        // HACK: convert back to Vec<&str> for Glob to work.
        let patterns = get_ignore_patterns(state.clone(), &root).await;
        let patterns = patterns.iter().map(AsRef::as_ref).collect::<Vec<&str>>();
        let ignore = match wax::any::<Glob, _>(patterns) {
            Ok(i) => i,
            Err(err) => {
                anyhow::bail!("Fail to generate ignore glob: {err}")
            }
        };
@github-actions github-actions bot added the todo label May 9, 2022
@github-actions
Copy link
Contributor Author

Closed in 8430976

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

No branches or pull requests

0 participants