treeflow 0.2.0

CLI tool for simplified Git worktree management to speed up switching contexts when working collaboratively.
Documentation
#[cfg(test)]
mod utils;

#[cfg(test)]
mod project_tests {
    use tempdir::TempDir;
    use treeflow::utils::Return;
    use crate::utils::treeflow_command::TreeflowCommand;

    #[test]
    fn project_add() {
        let config_dir = TempDir::new("config_dir").expect("should be able to create temp config dir");
        let current_dir =
            TempDir::new("current_dir").expect("should be able to create temp current dir");
        let repository_path = current_dir.path().to_path_buf();
        let worktrees_path = current_dir.path().join("worktrees");

        TreeflowCommand::new(config_dir.path().to_path_buf())
            .project_add(&repository_path, Some(&worktrees_path))
            .current_dir(current_dir.path())
            .cmd()
            .assert()
            .success()
            .stdout(Return::Null { }.print());

        TreeflowCommand::new(config_dir.path().to_path_buf())
            .project_list()
            .cmd()
            .assert()
            .success()
            .stdout(format!("{}\n", repository_path.display()));
    }

    #[test]
    fn project_remove() {
        let config_dir = TempDir::new("config_dir").expect("should be able to create temp config dir");
        let current_dir = TempDir::new("current_dir").expect("should be able to create temp current dir");
        let repository_path = current_dir.path().to_path_buf();
        let worktrees_path = current_dir.path().join("worktrees");

        // Add a project first
        TreeflowCommand::new(config_dir.path().to_path_buf())
            .project_add(&repository_path, Some(&worktrees_path))
            .current_dir(current_dir.path())
            .cmd()
            .assert()
            .success();

        // Remove the project
        TreeflowCommand::new(config_dir.path().to_path_buf())
            .project_remove(&repository_path)
            .current_dir(current_dir.path())
            .cmd()
            .assert()
            .success()
            .stdout(Return::Null { }.print());

        // Verify project is removed
        TreeflowCommand::new(config_dir.path().to_path_buf())
            .project_list()
            .cmd()
            .assert()
            .success()
            .stdout("<<No projects configured>>\n");
    }

    #[test]
    fn list_empty_projects() {
        let config_dir = TempDir::new("config_dir").expect("Temp dir");

        // List projects when none are configured
        TreeflowCommand::new(config_dir.path().to_path_buf())
            .project_list()
            .cmd()
            .assert()
            .success()
            .stdout("<<No projects configured>>\n");
    }
    #[test]
    fn list_multiple_projects() {
        let config_dir = TempDir::new("config_dir").expect("Temp dir");
        let current_dir = TempDir::new("current_dir").expect("Temp dir");
        let repo1_path = current_dir.path().join("repo1");
        let repo2_path = current_dir.path().join("repo2");
        let repo3_path = current_dir.path().join("repo3");

        let worktrees1_path = current_dir.path().join("worktrees1");
        let worktrees2_path = current_dir.path().join("worktrees2");
        let worktrees3_path = current_dir.path().join("worktrees3");

        // Create directories for repositories
        std::fs::create_dir_all(&repo1_path).expect("Failed to create repo1 dir");
        std::fs::create_dir_all(&repo2_path).expect("Failed to create repo2 dir");
        std::fs::create_dir_all(&repo3_path).expect("Failed to create repo3 dir");

        // Add multiple projects
        TreeflowCommand::new(config_dir.path().to_path_buf())
            .project_add(&repo1_path, Some(&worktrees1_path))
            .current_dir(current_dir.path())
            .cmd()
            .assert()
            .success();

        TreeflowCommand::new(config_dir.path().to_path_buf())
            .project_add(&repo2_path, Some(&worktrees2_path))
            .current_dir(current_dir.path())
            .cmd()
            .assert()
            .success();

        TreeflowCommand::new(config_dir.path().to_path_buf())
            .project_add(&repo3_path, Some(&worktrees3_path))
            .current_dir(current_dir.path())
            .cmd()
            .assert()
            .success();

        // Verify all appear in list in the order they were added
        TreeflowCommand::new(config_dir.path().to_path_buf())
            .project_list()
            .cmd()
            .assert()
            .success()
            .stdout(format!("{}\n{}\n{}\n", repo1_path.display(), repo2_path.display(), repo3_path.display()));
    }

    #[test]
    fn remove_projects_updates_list() {
        let config_dir = TempDir::new("config_dir").expect("Temp dir");
        let current_dir = TempDir::new("current_dir").expect("Temp dir");
        let repo1_path = current_dir.path().join("repo1");
        let repo2_path = current_dir.path().join("repo2");

        let worktrees1_path = current_dir.path().join("worktrees1");
        let worktrees2_path = current_dir.path().join("worktrees2");

        // Create directories for repositories
        std::fs::create_dir_all(&repo1_path).expect("Failed to create repo1 dir");
        std::fs::create_dir_all(&repo2_path).expect("Failed to create repo2 dir");

        // Add multiple projects
        TreeflowCommand::new(config_dir.path().to_path_buf())
            .project_add(&repo1_path, Some(&worktrees1_path))
            .current_dir(current_dir.path())
            .cmd()
            .assert()
            .success();

        TreeflowCommand::new(config_dir.path().to_path_buf())
            .project_add(&repo2_path, Some(&worktrees2_path))
            .current_dir(current_dir.path())
            .cmd()
            .assert()
            .success();

        // Remove one project
        TreeflowCommand::new(config_dir.path().to_path_buf())
            .project_remove(&repo2_path)
            .current_dir(current_dir.path())
            .cmd()
            .assert()
            .success();

        // Verify only remaining project is listed
        TreeflowCommand::new(config_dir.path().to_path_buf())
            .project_list()
            .cmd()
            .assert()
            .success()
            .stdout(format!("{}\n", repo1_path.display()));
    }
}