worktrunk 0.42.0

A CLI for Git worktree management, designed for parallel AI agent workflows
Documentation
use crate::common::{
    TestRepo, make_snapshot_cmd, repo, set_temp_home_env, set_xdg_config_path,
    setup_home_snapshot_settings, setup_snapshot_settings, temp_home, wt_command,
};
use insta_cmd::assert_cmd_snapshot;
use rstest::rstest;
use std::fs;
use tempfile::TempDir;

#[rstest]
fn test_config_init_already_exists(temp_home: TempDir) {
    // Create fake global config at XDG path
    let global_config_dir = temp_home.path().join(".config").join("worktrunk");
    fs::create_dir_all(&global_config_dir).unwrap();
    fs::write(
        global_config_dir.join("config.toml"),
        r#"worktree-path = "../{{ repo }}.{{ branch }}"
"#,
    )
    .unwrap();

    let settings = setup_home_snapshot_settings(&temp_home);
    settings.bind(|| {
        let mut cmd = wt_command();
        cmd.arg("config").arg("create");
        set_temp_home_env(&mut cmd, temp_home.path());
        set_xdg_config_path(&mut cmd, temp_home.path());

        assert_cmd_snapshot!(cmd, @"
        success: true
        exit_code: 0
        ----- stdout -----

        ----- stderr -----
        ○ User config already exists: ~/.config/worktrunk/config.toml
        ↳ To view both user and project configs, run wt config show
        ");
    });
}

#[rstest]
fn test_config_init_creates_file(temp_home: TempDir) {
    // Don't create config file - let create create it
    let global_config_dir = temp_home.path().join(".config").join("worktrunk");
    fs::create_dir_all(&global_config_dir).unwrap();

    let settings = setup_home_snapshot_settings(&temp_home);
    settings.bind(|| {
        let mut cmd = wt_command();
        cmd.arg("config").arg("create");
        set_temp_home_env(&mut cmd, temp_home.path());
        set_xdg_config_path(&mut cmd, temp_home.path());

        assert_cmd_snapshot!(cmd, @"
        success: true
        exit_code: 0
        ----- stdout -----

        ----- stderr -----
        ✓ Created user config: ~/.config/worktrunk/config.toml
        ↳ Edit this file to customize worktree paths and LLM settings
        ");
    });

    // Verify file was actually created
    let config_path = global_config_dir.join("config.toml");
    assert!(config_path.exists());
}

#[rstest]
fn test_config_create_project_creates_file(repo: TestRepo) {
    let settings = setup_snapshot_settings(&repo);
    settings.bind(|| {
        let mut cmd = make_snapshot_cmd(&repo, "config", &["create", "--project"], None);
        assert_cmd_snapshot!(cmd, @"
        success: true
        exit_code: 0
        ----- stdout -----

        ----- stderr -----
        ✓ Created project config: _REPO_/.config/wt.toml
        ↳ Edit this file to configure hooks for this repository
        ↳ See https://worktrunk.dev/hook/ for hook documentation
        ");
    });

    // Verify file was actually created
    let config_path = repo.root_path().join(".config/wt.toml");
    assert!(
        config_path.exists(),
        "Project config file should be created"
    );
}

#[rstest]
fn test_config_create_project_already_exists(repo: TestRepo) {
    // Create project config file
    let config_dir = repo.root_path().join(".config");
    fs::create_dir_all(&config_dir).unwrap();
    fs::write(
        config_dir.join("wt.toml"),
        r#"[[project.post-create]]
run = "echo hello"
"#,
    )
    .unwrap();

    let settings = setup_snapshot_settings(&repo);
    settings.bind(|| {
        let mut cmd = make_snapshot_cmd(&repo, "config", &["create", "--project"], None);
        assert_cmd_snapshot!(cmd, @"
        success: true
        exit_code: 0
        ----- stdout -----

        ----- stderr -----
        ○ Project config already exists: _REPO_/.config/wt.toml
        ↳ To view, run wt config show. To create a user config, run wt config create
        ");
    });
}