Update source control resource states in event loop

finchie
Jan 1, 2026, 1:22 PM
IDY5SNLOFZ663OCJ2L5NZMFNJXZSGL5O22QQXR5BIV3SJ2VUQIMQC

Dependencies

  • [2] 3YGYMEXV Create `event_loop` module
  • [3] NB2MF3MY Add `OpenWorkspaceFolder` event
  • [4] XDFSAPI7 Create a tokio runtime directly instead of `#[tokio::main]`
  • [5] MGJ23FHF Assign repository URI to source control in `OpenWorkspaceFolder` events
  • [6] OUADGWKR Create fully-initialized `SourceControl` object in `event_loop`
  • [7] 2ZAM5V35 Move event handling into modules
  • [8] SLTXBK5G Recursively discover repositories when handling `OpenWorkspaceFolder` event
  • [9] TWEUQ64D Move threadsafe function builder logic into function-specific modules
  • [10] QY4Z5ZXZ Refactor `event_loop/threadsafe_function` file into `event_loop::js_function` module
  • [11] IBVCQSSG Use `External` to wrap `initialize_source_control` arguments

Change contents

  • edit in editors/vscode/src/event_loop/mod.rs at line 2
    [6.2543]
    [2.172]
    use std::rc::Rc;
  • replacement in editors/vscode/src/event_loop/mod.rs at line 24
    [6.2786][6.2786:2939]()
    unrecorded_changes: vscode_sys::reference::SourceControlResourceGroupRef,
    untracked_paths: vscode_sys::reference::SourceControlResourceGroupRef,
    [6.2786]
    [3.1618]
    unrecorded_changes: Rc<vscode_sys::reference::SourceControlResourceGroupRef>,
    untracked_paths: Rc<vscode_sys::reference::SourceControlResourceGroupRef>,
  • replacement in editors/vscode/src/event_loop/mod.rs at line 29
    [2.455][10.18:118]()
    async fn event_loop(js_functions: js_function::Functions, mut receiver: UnboundedReceiver<Event>) {
    [2.455]
    [2.517]
    async fn event_loop(
    js_functions: js_function::Functions,
    mut sender: UnboundedSender<Event>,
    mut receiver: UnboundedReceiver<Event>,
    ) {
  • replacement in editors/vscode/src/event_loop/mod.rs at line 49
    [3.1760][3.1760:1797]()
    for event in &event_buffer {
    [3.1760]
    [3.1797]
    for event in event_buffer.drain(..) {
  • replacement in editors/vscode/src/event_loop/mod.rs at line 52
    [5.1532][10.119:250]()
    event::open_workspace_folder::handle(raw_uri, &mut repositories, &js_functions)
    .await
    [5.1532]
    [3.2519]
    event::open_workspace_folder::handle(
    raw_uri,
    &mut repositories,
    &js_functions,
    &mut sender,
    )
    .await
  • edit in editors/vscode/src/event_loop/mod.rs at line 60
    [3.2537]
    [3.2537]
    Event::UpdateResourceStates { repository_path } => {
    event::update_resource_states::handle(
    repository_path,
    &repositories,
    &js_functions,
    )
    .await
    }
  • replacement in editors/vscode/src/event_loop/mod.rs at line 85
    [2.1124][2.1124:1185]()
    if let Err(_existing_value) = EVENT_SENDER.set(sender) {
    [2.1124]
    [3.2740]
    if let Err(_existing_value) = EVENT_SENDER.set(sender.clone()) {
  • replacement in editors/vscode/src/event_loop/mod.rs at line 94
    [4.161][10.325:411]()
    std::thread::spawn(move || runtime.block_on(event_loop(js_functions, receiver)));
    [4.161]
    [3.2926]
    std::thread::spawn(move || runtime.block_on(event_loop(js_functions, sender, receiver)));
  • file addition: update_resource_states.rs (----------)
    [10.435]
    use std::rc::Rc;
    use camino::Utf8PathBuf;
    use napi::bindgen_prelude::{External, FunctionCallContext};
    use pijul_extension::path_state::PathState;
    use crate::vscode_sys::reference::SourceControlResourceGroupRef;
    use crate::vscode_sys::{SourceControlResourceState, Uri};
    pub struct Arguments {
    pub repository_path: Utf8PathBuf,
    pub repository_states: Vec<(Utf8PathBuf, PathState)>,
    pub unrecorded_changes: Rc<SourceControlResourceGroupRef>,
    pub untracked_paths: Rc<SourceControlResourceGroupRef>,
    }
    pub type Prototype = napi::threadsafe_function::ThreadsafeFunction<
    External<Arguments>,
    (),
    External<Arguments>,
    napi::Status,
    false,
    false,
    0,
    >;
    pub fn build(env: &napi::Env) -> Result<Prototype, napi::Error> {
    env.create_function_from_closure("update_resource_states", callback)?
    .build_threadsafe_function()
    .build()
    }
    fn callback(function_call_context: FunctionCallContext) -> Result<(), napi::Error> {
    let (external,): (&External<Arguments>,) = function_call_context.args()?;
    let Arguments {
    repository_path,
    repository_states,
    unrecorded_changes,
    untracked_paths,
    } = &**external;
    let mut modified_resource_states = Vec::new();
    let mut untracked_resource_states = Vec::new();
    for (relative_path, path_state) in repository_states {
    let absolute_path = repository_path.join(relative_path);
    let resource_uri = Uri::file(function_call_context.env, absolute_path.as_str())?;
    let resource_state =
    SourceControlResourceState::new(function_call_context.env, &resource_uri)?;
    match path_state {
    PathState::Untracked => untracked_resource_states.push(resource_state),
    PathState::Tracked(_tracked_state) => modified_resource_states.push(resource_state),
    }
    }
    unrecorded_changes
    .get_inner(function_call_context.env)?
    .set_resource_states(modified_resource_states)?;
    untracked_paths
    .get_inner(function_call_context.env)?
    .set_resource_states(untracked_resource_states)?;
    Ok(())
    }
  • edit in editors/vscode/src/event_loop/js_function/mod.rs at line 1
    [3.772]
    [11.0]
    use std::rc::Rc;
    use camino::Utf8PathBuf;
  • edit in editors/vscode/src/event_loop/js_function/mod.rs at line 5
    [11.55]
    [3.808]
    use pijul_extension::path_state::PathState;
  • edit in editors/vscode/src/event_loop/js_function/mod.rs at line 10
    [11.91]
    [10.486]
    pub mod update_resource_states;
  • edit in editors/vscode/src/event_loop/js_function/mod.rs at line 14
    [6.115]
    [5.729]
    update_resource_states: update_resource_states::Prototype,
  • edit in editors/vscode/src/event_loop/js_function/mod.rs at line 22
    [9.79]
    [5.968]
    update_resource_states: update_resource_states::build(env)?,
  • edit in editors/vscode/src/event_loop/js_function/mod.rs at line 42
    [11.452]
    [11.452]
    .call_async(External::new(arguments))
    .await
    }
    pub async fn update_resource_states(
    &self,
    repository_path: Utf8PathBuf,
    repository_states: Vec<(Utf8PathBuf, PathState)>,
    unrecorded_changes: &Rc<vscode_sys::reference::SourceControlResourceGroupRef>,
    untracked_paths: &Rc<vscode_sys::reference::SourceControlResourceGroupRef>,
    ) -> Result<(), napi::Error> {
    let arguments = update_resource_states::Arguments {
    repository_path,
    repository_states,
    unrecorded_changes: Rc::clone(unrecorded_changes),
    untracked_paths: Rc::clone(untracked_paths),
    };
    self.update_resource_states
  • file addition: update_resource_states.rs (----------)
    [7.332]
    use std::collections::HashMap;
    use camino::Utf8PathBuf;
    use crate::event_loop::Repository;
    use crate::event_loop::js_function::Functions;
    #[tracing::instrument(skip(repositories, js_functions))]
    pub async fn handle(
    repository_path: Utf8PathBuf,
    repositories: &HashMap<Utf8PathBuf, Repository>,
    js_functions: &Functions,
    ) {
    let Some(repository) = repositories.get(&repository_path) else {
    tracing::error!(message = "No repository found", ?repository_path);
    return;
    };
    if let Err(error) = js_functions
    .update_resource_states(
    repository_path,
    repository.repository.iter_path_states().collect(),
    &repository.unrecorded_changes,
    &repository.untracked_paths,
    )
    .await
    {
    tracing::error!(message = "Failed to update resource states", ?error);
    }
    }
  • edit in editors/vscode/src/event_loop/event/open_workspace_folder.rs at line 2
    [7.415]
    [7.415]
    use std::rc::Rc;
  • edit in editors/vscode/src/event_loop/event/open_workspace_folder.rs at line 6
    [7.480]
    [7.480]
    use tokio::sync::mpsc::UnboundedSender;
  • edit in editors/vscode/src/event_loop/event/open_workspace_folder.rs at line 8
    [7.481][7.481:516]()
    use crate::event_loop::Repository;
  • edit in editors/vscode/src/event_loop/event/open_workspace_folder.rs at line 9
    [10.2114]
    [7.581]
    use crate::event_loop::{Event, Repository};
  • replacement in editors/vscode/src/event_loop/event/open_workspace_folder.rs at line 13
    [7.668][7.668:687]()
    raw_uri: &str,
    [7.668]
    [7.687]
    raw_uri: String,
  • edit in editors/vscode/src/event_loop/event/open_workspace_folder.rs at line 16
    [10.2203]
    [7.792]
    sender: &mut UnboundedSender<Event>,
  • replacement in editors/vscode/src/event_loop/event/open_workspace_folder.rs at line 18
    [7.796][7.796:847]()
    let uri = match UriAbsoluteStr::new(raw_uri) {
    [7.796]
    [7.847]
    let uri = match UriAbsoluteStr::new(&raw_uri) {
  • replacement in editors/vscode/src/event_loop/event/open_workspace_folder.rs at line 125
    [8.3473][8.3473:3534]()
    unrecorded_changes,
    untracked_paths,
    [8.3473]
    [8.3534]
    unrecorded_changes: Rc::new(unrecorded_changes),
    untracked_paths: Rc::new(untracked_paths),
  • edit in editors/vscode/src/event_loop/event/open_workspace_folder.rs at line 134
    [8.3683]
    [8.3683]
    sender
    .send(Event::UpdateResourceStates { repository_path })
    .expect("Receiver should be open");
  • edit in editors/vscode/src/event_loop/event/mod.rs at line 1
    [7.3067]
    [7.3068]
    use camino::Utf8PathBuf;
  • edit in editors/vscode/src/event_loop/event/mod.rs at line 4
    [7.3099]
    [7.3099]
    pub mod update_resource_states;
  • edit in editors/vscode/src/event_loop/event/mod.rs at line 9
    [7.3175]
    [7.3175]
    UpdateResourceStates { repository_path: Utf8PathBuf },