use std::collections::HashMap;
use std::rc::Rc;
use camino::Utf8PathBuf;
use iri_string::types::UriAbsoluteString;
use tokio::sync::mpsc::UnboundedSender;
use crate::event_loop::js_function::Functions;
use crate::event_loop::{Event, ExtensionState, Repository};
#[tracing::instrument(skip(extension_state, js_functions, sender))]
pub async fn handle(
workspace_uri: UriAbsoluteString,
extension_state: &mut ExtensionState,
js_functions: &Functions,
sender: &mut UnboundedSender<Event>,
) {
if workspace_uri.scheme_str() != "file" {
tracing::info!(message = "Skipping unhandled URI scheme", ?workspace_uri);
return;
}
let workspace_path = Utf8PathBuf::from(workspace_uri.path_str());
let ignore_root = workspace_path.clone();
let (dot_directory_sender, mut dot_directory_receiver) = tokio::sync::mpsc::unbounded_channel();
std::thread::spawn(move || {
let walker = ignore::WalkBuilder::new(&ignore_root)
.current_dir(&ignore_root)
.build_parallel();
walker.run(move || {
let path_sender = dot_directory_sender.clone();
Box::new(move |entry_result| {
if let Ok(entry) = entry_result
&& let Some(file_type) = entry.file_type()
&& file_type.is_dir()
{
let dot_directory_path = entry.path().join(libpijul::DOT_DIR);
if dot_directory_path.is_dir() {
path_sender.send(entry.into_path()).unwrap();
return ignore::WalkState::Skip;
}
}
ignore::WalkState::Continue
})
});
});
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) =
extension_state.repositories.entry(repository_path.clone())
else {
tracing::warn!(message = "Ignoring existing repository");
continue;
};
let repository_uri = match js_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;
}
};
let (source_control, unrecorded_changes, untracked_paths) = match js_functions
.initialize_source_control(
repository_uri,
&extension_state.quick_diff_provider,
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;
}
};
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;
}
};
repository_entry.insert(Repository {
repository: file_system_repository,
source_control,
open_editors: HashMap::new(),
unrecorded_changes: Rc::new(unrecorded_changes),
untracked_paths: Rc::new(untracked_paths),
});
tracing::info!(
message = "Opened repository",
?repository_path,
?workspace_path
);
sender
.send(Event::UpdateResourceStates { repository_path })
.expect("Receiver should be open");
}
}