Recursively discover repositories when handling `OpenWorkspaceFolder` event

finchie
Jan 1, 2026, 5:04 AM
SLTXBK5GTNH3PUZNA5VG7IDICV3NZPWSCTJSE4YPOQEDMWO67PIQC

Dependencies

  • [2] WFWTKCJN Create initial Visual Studio Code extension
  • [3] 72K45XKD Refactor inline credit to improve hover messages
  • [4] MGJ23FHF Assign repository URI to source control in `OpenWorkspaceFolder` events
  • [5] 2ZAM5V35 Move event handling into modules

Change contents

  • edit in editors/vscode/src/event_loop/event/open_workspace_folder.rs at line 30
    [5.1275]
    [5.1275]
    let ignore_root = workspace_path.clone();
  • replacement in editors/vscode/src/event_loop/event/open_workspace_folder.rs at line 32
    [5.1276][5.1276:1375]()
    // TODO: multiple repositories per workspace
    let repository_path = workspace_path.clone();
    [5.1276]
    [5.1375]
    let (dot_directory_sender, mut dot_directory_receiver) = tokio::sync::mpsc::unbounded_channel();
    // TODO: better separate sync vs non-sync code
    std::thread::spawn(move || {
    let walker = ignore::WalkBuilder::new(&ignore_root)
    .current_dir(&ignore_root)
    .build_parallel();
  • replacement in editors/vscode/src/event_loop/event/open_workspace_folder.rs at line 39
    [5.1376][5.1376:1598]()
    let std::collections::hash_map::Entry::Vacant(repository_entry) =
    repositories.entry(repository_path.clone())
    else {
    tracing::warn!(message = "Ignoring existing repository");
    return;
    };
    [5.1376]
    [5.1598]
    walker.run(move || {
    let path_sender = dot_directory_sender.clone();
  • replacement in editors/vscode/src/event_loop/event/open_workspace_folder.rs at line 42
    [5.1599][5.1599:1914]()
    let repository_uri = match threadsafe_functions
    .uri_file(repository_path.to_string())
    .await
    {
    Ok(repository_uri) => repository_uri,
    Err(error) => {
    tracing::error!(message = "Failed to parse URI", ?repository_path, ?error);
    return;
    }
    };
    [5.1599]
    [5.1914]
    Box::new(move |entry_result| {
    // TODO: handle errors
    if let Ok(entry) = entry_result
    && let Some(file_type) = entry.file_type()
    && file_type.is_dir()
    {
    // Path: {ENTRY}/.pijul/
    let dot_directory_path = entry.path().join(libpijul::DOT_DIR);
    if dot_directory_path.is_dir() {
    path_sender.send(entry.into_path()).unwrap();
    // Don't traverse repositories
    return ignore::WalkState::Skip;
    }
    }
    ignore::WalkState::Continue
    })
    });
    });
    // TODO: debug assertion that no discovered repositories are nested
    while let Some(os_repository_path) = dot_directory_receiver.recv().await {
    let repository_path = match Utf8PathBuf::from_path_buf(os_repository_path.to_path_buf()) {
    Ok(repository_path) => repository_path,
    Err(utf8_path_error) => {
    tracing::error!(
    message = "Failed to convert OS path to UTF-8 path",
    ?os_repository_path,
    ?utf8_path_error
    );
    continue;
    }
    };
    let std::collections::hash_map::Entry::Vacant(repository_entry) =
    repositories.entry(repository_path.clone())
    else {
    tracing::warn!(message = "Ignoring existing repository");
    continue;
    };
    let repository_uri = match threadsafe_functions
    .uri_file(repository_path.to_string())
    .await
    {
    Ok(repository_uri) => repository_uri,
    Err(error) => {
    tracing::error!(message = "Failed to parse URI", ?repository_path, ?error);
    continue;
    }
    };
  • replacement in editors/vscode/src/event_loop/event/open_workspace_folder.rs at line 96
    [5.1915][5.1915:2425]()
    let (source_control, unrecorded_changes, untracked_paths) = match threadsafe_functions
    .initialize_source_control(
    repository_uri,
    String::from("Pijul"),
    String::from("Changes"),
    String::from("Untracked"),
    )
    .await
    {
    Ok(initialized_source_control) => initialized_source_control,
    Err(error) => {
    tracing::error!(message = "Unable to create source control", ?error);
    return;
    }
    };
    [5.1915]
    [5.2425]
    let (source_control, unrecorded_changes, untracked_paths) = match threadsafe_functions
    .initialize_source_control(
    repository_uri,
    String::from("Pijul"),
    String::from("Changes"),
    String::from("Untracked"),
    )
    .await
    {
    Ok(initialized_source_control) => initialized_source_control,
    Err(error) => {
    tracing::error!(message = "Unable to create source control", ?error);
    continue;
    }
    };
  • replacement in editors/vscode/src/event_loop/event/open_workspace_folder.rs at line 112
    [5.2426][5.2426:2707]()
    let file_system_repository = match pijul_extension::FileSystemRepository::new(&repository_path)
    {
    Ok(repository) => repository,
    Err(error) => {
    tracing::error!(message = "Failed to open repository", ?error);
    return;
    }
    };
    [5.2426]
    [5.2707]
    let file_system_repository =
    match pijul_extension::FileSystemRepository::new(&repository_path) {
    Ok(repository) => repository,
    Err(error) => {
    tracing::error!(message = "Failed to open repository", ?error);
    continue;
    }
    };
  • replacement in editors/vscode/src/event_loop/event/open_workspace_folder.rs at line 121
    [5.2708][5.2708:2916]()
    repository_entry.insert(Repository {
    repository: file_system_repository,
    source_control,
    open_editors: HashMap::new(),
    unrecorded_changes,
    untracked_paths,
    });
    [5.2708]
    [5.2916]
    repository_entry.insert(Repository {
    repository: file_system_repository,
    source_control,
    open_editors: HashMap::new(),
    unrecorded_changes,
    untracked_paths,
    });
  • replacement in editors/vscode/src/event_loop/event/open_workspace_folder.rs at line 129
    [5.2917][5.2917:3033]()
    tracing::info!(
    message = "Opened repository",
    ?repository_path,
    ?workspace_path
    );
    [5.2917]
    [5.3033]
    tracing::info!(
    message = "Opened repository",
    ?repository_path,
    ?workspace_path
    );
    }
  • edit in editors/vscode/Cargo.toml at line 27
    [3.12215]
    [4.3474]
    ignore.workspace = true
  • edit in Cargo.toml at line 34
    [3.12435]
    [4.3503]
    ignore = "0.4.25"
  • replacement in Cargo.lock at line 1229
    [2.206635][2.206635:206654]()
    version = "0.4.16"
    [2.206635]
    [2.206654]
    version = "0.4.18"
  • replacement in Cargo.lock at line 1231
    [2.206719][2.206719:206797]()
    checksum = "54a1028dfc5f5df5da8a56a73e6c153c9a9708ec57232470703592a3f18e49f5"
    [2.206719]
    [2.206797]
    checksum = "52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3"
  • replacement in Cargo.lock at line 1675
    [2.215483][2.215483:215502]()
    version = "0.4.23"
    [2.215483]
    [2.215502]
    version = "0.4.25"
  • replacement in Cargo.lock at line 1677
    [2.215567][2.215567:215645]()
    checksum = "6d89fd380afde86567dfba715db065673989d6253f42b88179abd3eae47bda4b"
    [2.215567]
    [2.215645]
    checksum = "d3d782a365a015e0f5c04902246139249abf769125006fbe7649e2ee88169b4a"
  • edit in Cargo.lock at line 2597
    [3.16635]
    [4.3758]
    "ignore",