This initial change implements some basic extension functionality including quick diff, inline credit and file states. Future changes will be much smaller in scope and focus on adding features and improving robustness/architecture.
WFWTKCJNC4VSURSQWE5FXJGTEJJOCDMQ6LN2O6EW2DNOVT2ZUMRQC use camino::Utf8PathBuf;use clap::Parser;mod build;#[derive(Debug, clap::Parser)]pub enum SubCommand {Build(build::Args),}#[derive(Clone, Copy, Debug, clap::ValueEnum)]pub enum ExtensionTarget {#[value(name = "vscode")]VisualStudioCode,}impl ExtensionTarget {pub fn name(&self) -> &str {match self {ExtensionTarget::VisualStudioCode => "vscode",}}pub fn base_path(&self, metadata: &cargo_metadata::Metadata) -> Utf8PathBuf {// TODO: get the workspace rootlet workspace_root = &metadata.workspace_root;assert!(workspace_root.exists());assert!(workspace_root.is_dir());let path = workspace_root.join("extensions").join(self.name());assert!(path.exists());assert!(path.is_dir());path}}fn main() -> Result<(), anyhow::Error> {let sub_command = SubCommand::parse();let metadata = cargo_metadata::MetadataCommand::new().exec()?;match sub_command {SubCommand::Build(args) => args.run(&metadata),}}
use std::process::Command;use crate::ExtensionTarget;#[derive(Debug, clap::Parser)]pub struct Args {#[arg(value_enum)]extension_target: ExtensionTarget,}impl Args {pub fn run(&self, metadata: &cargo_metadata::Metadata) -> Result<(), anyhow::Error> {let base_path = self.extension_target.base_path(metadata);// TODO: walk the tree before/after build to make sure no artifacts were missedmatch self.extension_target {ExtensionTarget::VisualStudioCode => {// Steps:// 1. Install all dependencies// 2. Build native Rust module// 3. Build TypeScript codelet out_dir = base_path.join("out");let native_module = out_dir.join("native-module");std::fs::create_dir_all(&out_dir)?;std::fs::create_dir_all(&native_module)?;// TODO: pnpm install?// TODO: release builds// TODO: multiple targetslet mut rust_build = Command::new("pnpm");rust_build.current_dir(&base_path);rust_build.args(["exec","napi","build","--platform","--output-dir",native_module.as_str(),"--target","x86_64-unknown-linux-gnu",]);let rust_exit_status = rust_build.status()?;assert!(rust_exit_status.success());let mut typescript_build = Command::new("pnpm");typescript_build.current_dir(base_path);typescript_build.args(["exec", "tsc", "--outDir", out_dir.as_str()]);let typescript_exit_status = typescript_build.status()?;assert!(typescript_exit_status.success());}}Ok(())}}
[package]name = "xtask"publish = falsedescription = "Build scripts using the cargo-xtask pattern"# Keys inherited from workspaceauthors.workspace = truecategories.workspace = trueedition.workspace = truekeywords.workspace = truelicense.workspace = truerepository.workspace = trueversion.workspace = true[dependencies]anyhow.workspace = truecamino.workspace = truecargo_metadata.workspace = trueclap.workspace = true
// TODO: rewrite to be generic over filesystem implementationsuse std::collections::HashSet;use camino::{Utf8Path, Utf8PathBuf};use canonical_path::CanonicalPathBuf;use libpijul::pristine::sanakirja::{MutTxn, SanakirjaError};use libpijul::{ArcTxn, TxnTExt};#[derive(Debug, thiserror::Error)]pub enum UntrackedItemError {#[error("unable to get untracked path from filesystem: {0:#?}")]IO(std::io::Error),#[error("unable to check if path is tracked: {0:#?}")]IsTracked(SanakirjaError),#[error("unable to convert `{invalid_path:#?}` to UTF-8: {conversion_error:#?}")]Utf8Path {invalid_path: std::path::PathBuf,conversion_error: camino::FromPathBufError,},}#[derive(Debug, thiserror::Error)]#[error(transparent)]pub enum UntrackedError {#[error("unable to get available parallelism: {0:#?}")]AvailableParallelism(std::io::Error),#[error("unable to canonicalize root path `{root_path}`: {io_error:#?}")]CanonicalRoot {root_path: Utf8PathBuf,io_error: std::io::Error,},#[error("unable to iterate untracked files: {0:#?}")]Iteration(std::io::Error),#[error(transparent)]IterationItem(#[from] UntrackedItemError),}pub fn file_system(root: &Utf8Path,file_system: &libpijul::working_copy::FileSystem,transaction: ArcTxn<MutTxn<()>>,) -> Result<HashSet<Utf8PathBuf>, UntrackedError> {let untracked_items_transaction = transaction.clone();let canonical_path =CanonicalPathBuf::canonicalize(root).map_err(|io_error| UntrackedError::CanonicalRoot {root_path: root.to_path_buf(),io_error,})?;let untracked_files: HashSet<Utf8PathBuf> = file_system.iterate_prefix_rec(canonical_path.clone(),canonical_path,false,std::thread::available_parallelism().map_err(UntrackedError::AvailableParallelism)?.get(),// Follow all paths|_path, _is_directory| true,).map_err(UntrackedError::Iteration)?// Handle any errors in iteration.map(|filesystem_result| match filesystem_result {Ok((path, _is_directory)) => {Utf8PathBuf::try_from(path.clone()).map_err(|conversion_error| {UntrackedItemError::Utf8Path {invalid_path: path,conversion_error,}})}Err(io_error) => Err(UntrackedItemError::IO(io_error)),})// Filter out tracked paths.filter_map(|path_result| match path_result {Ok(path) => match untracked_items_transaction.read().is_tracked(path.as_str()) {Ok(true) => None,Ok(false) => Some(Ok(path)),Err(error) => Some(Err(UntrackedItemError::IsTracked(error))),},Err(error) => Some(Err(error)),}).collect::<Result<_, UntrackedItemError>>()?;Ok(untracked_files)}
use std::collections::HashMap;use camino::Utf8PathBuf;use libpijul::change::BaseHunk;use libpijul::changestore::ChangeStore;use libpijul::pristine::sanakirja::{MutTxn, SanakirjaError};use libpijul::working_copy::WorkingCopy;use libpijul::{ArcTxn, ChannelRef, RecordBuilder};use crate::TrackedState;#[derive(Debug, thiserror::Error)]pub enum ModifiedPathsError<C: std::error::Error + 'static, W: std::error::Error> {Globalize(#[from] SanakirjaError),Record(#[from] libpijul::record::RecordError<C, W, MutTxn<()>>),}pub fn modified_paths<C, W>(transaction: &ArcTxn<MutTxn<()>>,channel: &ChannelRef<MutTxn<()>>,working_copy: &W,change_store: &C,) -> Result<HashMap<Utf8PathBuf, TrackedState>, ModifiedPathsError<C::Error, W::Error>>whereC: ChangeStore + Clone + Send + 'static,W: WorkingCopy + Clone + Send + Sync + 'static,{let mut unrecorded_changes = RecordBuilder::new();unrecorded_changes.record(transaction.clone(),libpijul::Algorithm::default(),false, // TODO: check and document&libpijul::DEFAULT_SEPARATOR,channel.clone(),working_copy,change_store,"",1, // TODO: figure out concurrency model)?;let unrecorded_state = unrecorded_changes.finish();let mut modified_paths = HashMap::new();for hunk in unrecorded_state.actions {match hunk {BaseHunk::FileMove { path, .. } => {modified_paths.entry(Utf8PathBuf::from(path)).and_modify(|path_state| match path_state {TrackedState::Modified => *path_state = TrackedState::ModifiedAndMoved,_ => unreachable!("{path_state:#?}"),}).or_insert(TrackedState::Moved);}BaseHunk::FileDel { path, .. } => {modified_paths.try_insert(Utf8PathBuf::from(path), TrackedState::Removed).unwrap();}BaseHunk::FileAdd { path, .. } => {modified_paths.try_insert(Utf8PathBuf::from(path), TrackedState::Added).unwrap();}BaseHunk::Edit { local, .. } | BaseHunk::Replacement { local, .. } => {modified_paths.entry(Utf8PathBuf::from(local.path)).and_modify(|path_state| match path_state {TrackedState::Modified => (),TrackedState::Moved => *path_state = TrackedState::ModifiedAndMoved,_ => unreachable!("{path_state:#?}"),}).or_insert(TrackedState::Modified);}// TODO: FileUndel// TODO: conflicts_ => continue,}}Ok(modified_paths)}
#![feature(map_try_insert)]// TODO: cache wherever possible// TODO: audit pub fields// TODO: changestore/pristine FileSystem integration should integrate with WorkingCopy(Read) traits// TODO: test against memfs to make sure alternative filesystems are supported https://github.com/microsoft/vscode-extension-samples/blob/main/fsprovider-sample/README.md// TODO: zero-copy data if possible?// TODO: try do one transaction per function call (no inline .read() etc) - unless maybe if only one read/write call?// TODO: atomic updates to everything? e.g. write working copy and pristine in one go so everything stays in sync// TODO: inject like 10secs of latency everywhere to make sure cancellation works properly (same for any await point - could introduce TOCTOU bugs)// TODO: update tracked state when externally modified on disk (e.g. pijul command directly) - and figure out how to test this?// TODO: make sure paths are based in the root of the repouse std::collections::{HashMap, HashSet};use camino::{Utf8Path, Utf8PathBuf};use libpijul::change::ChangeHeader;use libpijul::changestore;use libpijul::changestore::ChangeStore;use libpijul::pristine::TxnErr;use libpijul::pristine::sanakirja::{MutTxn, Pristine, SanakirjaError};use libpijul::working_copy::WorkingCopy;use libpijul::working_copy::{self, WorkingCopyRead};use libpijul::{ArcTxn, ChangeId, ChannelRef, TxnT};use crate::author::{AuthorSource, Authors};use crate::channel_state::{ChannelState, ChannelStateError};use crate::file_system::changes::unrecorded::UnrecordedChangesError;use crate::file_system::open_file::{OpenFile, OpenFileError};use crate::file_system::working_copy::EditorWorkingCopy;use crate::modified_paths::ModifiedPathsError;pub mod author;pub mod channel_state;pub mod file_system;pub mod modified_paths;pub mod untracked;#[derive(Debug, thiserror::Error)]pub enum RepositoryError<C: std::error::Error + 'static, W: std::error::Error + 'static> {#[error("unable to open pristine: {0:#?}")]Pristine(#[from] SanakirjaError),#[error("unable to begin transaction: {0:#?}")]BeginTransaction(#[from] BeginTransactionError),#[error("unable to get untracked paths: {0:#?}")]Untracked(#[from] untracked::UntrackedError),#[error("failed to log changes: {0:#?}")]Changes(#[from] ChannelStateError<C>),#[error("unable to get modified paths: {0:#?}")]Modified(#[from] ModifiedPathsError<C, W>),}#[derive(Debug, thiserror::Error)]pub enum BeginTransactionError {#[error("unable to begin transaction: {0:#?}")]Transaction(#[from] SanakirjaError),#[error("unable to open channel: {0:#?}")]Channel(#[from] TxnErr<SanakirjaError>),}#[derive(Debug, thiserror::Error)]pub enum CreditError {#[error("error while checking if `{path}` is tracked: {error:#?}")]GetIsTracked {path: Utf8PathBuf,error: SanakirjaError,},#[error("missing open file for {0}")]MissingOpenFile(Utf8PathBuf),}#[derive(Debug, thiserror::Error)]pub enum CreateOpenFileError<C: std::error::Error + 'static, W: std::error::Error + 'static> {#[error("unable to get metadata for file: {0:?}")]FileMetadata(W),#[error(transparent)]OpenFile(#[from] OpenFileError<C>),#[error("File already open at {0}")]AlreadyOpen(Utf8PathBuf),}#[derive(Debug, thiserror::Error)]pub enum UpdateOpenFileError<C: std::error::Error + 'static> {#[error(transparent)]UnrecordedChanges(#[from] UnrecordedChangesError<C>),#[error("No file open at {0}")]NoMatchingFile(Utf8PathBuf),#[error("Unable to begin transaction: {0:#?}")]BeginTransaction(#[from] BeginTransactionError),}#[derive(Clone, Copy, Debug)]pub enum TrackedState {Added,Removed,Modified,Moved,ModifiedAndMoved,}#[derive(Debug)]pub enum PathState {Untracked,Tracked(TrackedState),}pub type FileSystemRepository =Repository<changestore::filesystem::FileSystem, working_copy::FileSystem>;pub struct Repository<C, W>whereC: ChangeStore + Clone + Send + 'static,W: WorkingCopy + Clone + Send + Sync + 'static,{pub authors: Authors,pub channel_state: ChannelState,pub working_copy: EditorWorkingCopy<W>,// TODO: use a triepub untracked: HashSet<Utf8PathBuf>,pub modified_paths: HashMap<Utf8PathBuf, TrackedState>,pub change_store: C,pub pristine: Pristine,}impl FileSystemRepository {pub fn new(root: &Utf8Path,// TODO: take open files here) -> Result<Self, RepositoryError<changestore::filesystem::Error, std::io::Error>> {let dot_directory = root.join(libpijul::DOT_DIR);let change_store = changestore::filesystem::FileSystem::from_root(root.as_str(), 256);let pristine = Pristine::new(dot_directory.join("pristine").join("db").as_str())?;let file_system = working_copy::FileSystem::from_root(root.as_str());let (transaction, channel) = begin_transaction(&pristine)?;let working_copy = EditorWorkingCopy::new(file_system);let channel_state = ChannelState::new(&transaction, &channel, &change_store)?;let authors = Authors::new(&channel_state, &dot_directory);let untracked =untracked::file_system(root, &working_copy.working_copy, transaction.clone())?;let modified_paths = modified_paths::modified_paths(&transaction,&channel,&working_copy.working_copy,&change_store,)?;Ok(Self {authors,channel_state,working_copy,untracked,modified_paths,change_store,pristine,})}}impl<C, W> Repository<C, W>whereC: ChangeStore + Clone + Send + 'static,W: WorkingCopy + Clone + Send + Sync + 'static,{pub fn get_change_header(&self, change_id: &ChangeId) -> Option<&ChangeHeader> {self.channel_state.get_change_header(change_id)}pub fn get_path_state(&self, path: &Utf8Path) -> Option<PathState> {if self.untracked.contains(path) {Some(PathState::Untracked)} else {self.modified_paths.get(path).map(|path_state| PathState::Tracked(*path_state))}}pub fn is_untracked(&self, path: &Utf8Path) -> bool {self.untracked.contains(path)}pub fn iter_modified(&self) -> impl Iterator<Item = &Utf8PathBuf> {self.modified_paths.keys()}pub fn iter_untracked(&self) -> impl Iterator<Item = &Utf8PathBuf> {self.untracked.iter()}pub fn authors_for_change(&self, change_header: &ChangeHeader) -> Vec<&AuthorSource> {self.authors.authors_for_change(change_header)}pub fn create_open_file(&mut self,path: Utf8PathBuf,file_contents: String,) -> Result<(), CreateOpenFileError<C::Error, W::Error>> {let metadata = self.working_copy.file_metadata(path.as_str()).map_err(CreateOpenFileError::FileMetadata)?;let (transaction, channel) = begin_transaction(&self.pristine).unwrap();let open_file = OpenFile::open(path.clone(),file_contents,metadata,&transaction,&channel,&self.change_store,&self.working_copy,)?;self.working_copy.open_files.try_insert(path.clone(), open_file).map_err(|_error| CreateOpenFileError::AlreadyOpen(path))?;Ok(())}pub fn update_open_file(&mut self,path: &Utf8Path,character_offset: usize,characters_replaced: usize,replacement_text: &str,) -> Result<(), UpdateOpenFileError<C::Error>> {let open_file = self.working_copy.open_files.get_mut(path).ok_or_else(|| UpdateOpenFileError::NoMatchingFile(path.to_path_buf()))?;let (transaction, channel) = begin_transaction(&self.pristine)?;open_file.update(character_offset,characters_replaced,replacement_text,&transaction,&channel,&self.change_store,)?;Ok(())}pub fn get_open_file(&self, path: &Utf8Path) -> Option<&OpenFile> {self.working_copy.open_files.get(path)}}fn begin_transaction(pristine: &Pristine,) -> Result<(ArcTxn<MutTxn<()>>, ChannelRef<MutTxn<()>>), BeginTransactionError> {let transaction = pristine.arc_txn_begin()?;let channel = transaction.read().load_channel(transaction.read().current_channel().unwrap_or(libpijul::DEFAULT_CHANNEL),)?.unwrap();Ok((transaction, channel))}
use std::collections::HashMap;use camino::{Utf8Path, Utf8PathBuf};use libpijul::working_copy::WorkingCopy;use libpijul::working_copy::WorkingCopyRead;use crate::file_system::open_file::OpenFile;#[derive(Clone)]pub struct EditorWorkingCopy<W: WorkingCopy + Clone + Send + Sync + 'static> {pub working_copy: W,pub open_files: HashMap<Utf8PathBuf, OpenFile>,}impl<W: WorkingCopy + Clone + Send + Sync + 'static> EditorWorkingCopy<W> {pub fn new(working_copy: W) -> Self {Self {working_copy,open_files: HashMap::new(),}}}impl<W: WorkingCopy + Clone + Send + Sync + 'static> WorkingCopyRead for EditorWorkingCopy<W> {type Error = W::Error;fn file_metadata(&self, file: &str) -> Result<libpijul::pristine::InodeMetadata, Self::Error> {self.working_copy.file_metadata(file)}fn read_file(&self, file: &str, buffer: &mut Vec<u8>) -> Result<(), Self::Error> {match self.open_files.get(Utf8Path::new(file)) {Some(open_file) => buffer.extend(open_file.contents.text.bytes()),None => self.working_copy.read_file(file, buffer)?,}Ok(())}fn modified_time(&self, file: &str) -> Result<std::time::SystemTime, Self::Error> {match self.open_files.get(Utf8Path::new(file)) {Some(open_file) => Ok(open_file.contents.modified_time),None => self.working_copy.modified_time(file),}}}
use std::ops::RangeInclusive;use camino::Utf8PathBuf;use libpijul::ArcTxn;use libpijul::ChannelRef;use libpijul::TxnTExt;use libpijul::changestore::ChangeStore;use libpijul::pristine::InodeMetadata;use libpijul::pristine::sanakirja::MutTxn;use libpijul::pristine::sanakirja::SanakirjaError;use libpijul::working_copy::WorkingCopyRead;use crate::file_system::changes::CreditSource;use crate::file_system::changes::FileCredits;use crate::file_system::changes::FileCreditsError;use crate::file_system::changes::Span;use crate::file_system::changes::unrecorded::UnrecordedChangesError;use crate::file_system::open_file::contents::FileContents;pub mod contents;#[derive(Debug, thiserror::Error)]pub enum OpenFileError<C: std::error::Error + 'static> {#[error("failed to check if {path} is tracked: {error:#?}")]CheckIfTracked {path: Utf8PathBuf,error: SanakirjaError,},#[error(transparent)]FileChanges(#[from] UnrecordedChangesError<C>),#[error(transparent)]TrackedFile(#[from] FileCreditsError<C>),}#[derive(Clone, Debug)]pub struct OpenFile {pub contents: FileContents,pub credits: Option<FileCredits>,}impl OpenFile {pub fn open<C, W>(path: Utf8PathBuf,file_contents: String,metadata: InodeMetadata,transaction: &ArcTxn<MutTxn<()>>,channel: &ChannelRef<MutTxn<()>>,change_store: &C,working_copy: &W,) -> Result<Self, OpenFileError<C::Error>>whereC: ChangeStore + Clone + Send + 'static,W: WorkingCopyRead,{let contents = FileContents::new(path.clone(), metadata, file_contents, working_copy);let credits = if transaction.read().is_tracked(path.as_str()).map_err(|error| OpenFileError::CheckIfTracked { path, error })?{Some(FileCredits::new(&contents,transaction,channel,change_store,)?)} else {None};Ok(Self { contents, credits })}pub fn update<C>(&mut self,character_offset: usize,characters_replaced: usize,replacement_text: &str,transaction: &ArcTxn<MutTxn<()>>,channel: &ChannelRef<MutTxn<()>>,change_store: &C,) -> Result<(), UnrecordedChangesError<C::Error>>whereC: ChangeStore + Clone + Send + 'static,{if characters_replaced > 0 {self.contents.text.remove(character_offset..(character_offset + characters_replaced));}if !replacement_text.is_empty() {self.contents.text.insert(character_offset, replacement_text);}if let Some(credits) = &mut self.credits {// TODO: only re-compute spans that were affectedcredits.recompute_spans(&self.contents, transaction, channel, change_store)?;}Ok(())}pub fn credit(&self, lines: RangeInclusive<usize>) -> Vec<Span<CreditSource>> {match &self.credits {Some(credits) => credits.spans_within_lines(lines).collect(),None => Vec::from([Span {value: CreditSource::Untracked,lines,}]),}}pub fn tracked_contents(&self) -> String {self.contents.text.to_string()}}
use std::time::SystemTime;use camino::Utf8PathBuf;use libpijul::pristine::InodeMetadata;use libpijul::working_copy::WorkingCopyRead;use ropey::Rope;#[derive(Debug, thiserror::Error)]pub enum FileContentsError {#[error("Invalid path: expected {expected_path:?}, got {incorrect_path:?}")]InvalidPath {expected_path: Utf8PathBuf,incorrect_path: Utf8PathBuf,},}#[derive(Clone, Debug)]pub struct FileContents {// TODO: path shouldn't be stored herepub path: Utf8PathBuf,pub metadata: InodeMetadata,pub modified_time: SystemTime,pub text: Rope,}impl FileContents {pub fn new<W: WorkingCopyRead>(path: Utf8PathBuf,metadata: InodeMetadata,contents: String,working_copy: &W,) -> Self {let last_modified_time = working_copy.modified_time(path.as_str()).unwrap_or(SystemTime::now());Self {path,metadata,modified_time: last_modified_time,text: Rope::from(contents),}}}// TODO: implement `WorkingCopyRead` for `EditorWorkingCopy` instead?impl WorkingCopyRead for FileContents {type Error = FileContentsError;fn file_metadata(&self, file: &str) -> Result<InodeMetadata, Self::Error> {if file != self.path.as_str() {return Err(FileContentsError::InvalidPath {expected_path: self.path.clone(),incorrect_path: Utf8PathBuf::from(file),});}Ok(self.metadata)}fn read_file(&self, file: &str, buffer: &mut Vec<u8>) -> Result<(), Self::Error> {if file != self.path.as_str() {return Err(FileContentsError::InvalidPath {expected_path: self.path.clone(),incorrect_path: Utf8PathBuf::from(file),});}buffer.extend(self.text.bytes());Ok(())}fn modified_time(&self, file: &str) -> Result<SystemTime, Self::Error> {if file != self.path.as_str() {return Err(FileContentsError::InvalidPath {expected_path: self.path.clone(),incorrect_path: Utf8PathBuf::from(file),});}Ok(self.modified_time)}}
pub mod changes;pub mod open_file;pub mod working_copy;
use libpijul::change::{Atom, BaseHunk, TextSerError};use libpijul::changestore::ChangeStore;use libpijul::pristine::sanakirja::{MutTxn, SanakirjaError};use libpijul::{ArcTxn, ChannelRef, RecordBuilder};use crate::file_system::changes::Span;use crate::file_system::open_file::contents::{FileContents, FileContentsError};#[derive(Debug, thiserror::Error)]#[error(transparent)]pub enum UnrecordedChangesError<C: std::error::Error + 'static> {ChangeContents(#[from] TextSerError<C>),Globalize(#[from] SanakirjaError),Record(#[from] libpijul::record::RecordError<C, FileContentsError, MutTxn<()>>),}#[derive(Clone, Copy, Debug)]pub enum SpanKind {Replacement {old_line_count: usize,new_line_count: usize,},Addition {lines_added: usize,},Deletion {lines_removed: usize,},}#[derive(Clone, Debug)]pub struct UnrecordedChanges {pub spans: Vec<Span<SpanKind>>,}impl UnrecordedChanges {pub fn new<C>(file: &FileContents,transaction: &ArcTxn<MutTxn<()>>,channel: &ChannelRef<MutTxn<()>>,change_store: &C,) -> Result<Self, UnrecordedChangesError<C::Error>>whereC: ChangeStore + Clone + Send + 'static,{let mut unrecorded_changes = RecordBuilder::new();unrecorded_changes.record(transaction.clone(),libpijul::Algorithm::default(),false, // TODO: check and document&libpijul::DEFAULT_SEPARATOR,channel.clone(),file,change_store,file.path.as_str(),1, // TODO: figure out concurrency model)?;let unrecorded_state = unrecorded_changes.finish();let change_contents = unrecorded_state.contents.lock();let mut unrecorded_spans = Vec::new();// TODO: handle encodingfor hunk in unrecorded_state.actions {let globalized_hunk = hunk.globalize(&*transaction.read())?;match globalized_hunk {BaseHunk::Replacement {change,replacement,local,encoding,} => {let old_contents = libpijul::change::get_change_contents(change_store,&change,&change_contents,)?;let new_contents = libpijul::change::get_change_contents(change_store,&replacement,&change_contents,)?;let old_text = String::from_utf8(old_contents).unwrap();let new_text = String::from_utf8(new_contents).unwrap();let old_line_count = old_text.lines().count().strict_sub(1);let new_line_count = new_text.lines().count().strict_sub(1);let span_start = local.line - 1;unrecorded_spans.push(Span {value: SpanKind::Replacement {old_line_count,new_line_count,},lines: span_start..=span_start.strict_add(new_line_count),});}BaseHunk::Edit {change,local,encoding,} => {let new_contents = libpijul::change::get_change_contents(change_store,&change,&change_contents,)?;let text = String::from_utf8(new_contents).unwrap();let line_count = text.lines().count();let span_start = local.line - 1;// Skip deletions as they don't contribute any spanslet span = if let Atom::EdgeMap(edge) = change&& (edge.edges.is_empty() || edge.edges[0].flag.is_deleted()){Span {value: SpanKind::Deletion {lines_removed: line_count,},lines: span_start..=span_start,}} else {Span {value: SpanKind::Addition {lines_added: line_count,},lines: span_start..=(span_start + line_count - 1),}};unrecorded_spans.push(span);}// TODO: handle conflict resolution// TODO: handle moves_ => {tracing::warn!(message = "Skipping unrecorded hunk", ?globalized_hunk);}}}unrecorded_spans.sort_by_key(|span| *span.lines.start());Ok(Self {spans: unrecorded_spans,})}}
use std::ops::RangeInclusive;use std::sync::OnceLock;use camino::Utf8Path;use libpijul::changestore::ChangeStore;use libpijul::pristine::sanakirja::{MutTxn, SanakirjaError};use libpijul::vertex_buffer::VertexBuffer;use libpijul::{ArcTxn, ChangeId, ChannelRef, TxnTExt, Vertex};use crate::file_system::changes::{CreditSource, Span};#[derive(Debug, thiserror::Error)]pub enum RecordedStateError<C: std::error::Error + 'static> {#[error("unable to find oldest vertex: {0:#?}")]OldestVertex(#[from] libpijul::fs::FsErrorC<C, MutTxn<()>>),#[error("unable to output file: {0:#?}")]OutputFile(#[from] libpijul::output::FileError<C, MutTxn<()>>),#[error("unable to get external hash for {change_id:#?}")]ExternalHash {change_id: libpijul::pristine::ChangeId,error: libpijul::pristine::TxnErr<SanakirjaError>,},#[error("no matching external hash for change ID: {0:#?}")]MissingExternalHash(libpijul::pristine::ChangeId),#[error("unable to get hash from changestore: {0:#?}")]ChangeStore(C),}// TODO: reference diff::vertex_buffer::Diff file:///home/finchie/Projects/Pijul/pijul/target/doc/libpijul/diff/vertex_buffer/struct.Diff.htmlstruct ChangesBuffer {introduced_by: OnceLock<ChangeId>,original_contents: String,spans: Vec<Span<ChangeId>>,}// TODO: don't assume encoding#[derive(Clone, Debug)]pub struct RecordedState {pub introduced_by: ChangeId,pub original_contents: String,pub spans: Vec<Span<ChangeId>>,}impl RecordedState {pub fn new<C>(path: &Utf8Path,transaction: &ArcTxn<MutTxn<()>>,channel: &ChannelRef<MutTxn<()>>,change_store: &C,) -> Result<Self, RecordedStateError<C::Error>>whereC: ChangeStore,{// TODO: handle ambiguity (possibly when there is a path conflict?)let (oldest_vertex, _ambiguous) =transaction.read().follow_oldest_path(change_store, channel, path.as_str())?;let mut changes_buffer = ChangesBuffer {introduced_by: OnceLock::new(),original_contents: String::new(),spans: Vec::new(),};libpijul::output::output_file(change_store,transaction,channel,oldest_vertex,&mut changes_buffer,)?;Ok(Self {introduced_by: changes_buffer.introduced_by.take().unwrap(),original_contents: changes_buffer.original_contents,spans: changes_buffer.spans,})}pub fn spans_within_lines(&self,untracked_line_range: RangeInclusive<usize>,offset: isize,) -> impl Iterator<Item = Span<CreditSource>> {let tracked_line_range = untracked_line_range.start().strict_add_signed(offset)..=untracked_line_range.end().strict_add_signed(offset);Span::spans_within_lines(&self.spans, tracked_line_range).map(move |span| Span {value: CreditSource::Tracked(span.value),lines: (span.lines.start().strict_sub_signed(offset))..=(span.lines.end().strict_sub_signed(offset)),})}}impl VertexBuffer for ChangesBuffer {fn output_line<E, F>(&mut self, vertex: Vertex<ChangeId>, contents: F) -> Result<(), E>whereE: From<std::io::Error>,F: FnOnce(&mut [u8]) -> Result<(), E>,{// The first "line" output is an empty line representing the change that introduced the fileif self.introduced_by.get().is_none() {self.introduced_by.set(vertex.change).unwrap();assert!(vertex.is_empty());return Ok(());}// The final "line" output is an empty line with an empty change IDif vertex.change.0.as_u64() == 0 {return Ok(());}assert!(!vertex.is_empty());assert!(!vertex.is_root());let mut buffer = vec![0; vertex.end - vertex.start];contents(&mut buffer)?;let contents = String::from_utf8(buffer).unwrap();// Keep track of the original contentsself.original_contents.push_str(&contents);// Add the starting line and line count of the contents affected by this change IDlet start_line = match self.spans.last() {Some(previous_span) => previous_span.next_span_start(),None => 0,};let length = contents.lines().count();self.spans.push(Span {value: vertex.change,lines: start_line..=(start_line + length - 1),});Ok(())}// TODO: handle all the conflict markers independentlyfn output_conflict_marker<C: libpijul::changestore::ChangeStore>(&mut self,s: &str,id: usize,sides: Option<(&C, &[&libpijul::Hash])>,) -> Result<(), std::io::Error> {todo!("Conflict markers")}}
use std::ops::RangeInclusive;use libpijul::changestore::ChangeStore;use libpijul::pristine::sanakirja::MutTxn;use libpijul::{ArcTxn, ChangeId, ChannelRef};use crate::file_system::changes::recorded::RecordedStateError;use crate::file_system::changes::unrecorded::UnrecordedChangesError;use crate::file_system::open_file::contents::FileContents;pub mod recorded;pub mod unrecorded;#[derive(Clone, Debug)]pub struct Span<T: std::fmt::Debug> {pub value: T,pub lines: RangeInclusive<usize>,}impl<T: Clone + std::fmt::Debug> Span<T> {pub fn next_span_start(&self) -> usize {self.lines.end() + 1}pub fn spans_within_lines(spans: &[Self],line_range: RangeInclusive<usize>,) -> impl Iterator<Item = Self> {debug_assert!(line_range.start() <= line_range.end(),"Invalid range: {line_range:#?}");debug_assert!(spans.is_sorted_by_key(|span| span.lines.start()));let lines_start = *line_range.start();let lines_end = *line_range.end();spans.iter().skip_while(move |span| *span.lines.end() < lines_start).take_while(move |span| *span.lines.start() <= lines_end).filter_map(move |span| {let span_start = *span.lines.start().max(&lines_start);let span_end = *span.lines.end().min(&lines_end);if span_end >= span_start {Some(Span {value: span.value.clone(),lines: span_start..=span_end,})} else {None}})}}#[derive(Clone, Debug, PartialEq, Eq)]pub enum CreditSource {Tracked(ChangeId),Untracked,}#[derive(Debug, thiserror::Error)]pub enum FileCreditsError<C: std::error::Error + 'static> {#[error("unable to get tracked file state: {0:?}")]TrackedState(#[from] RecordedStateError<C>),#[error("unable to get untracked changes: {0:?}")]UntrackedChanges(#[from] UnrecordedChangesError<C>),}#[derive(Clone, Debug)]pub struct FileCredits {pub recorded_state: recorded::RecordedState,pub spans: Vec<Span<CreditSource>>,}impl FileCredits {pub fn new<C>(file: &FileContents,transaction: &ArcTxn<MutTxn<()>>,channel: &ChannelRef<MutTxn<()>>,change_store: &C,) -> Result<Self, FileCreditsError<C::Error>>whereC: ChangeStore + Clone + Send + 'static,{let state = recorded::RecordedState::new(&file.path, transaction, channel, change_store)?;let mut tracked_file = Self {recorded_state: state,spans: Vec::new(),};tracked_file.recompute_spans(file, transaction, channel, change_store)?;Ok(tracked_file)}pub fn recompute_spans<C>(&mut self,file: &FileContents,transaction: &ArcTxn<MutTxn<()>>,channel: &ChannelRef<MutTxn<()>>,change_store: &C,) -> Result<(), UnrecordedChangesError<C::Error>>whereC: ChangeStore + Clone + Send + 'static,{let untracked_changes =unrecorded::UnrecordedChanges::new(file, transaction, channel, change_store)?;let mut merged_spans = Vec::new();let mut untracked_spans = untracked_changes.spans.iter().peekable();let mut current_offset: isize = 0;let mut incomplete_span_start: Option<usize> = Some(0);while let Some(untracked_span) = untracked_spans.next() {if let Some(incomplete_span_start) = incomplete_span_start.take()&& *untracked_span.lines.start() > incomplete_span_start{merged_spans.extend(self.recorded_state.spans_within_lines(incomplete_span_start..=(untracked_span.lines.start().strict_sub(1)),current_offset,));}match untracked_span.value {unrecorded::SpanKind::Replacement {old_line_count,new_line_count,} => {merged_spans.push(Span {value: CreditSource::Untracked,lines: untracked_span.lines.clone(),});let replacement_line_offset =(new_line_count as isize).strict_add_unsigned(old_line_count);current_offset = current_offset.strict_add(replacement_line_offset);}unrecorded::SpanKind::Addition { lines_added } => {merged_spans.push(Span {value: CreditSource::Untracked,lines: untracked_span.lines.clone(),});current_offset = current_offset.strict_sub_unsigned(lines_added);}unrecorded::SpanKind::Deletion { lines_removed } => {// Deletions don't contribute any spans, only change the offset// to skip the deleted lines.current_offset = current_offset.strict_add_unsigned(lines_removed);incomplete_span_start = Some(*untracked_span.lines.start());}}if let Some(next_untracked_span) = untracked_spans.peek()&& *next_untracked_span.lines.start() > untracked_span.next_span_start(){merged_spans.extend(self.recorded_state.spans_within_lines(untracked_span.next_span_start()..=(next_untracked_span.lines.start() - 1),current_offset,));}}let file_length = file.text.len_lines(ropey::LineType::LF_CR).strict_sub(1);if let Some(final_span) = merged_spans.last()&& *final_span.lines.end() < file_length.strict_sub(1){merged_spans.extend(self.recorded_state.spans_within_lines((final_span.lines.end() + 1)..=file_length.strict_sub(1),current_offset,));}if merged_spans.is_empty() {merged_spans.extend(self.recorded_state.spans_within_lines(0..=file_length.strict_sub(1), 0),);}// If the final line ends in a newline, text editors will allow selecting the "next line"// For example: `Line 1\nLine 2\n` will be rendered as:// ```// Line 1// Line 2//// ```// So extend the span of line 2 (index 1) to include this empty lineif let Some(final_span) = merged_spans.last_mut()&& let Some(final_character) = file.text.chars().last()&& final_character == '\n'{let start_line = *final_span.lines.start();let end_line = *final_span.lines.end();final_span.lines = start_line..=(end_line + 1);}// Check the spans were generated correctlyif cfg!(debug_assertions) {let mut span_windows = merged_spans.windows(2);// Span ranges must be in orderwhile let Some([first, second]) = span_windows.next() {assert_eq!(first.lines.end() + 1,*second.lines.start(),"Invalid span ranges: {merged_spans:#?}")}// Entire file is coveredlet last_span_line = merged_spans.last().map(|span| *span.lines.end()).unwrap_or(0);let last_text_lines = file.text.len_lines(ropey::LineType::LF_CR) - 1;assert_eq!(last_span_line, last_text_lines,"Incorrect span end (got {last_span_line}, expected {last_text_lines}): {merged_spans:#?}");}// Combine consecutive spans of the same type into a single spanmerged_spans =merged_spans.into_iter().fold(Vec::new(), |mut previous_spans, current_span| {if let Some(previous_span) = previous_spans.last_mut()&& previous_span.value == current_span.value{let previous_start = *previous_span.lines.start();previous_span.lines = previous_start..=*current_span.lines.end();} else {previous_spans.push(current_span);}previous_spans});self.spans = merged_spans;Ok(())}// TODO: check that range is within limits?pub fn spans_within_lines(&self,line_range: RangeInclusive<usize>,) -> impl Iterator<Item = Span<CreditSource>> {Span::spans_within_lines(&self.spans, line_range)}}
use std::cell::OnceCell;use std::collections::HashMap;use libpijul::change::ChangeHeader;use libpijul::changestore::ChangeStore;use libpijul::pristine::TxnErr;use libpijul::pristine::sanakirja::{MutTxn, SanakirjaError};use libpijul::{ArcTxn, ChangeId, ChannelRef, GraphTxnT, TxnTExt};#[derive(Debug, thiserror::Error)]pub enum ChannelStateError<C: std::error::Error + 'static> {#[error("unable to iterate changes: {0:#?}")]ReverseLog(SanakirjaError),#[error("encountered error while iterating log: {0:#?}")]Item(SanakirjaError),#[error("unable to get external hash: {0:#?}")]InternalHash(TxnErr<SanakirjaError>),#[error("unable to read changes: {0:#?}")]ChangeStore(C),}pub struct ChannelState {root_change: ChangeId,changes: HashMap<ChangeId, ChangeHeader>,}impl ChannelState {pub fn new<C>(transaction: &ArcTxn<MutTxn<()>>,channel: &ChannelRef<MutTxn<()>>,change_store: &C,) -> Result<Self, ChannelStateError<C::Error>>whereC: ChangeStore + Clone + Send + 'static,{let mut changes = HashMap::new();let mut root_change = OnceCell::new();// TODO: authors// let mut authors = HashSet::new();let read_transaction = transaction.read();let mut reverse_log = read_transaction.reverse_log(&*channel.read(), None).map_err(ChannelStateError::ReverseLog)?.peekable();while let Some(log_result) = reverse_log.next() {// TODO: merklelet (_, (hash, merkle)) = log_result.map_err(ChannelStateError::Item)?;let change_id = *read_transaction.get_internal(hash).map_err(ChannelStateError::InternalHash)?.unwrap();// TODO: `change_id.is_root()` is broken?if reverse_log.peek().is_none() {root_change.set(change_id).unwrap();} else {let change_header = change_store.get_header(&hash.into()).map_err(ChannelStateError::ChangeStore)?;dbg!(&change_header.authors);changes.try_insert(change_id, change_header).unwrap();}}Ok(ChannelState {root_change: root_change.take().unwrap(),changes,})}pub fn get_change_header(&self, change_id: &ChangeId) -> Option<&ChangeHeader> {self.changes.get(change_id)}pub fn iter_change_headers(&self) -> impl Iterator<Item = &ChangeHeader> {self.changes.values()}}
use std::collections::HashMap;use std::collections::hash_map::Entry;use std::fs::File;use camino::Utf8Path;use libpijul::change::ChangeHeader;use crate::channel_state::ChannelState;#[derive(Clone, Debug)]pub enum AuthorSource {Local(pijul_identity::Complete),Remote(pijul_identity::Complete),Unknown(String),}pub struct Authors {authors: HashMap<String, AuthorSource>,}impl Authors {pub fn new(channel_state: &ChannelState, dot_directory: &Utf8Path) -> Self {let mut authors = HashMap::new();let repository_identities_path = dot_directory.join("identities");match pijul_identity::Complete::load_all() {Ok(local_identities) => {for local_identity in local_identities {let public_key_signature = local_identity.public_key.key.clone();match authors.entry(public_key_signature.clone()) {Entry::Occupied(occupied_entry) => {tracing::error!(message = "Duplicate local identities found",public_key_signature,previous_author = ?occupied_entry.get(),);}Entry::Vacant(vacant_entry) => {vacant_entry.insert(AuthorSource::Local(local_identity));}}}}Err(error) => tracing::error!(message = "Unable to load local identities", ?error),}for change_header in channel_state.iter_change_headers() {for serialized_author in &change_header.authors {match serialized_author.0.get("key") {Some(public_key_signature) => {if let Entry::Vacant(vacant_entry) =authors.entry(public_key_signature.to_owned()){// Try to read from `.pijul/identities/{public_key_signature}`let identity_path =repository_identities_path.join(public_key_signature);let author_source = match File::open(&identity_path) {Ok(identity_file) => match serde_json::from_reader(identity_file) {Ok(remote_identity) => AuthorSource::Remote(remote_identity),Err(error) => {tracing::error!(message = "Failed to deserialize identity file",?identity_path,?error);AuthorSource::Unknown(public_key_signature.to_owned())}},Err(error) => {tracing::error!(message = "Failed to open identity file",?identity_path,?error);AuthorSource::Unknown(public_key_signature.to_owned())}};vacant_entry.insert(author_source);}}None => {tracing::warn!(message = "Author missing `key` field", ?serialized_author);}}}}Self { authors }}pub fn authors_for_change(&self, change_header: &ChangeHeader) -> Vec<&AuthorSource> {let mut authors = Vec::new();for serialized_author in &change_header.authors {match serialized_author.0.get("key") {Some(public_key_signature) => match self.authors.get(public_key_signature) {Some(author) => {authors.push(author);}None => tracing::error!(message = "No matching author for key",public_key_signature,?change_header),},None => {tracing::warn!(message = "Author missing `key` field", ?serialized_author);}}}authors}}
[package]name = "pijul-extension"version = "0.1.0"edition = "2024"[dependencies]camino.workspace = truecanonical-path.workspace = truelibpijul.workspace = truepath-slash.workspace = truepijul-identity.workspace = trueropey.workspace = trueserde_json.workspace = truethiserror.workspace = truetracing.workspace = true
{"compilerOptions": {"module": "Node16","target": "ES2022","outDir": "out","lib": ["ES2022"],"sourceMap": true,"rootDir": "src","strict": true /* enable all strict type-checking options *//* Additional Checks */// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */// "noUnusedParameters": true, /* Report errors on unused parameters. */}}
use napi::bindgen_prelude;use napi::bindgen_prelude::JsObjectValue;use super::macros::{event_handler, namespace_field_getter, namespace_function, register_provider};use super::{TextDocument, TextDocumentChangeEvent, TextDocumentContentProvider, Uri, WorkspaceFolder,WorkspaceFoldersChangeEvent,};event_handler!("workspace","onDidChangeTextDocument",on_did_change_text_document(TextDocumentChangeEvent));event_handler!("workspace","onDidChangeWorkspaceFolders",on_did_change_workspace_folders(WorkspaceFoldersChangeEvent));namespace_field_getter! {"workspace" {"textDocuments": get_text_documents -> Vec<TextDocument<'env>>;"workspaceFolders": get_workspace_folders -> Vec<WorkspaceFolder<'env>>;}}namespace_function! {"workspace" {"getWorkspaceFolder":get_workspace_folder(uri: &Uri,) -> Option<WorkspaceFolder<'env>>;}}register_provider!("workspace","registerTextDocumentContentProvider",register_text_document_content_provider(scheme: &str, provider: TextDocumentContentProvider<'env>));
use napi::bindgen_prelude;use napi::bindgen_prelude::JsObjectValue;use super::macros::{event_handler, namespace_field_getter, namespace_function, register_provider};use super::{DecorationRenderOptions, FileDecorationProvider, TextEditor, TextEditorDecorationType,TextEditorSelectionChangeEvent,};event_handler!("window","onDidChangeTextEditorSelection",on_did_change_text_editor_selections(TextEditorSelectionChangeEvent));event_handler!("window","onDidChangeVisibleTextEditors",on_did_change_visible_text_editors(Vec<TextEditor>));namespace_field_getter! {"window" {"activeTextEditor": get_active_text_editor -> Option<TextEditor<'env>>;"visibleTextEditors": get_visible_text_editors -> Vec<TextEditor<'env>>;}}namespace_function! {"window" {"createTextEditorDecorationType":create_text_editor_decoration_type(render_options: DecorationRenderOptions,) -> TextEditorDecorationType<'env>;}}register_provider!("window", "registerFileDecorationProvider", register_file_decoration_provider(provider: FileDecorationProvider));pub fn create_log_output_channel<'env>(env: &napi::Env,name: &str,) -> Result<bindgen_prelude::Object<'env>, napi::Error> {let vscode_object = super::VscodeContext::vscode(env)?;let window: bindgen_prelude::Object = vscode_object.get_named_property("window")?;let function_prototype: bindgen_prelude::Function<bindgen_prelude::FnArgs<(&str, bindgen_prelude::Object)>,bindgen_prelude::Object,> = window.get_named_property("createOutputChannel")?;let mut options = bindgen_prelude::Object::new(env)?;options.set_named_property("log", true)?;let output_channel =function_prototype.apply(window, bindgen_prelude::FnArgs::from((name, options)))?;Ok(output_channel)}
use napi::bindgen_prelude;use napi::bindgen_prelude::JsObjectValue;use super::macros::namespace_function;use super::{SourceControl, Uri};namespace_function! {"scm" {"createSourceControl":create_source_control(id: &str,label: &str,root_uri: &Uri,) -> SourceControl<'env>;}}
use napi::bindgen_prelude;use super::macros::object_reference;use super::{SourceControl, SourceControlResourceGroup, TextEditor, TextEditorDecorationType};object_reference!(SourceControlRef: SourceControl);object_reference!(SourceControlResourceGroupRef: SourceControlResourceGroup);object_reference!(TextEditorRef: TextEditor);object_reference!(TextEditorDecorationTypeRef: TextEditorDecorationType);
// TODO: `FromNapiValue` should also validate// TODO: either completely remove/embrace `FnArgs`use std::sync::MappedMutexGuard;use std::sync::{Mutex, MutexGuard, OnceLock};use napi::JsValue;use napi::bindgen_prelude;use napi::bindgen_prelude::{FromNapiValue, JsObjectValue, ToNapiValue, TypeName, ValidateNapiValue,};use napi_sys::{napi_env, napi_value};use macros::{class_wrapper, empty_function_caller, field_getter, field_setter, function_caller,function_setter, interface_builder, static_class_method,};// Internal/helper modulespub mod log;mod macros;pub mod reference;// VSCode API namespacespub mod scm;pub mod window;pub mod workspace;static CONTEXT: Mutex<OnceLock<VscodeContext>> = Mutex::new(OnceLock::new());struct VscodeContext {vscode: bindgen_prelude::ObjectRef,extension_context: bindgen_prelude::ObjectRef,}impl VscodeContext {fn inner() -> Result<MappedMutexGuard<'static, Self>, napi::Error> {let mutex_guard = CONTEXT.lock().map_err(|_error| {napi::Error::from_reason("vscode_sys::Context mutex has been poisoned")})?;MutexGuard::filter_map(mutex_guard, |guarded_value| match guarded_value.get_mut() {Some(vscode_context) => Some(vscode_context),None => None,}).map_err(|_empty_guard| {napi::Error::new(napi::Status::GenericFailure, "`vscode` object is not set")})}fn extension_context<'env>(env: &'env napi::Env,) -> Result<bindgen_prelude::Object<'env>, napi::Error> {let context = Self::inner()?;context.extension_context.get_value(env)}fn vscode<'env>(env: &'env napi::Env) -> Result<bindgen_prelude::Object<'env>, napi::Error> {let context = Self::inner()?;context.vscode.get_value(env)}}pub fn activate(vscode_object: &bindgen_prelude::Object,extension_context: &bindgen_prelude::Object,) -> Result<(), napi::Error> {let mutex_guard = CONTEXT.lock().map_err(|_error| {napi::Error::from_reason("vscode_sys::Context mutex was poisoned before it could be initialized",)})?;let context = VscodeContext {vscode: vscode_object.create_ref()?,extension_context: extension_context.create_ref()?,};mutex_guard.set(context).map_err(|_error| {napi::Error::from_reason("`activate()` has already been called, but must be called exactly once",)})?;Ok(())}class_wrapper!(FileDecoration(badge: &str, tooltip: &str, color: &ThemeColor));class_wrapper!(MarkdownString(value: &str, support_theme_icons: bool));class_wrapper!(Position(line: u32, character: u32));field_getter! {Position {"line": get_line -> u32;}}class_wrapper!(Range(start: &Position<'env>, end: &Position<'env>));class_wrapper!(Selection(anchor: &Position<'env>, active: &Position<'env>));field_getter! {Selection {"start": get_start -> Position<'env>;"end": get_end -> Position<'env>;}}class_wrapper!(ThemeColor(id: &str));// TODO: private constructorclass_wrapper!(Uri(scheme: &str, authority: &str, path: &str, query: &str, fragment: &str));field_getter! {Uri {"fsPath": get_fs_path -> String;"scheme": get_scheme -> String;}}empty_function_caller! {Uri {"toString":to_string() -> String;}}function_caller! {Uri {"with":with(change: UriWithChange,) -> Uri<'env>;}}static_class_method! {Uri {"file":file(path: &str,) -> Uri<'env>;}}interface_builder! {DecorationOptions {("range": Range, range: &Range),}("hoverMessage", hover_message: &MarkdownString),("renderOptions", render_options: DecorationInstanceRenderOptions),}interface_builder! {DecorationInstanceRenderOptions {}("after", after: ThemableDecorationAttachmentRenderOptions),}interface_builder! {DecorationRenderOptions {}("after", after: ThemableDecorationAttachmentRenderOptions),}interface_builder! {FileDecorationProvider {F: set_provide_file_decoration =provide_file_decoration(uri: Uri,cancellation_token: bindgen_prelude::Object) -> FileDecoration<'function_context>;}}function_setter! {FileDecorationProvider {"provideFileDecoration" {set_provide_file_decoration(uri: Uri,cancellation_token: bindgen_prelude::Object) -> FileDecoration<'function_context>;bindgen_prelude::ObjectRef = |returned_result: Option<FileDecoration>| returned_result.map(|object| object.inner.create_ref()).transpose();}}}interface_builder! {QuickDiffProvider {}}function_setter! {QuickDiffProvider {"provideOriginalResource" {set_provide_original_resource(uri: Uri<'function_context>,cancellation_token: bindgen_prelude::Object<'function_context>) -> Uri<'function_context>;bindgen_prelude::ObjectRef = |returned_result: Option<Uri>| returned_result.map(|object| object.inner.create_ref()).transpose();}}}interface_builder! {SourceControl {}}field_setter! {SourceControl {"quickDiffProvider": set_quick_diff_provider(QuickDiffProvider);}}function_caller! {SourceControl {"createResourceGroup":create_resource_group(id: &str,label: &str,) -> SourceControlResourceGroup<'env>;}}interface_builder! {SourceControlResourceGroup {}}field_setter! {SourceControlResourceGroup {"resourceStates": set_resource_states(Vec<SourceControlResourceState>);}}interface_builder! {SourceControlResourceState {("resourceUri": Uri, resource_uri: &Uri),}}interface_builder! {TextDocument {}}field_getter! {TextDocument {"uri": get_uri -> Uri<'env>;}}function_caller! {TextDocument {"getText":get_text(range: Option<Range>,) -> String;}}interface_builder! {TextDocumentChangeEvent {}}field_getter! {TextDocumentChangeEvent {"document": get_document -> TextDocument<'env>;"contentChanges": get_content_changes -> Vec<TextDocumentContentChangeEvent<'env>>;}}interface_builder! {TextDocumentContentChangeEvent {}}field_getter! {TextDocumentContentChangeEvent {"rangeOffset": get_range_offset -> u32;"rangeLength": get_range_length -> u32;"text": get_text -> String;}}interface_builder! {TextDocumentContentProvider {F: set_provide_text_document_content =provide_text_document_content(uri: Uri<'function_context>,cancellation_token: bindgen_prelude::Object<'function_context>) -> String;}}function_setter! {TextDocumentContentProvider {"provideTextDocumentContent" {set_provide_text_document_content(uri: Uri<'function_context>,cancellation_token: bindgen_prelude::Object<'function_context>) -> String;String = |returned_result: Option<String>| Ok(returned_result);}}}interface_builder! {TextEditor {}}field_getter! {TextEditor {"document": get_document -> TextDocument<'env>;"selections": get_selections -> Vec<Selection<'env>>;}}function_caller! {TextEditor {"setDecorations":set_decorations(decoration_type: TextEditorDecorationType,options: Vec<DecorationOptions>,) -> ();}}interface_builder! {TextEditorDecorationType {}}interface_builder! {TextEditorSelectionChangeEvent {}}field_getter! {TextEditorSelectionChangeEvent {"textEditor": get_text_editor -> TextEditor<'env>;"selections": get_selections -> Vec<Selection<'env>>;}}interface_builder! {ThemableDecorationAttachmentRenderOptions {}("color", color: &ThemeColor),("contentText", content_text: &str),("margin", margin: &str),}interface_builder! {UriWithChange {}("scheme", scheme: &str),("authority", authority: &str),("path", path: &str),("query", query: &str),("fragment", fragment: &str),}interface_builder! {WorkspaceFolder {}}field_getter! {WorkspaceFolder {"uri": get_uri -> Uri<'env>;}}interface_builder! {WorkspaceFoldersChangeEvent {}}field_getter! {WorkspaceFoldersChangeEvent {"added": get_added -> Vec<WorkspaceFolder<'env>>;"removed": get_removed -> Vec<WorkspaceFolder<'env>>;}}
macro_rules! register_provider {($namespace:literal, $function_js_name:literal,$function_rust_name:ident($($argument_name:ident: $argument_type:ty),+)) => {// TODO: error handlingpub fn $function_rust_name<'env>(env: &'env napi::Env,extension_context: &bindgen_prelude::Object,$($argument_name: $argument_type),+) -> Result<(), napi::Error> {let vscode_object = super::VscodeContext::vscode(env)?;let namespace: bindgen_prelude::Object = vscode_object.get_named_property($namespace)?;let js_register_provider: bindgen_prelude::Function<bindgen_prelude::FnArgs<($($argument_type,)+)>,bindgen_prelude::Object,> = namespace.get_named_property($function_js_name)?;let subscription = js_register_provider.apply(namespace, bindgen_prelude::FnArgs::from(($($argument_name,)+)))?;let mut subscriptions: bindgen_prelude::Array =extension_context.get_named_property("subscriptions")?;subscriptions.insert(subscription)?;Ok(())}};}pub(crate) use register_provider;
macro_rules! object_reference {($reference_name:ident: $owned_name:ident) => {pub struct $reference_name {inner: bindgen_prelude::ObjectRef,}impl $reference_name {pub fn get_inner<'env>(&self,env: &'env napi::Env,) -> Result<$owned_name<'env>, napi::Error> {let inner = self.inner.get_value(env)?;Ok($owned_name { inner })}}impl<'env> $owned_name<'env> {pub fn create_ref(&self) -> Result<$reference_name, napi::Error> {let inner = self.inner.create_ref()?;Ok($reference_name { inner })}}};}pub(crate) use object_reference;
pub mod field;pub mod function;
macro_rules! function_setter {($interface_name:ident {$($function_js_name:literal {$setter_name:ident($($function_argument_name:ident: $function_argument_type:ty),*) -> $function_borrowed_return_type:ty;// TODO: remove this hack and properly handle types$function_owned_return_type:ty = $function_create_owned_return_type:expr;})*}) => {impl<'env> $interface_name<'env> {$(pub fn $setter_name<F>(&mut self,env: &napi::Env,function_callback: F,) -> Result<(), napi::Error>whereF: for<'function_context> Fn(&'function_context napi::Env,$($function_argument_type,)*) -> Result<Option<$function_borrowed_return_type>,napi::Error,> + 'static,{let function_callback: bindgen_prelude::Function<// Treat arguments as `Unknown` to make sure type errors are handled inside the closurebindgen_prelude::Unknown,// Extend the return type's lifetime beyond the lifetime of the closureOption<$function_owned_return_type>,> =env.create_function_from_closure($function_js_name, move |function_context| {// TODO: error handlinglet ($($function_argument_name),*) = function_context.args()?;let returned_result =function_callback(function_context.env, $($function_argument_name),*)?;$function_create_owned_return_type(returned_result)})?;self.inner.set_named_property($function_js_name, function_callback)?;Ok(())})*}};}pub(crate) use function_setter;
pub mod caller;pub mod setter;
macro_rules! empty_function_caller {($interface_name:ident {$($empty_function_js_name:literal:$empty_function_rust_name:ident() -> $empty_function_return_type:ty;)*}) => {impl<'env> $interface_name<'env> {$(pub fn $empty_function_rust_name(&self,) -> Result<$empty_function_return_type, napi::Error> {let js_function: bindgen_prelude::Function<(),$empty_function_return_type,> = self.inner.get_named_property($empty_function_js_name)?;js_function.apply(self.inner, ())})*}};}macro_rules! function_caller {($interface_name:ident {$($function_js_name:literal:$function_rust_name:ident($($function_argument_name:ident: $function_argument_type:ty,)+) -> $function_return_type:ty;)*}) => {impl<'env> $interface_name<'env> {$(pub fn $function_rust_name(&self,$($function_argument_name: $function_argument_type),+) -> Result<$function_return_type, napi::Error> {let js_function: bindgen_prelude::Function<bindgen_prelude::FnArgs<($($function_argument_type,)+)>,$function_return_type,> = self.inner.get_named_property($function_js_name)?;js_function.apply(self.inner, bindgen_prelude::FnArgs::from(($($function_argument_name,)+)))})*}};}pub(crate) use empty_function_caller;pub(crate) use function_caller;
macro_rules! field_setter {($object_name:ident {$($field_js_name:literal: $setter_name:ident($field_type:ty);)*}) => {impl<'env> $object_name<'env> {$(pub fn $setter_name(&mut self, value: $field_type) -> Result<(), napi::Error> {self.inner.set_named_property($field_js_name, value)})*}};}pub(crate) use field_setter;
mod getter;mod setter;pub(crate) use getter::field_getter;pub(crate) use setter::field_setter;
macro_rules! field_getter {($object_name:ident {$($field_js_name:literal: $getter_name:ident -> $field_type:ty;)*}) => {impl<'env> $object_name<'env> {$(pub fn $getter_name(&self) -> Result<$field_type, napi::Error> {self.inner.get_named_property($field_js_name)})*}};}pub(crate) use field_getter;
pub mod field_getter;pub mod function;
macro_rules! namespace_function {($namespace:literal {$($function_js_name:literal: $function_rust_name:ident($($argument_name:ident: $argument_type:ty,)*) -> $return_type:ty;)*}) => {$(pub fn $function_rust_name<'env>(env: &napi::Env,$($argument_name: $argument_type),*) -> Result<$return_type, napi::Error> {let vscode_object = super::VscodeContext::vscode(env)?;let namespace: bindgen_prelude::Object = vscode_object.get_named_property($namespace)?;let function_prototype: bindgen_prelude::Function<bindgen_prelude::FnArgs<($($argument_type,)*)>,$return_type,> = namespace.get_named_property($function_js_name)?;function_prototype.apply(namespace,bindgen_prelude::FnArgs::from(($($argument_name,)*)),)})*};}pub(crate) use namespace_function;
macro_rules! namespace_field_getter {($namespace:literal {$($field_js_name:literal: $function_name:ident -> $field_type:ty;)*}) => {$(pub fn $function_name<'env>(env: &'env napi::Env) -> Result<$field_type, napi::Error> {let vscode_object = super::VscodeContext::vscode(env)?;let window: bindgen_prelude::Object = vscode_object.get_named_property($namespace)?;window.get_named_property($field_js_name)})*};}pub(crate) use namespace_field_getter;
mod class;mod event_handler;mod interface_builder;mod namespace;mod object;mod object_reference;mod register_provider;pub(super) use class::static_method::static_class_method;pub(super) use class::wrapper::class_wrapper;pub(super) use event_handler::event_handler;pub(super) use interface_builder::interface_builder;pub(super) use namespace::field_getter::namespace_field_getter;pub(super) use namespace::function::namespace_function;pub(super) use object::field::field_getter;pub(super) use object::field::field_setter;pub(super) use object::function::caller::empty_function_caller;pub(super) use object::function::caller::function_caller;pub(super) use object::function::setter::function_setter;pub(super) use object_reference::object_reference;pub(super) use register_provider::register_provider;
macro_rules! interface_builder {($interface_name:ident {$(($required_field_js_name:literal: $required_field_js_type:ty,$required_field_rust_name:ident: $required_field_rust_type:ty),)*$($required_function_generic:ident: $required_function_setter:ident =$required_function_rust_name:ident($($required_function_argument_name:ident: $required_function_argument_type:ty),*) -> $required_function_return_type:ty;)*}$(($optional_field_js_name:literal, $optional_field_rust_name:ident: $optional_field_type:ty),)*) => {#[derive(Clone, Copy)]pub struct $interface_name<'env> {inner: ::napi::bindgen_prelude::Object<'env>}impl<'env> $interface_name<'env> {pub fn new<$($required_function_generic),*>(env: &napi::Env,$($required_field_rust_name: $required_field_rust_type),*$($required_function_rust_name: $required_function_generic),*) -> Result<Self, napi::Error>where$($required_function_generic: for<'function_context> Fn(&'function_context napi::Env,$($required_function_argument_type,)*) -> Result<Option<$required_function_return_type>,napi::Error,> + 'static,)*{// TODO: generate more idiomatic code depending on if the object actually gets mutated#[allow(unused_mut)]let mut builder = Self {inner: bindgen_prelude::Object::new(env)?,};// TODO: use Rust setters here$(builder.inner.set_named_property($required_field_js_name, $required_field_rust_name)?;)*$(builder.$required_function_setter(env, $required_function_rust_name)?;)*Ok(builder)}$(pub fn $optional_field_rust_name(mut self, $optional_field_rust_name: $optional_field_type) -> Result<Self, ::napi::Error> {self.inner.set_named_property($optional_field_js_name, $optional_field_rust_name)?;Ok(self)})*}impl<'env> bindgen_prelude::ToNapiValue for &$interface_name<'env> {unsafe fn to_napi_value(env: napi_sys::napi_env, val: Self) -> Result<napi_sys::napi_value, napi::Error> {unsafe { bindgen_prelude::Object::to_napi_value(env, val.inner) }}}impl<'env> bindgen_prelude::ToNapiValue for $interface_name<'env> {unsafe fn to_napi_value(env: napi_sys::napi_env, val: Self) -> Result<napi_sys::napi_value, napi::Error> {unsafe { bindgen_prelude::Object::to_napi_value(env, val.inner) }}}impl<'env> bindgen_prelude::TypeName for $interface_name<'env> {fn type_name() -> &'static str {bindgen_prelude::Object::type_name()}fn value_type() -> napi::ValueType {bindgen_prelude::Object::value_type()}}// TODO: validate non-optional fieldsimpl<'env> bindgen_prelude::FromNapiValue for $interface_name<'env> {unsafe fn from_napi_value(raw_env: napi_sys::napi_env,napi_val: napi_sys::napi_value,) -> Result<Self, napi::Error> {let inner = unsafe { bindgen_prelude::Object::from_napi_value(raw_env, napi_val) }?;Ok(Self { inner })}}// TODO: validate functionsimpl<'env> bindgen_prelude::ValidateNapiValue for $interface_name<'env> {unsafe fn validate(raw_env: napi_sys::napi_env,raw_interface_value: napi_sys::napi_value,) -> Result<napi_sys::napi_value, napi::Error> {// TODO: only generate when needed#[allow(unused)]let interface = match unsafe {<bindgen_prelude::Object as bindgen_prelude::ValidateNapiValue>::validate(raw_env, raw_interface_value)} {Ok(_validated_object) => bindgen_prelude::Object::from_raw(raw_env, raw_interface_value),Err(error) => {return Err(napi::Error::from_reason(format!("{} should be an Object: {}",stringify!($interface_name),error)));}};$(let _property_value: $required_field_js_type = interface.get_named_property($required_field_js_name).map_err(|mut error| {error.reason = format!("Error validating property {} of {}: {}",$required_field_js_name,stringify!($interface_name),error.reason);error})?;)*Ok(raw_interface_value)}}};}pub(crate) use interface_builder;
macro_rules! event_handler {($namespace:literal, $function_js_name:literal, $function_rust_name:ident($event_type:ty)) => {pub fn $function_rust_name<F>(env: &napi::Env,handler: F,// TODO: generic errors) -> Result<(), napi::Error>whereF: for<'function_context> Fn(&'function_context napi::Env,$event_type,) -> Result<(), napi::Error>+ 'static,{let extension_context = super::VscodeContext::extension_context(env)?;let mut subscriptions: bindgen_prelude::Array =extension_context.get_named_property("subscriptions")?;let vscode_object = super::VscodeContext::vscode(env)?;let namespace: bindgen_prelude::Object =vscode_object.get_named_property($namespace)?;let event_creator: bindgen_prelude::Function<bindgen_prelude::Function<$event_type, ()>,// TODO: disposablebindgen_prelude::Object,> = namespace.get_named_property($function_js_name)?;let event_handler_fn: bindgen_prelude::Function<$event_type, ()> = env.create_function_from_closure($function_js_name, move |function_context| {let parent_span = tracing::span!(tracing::Level::TRACE, "event_handler");let _entered_span = parent_span.enter();let event = match function_context.args::<($event_type,)>() {Ok((event,)) => event,Err(error) => {tracing::error!(message = "Invalid arguments",event_handler = $function_js_name,?error);return Ok(());}};if let Err(error) = handler(function_context.env, event) {tracing::error!(message = "Handler exited unsuccessfully",event_handler = $function_js_name,?error);}Ok(())})?;let handler_subscription: bindgen_prelude::Object =event_creator.call(event_handler_fn)?;subscriptions.insert(handler_subscription)?;Ok(())}};}pub(crate) use event_handler;
// TODO: lifetimes when storing in e.g. statics// TODO: either qualify everything or nothingmacro_rules! class_wrapper {($class_name:ident($($argument_name:ident: $argument_type:ty),*)) => {pub struct $class_name<'env> {pub inner: ::napi::bindgen_prelude::Object<'env>,}impl<'env> $class_name<'env> {pub fn new(env: &napi::Env,$($argument_name: $argument_type),*) -> Result<Self, ::napi::Error> {let vscode_object = VscodeContext::vscode(env)?;let constructor_prototype: ::napi::bindgen_prelude::Function<'env,::napi::bindgen_prelude::FnArgs<($($argument_type,)*)>,::napi::bindgen_prelude::Object<'env>,> = vscode_object.get_named_property(stringify!($class_name))?;let class_result: ::napi::bindgen_prelude::Unknown =constructor_prototype.new_instance(::napi::bindgen_prelude::FnArgs::from(($($argument_name,)*)))?;let class_object = ::napi::bindgen_prelude::Object::from_unknown(class_result)?;Ok(Self {inner: class_object,})}}impl<'env> ToNapiValue for &$class_name<'env> {unsafe fn to_napi_value(env: napi_env, val: Self) -> Result<napi_value, napi::Error> {unsafe { bindgen_prelude::Object::to_napi_value(env, val.inner) }}}impl<'env> ToNapiValue for $class_name<'env> {unsafe fn to_napi_value(env: napi_env, val: Self) -> Result<napi_value, napi::Error> {unsafe { bindgen_prelude::Object::to_napi_value(env, val.inner) }}}// TODO: validate non-optional fields// TODO: move validation logic into validatenapivalue???impl<'env> FromNapiValue for $class_name<'env> {unsafe fn from_napi_value(raw_env: napi_sys::napi_env,napi_val: napi_sys::napi_value,) -> Result<Self, napi::Error> {let inner = unsafe { bindgen_prelude::Object::from_napi_value(raw_env, napi_val) }?;Ok(Self { inner })}}impl<'env> TypeName for $class_name<'env> {fn type_name() -> &'static str {bindgen_prelude::Object::type_name()}fn value_type() -> napi::ValueType {bindgen_prelude::Object::value_type()}}impl<'env> ValidateNapiValue for $class_name<'env> {unsafe fn validate(raw_env: napi_sys::napi_env,raw_class: napi_sys::napi_value,) -> Result<napi_sys::napi_value, napi::Error> {let class = match unsafe { <bindgen_prelude::Object as ValidateNapiValue>::validate(raw_env, raw_class) } {Ok(_validated_class) => bindgen_prelude::Object::from_raw(raw_env, raw_class),Err(mut error) => {error.reason = format!("Invalid type for {}: {}", stringify!($class_name), error.reason);return Err(error);}};let env = napi::Env::from_raw(raw_env);let vscode_object = VscodeContext::vscode(&env)?;let constructor: bindgen_prelude::Function<bindgen_prelude::FnArgs<($($argument_type,)*)>, bindgen_prelude::Object> = vscode_object.get_named_property(stringify!($class_name))?;if !class.instanceof(constructor)? {return Err(napi::Error::from_reason(concat!("Object is not an instance of ", stringify!($class_name)),));}// TODO: validate fieldsOk(raw_class)}}};}pub(crate) use class_wrapper;
macro_rules! static_class_method {($class_name:ident {$($function_js_name:literal:$function_rust_name:ident($($function_argument_name:ident: $function_argument_type:ty,)*) -> $function_return_type:ty;)*}) => {impl<'env> $class_name<'env> {$(pub fn $function_rust_name(env: &'env napi::Env,$($function_argument_name: $function_argument_type),*) -> Result<$function_return_type, napi::Error> {let vscode_object = VscodeContext::vscode(env)?;let constructor: ::napi::bindgen_prelude::Function<bindgen_prelude::Unknown,bindgen_prelude::Unknown,> = vscode_object.get_named_property(stringify!($class_name))?;let js_function: bindgen_prelude::Function<bindgen_prelude::FnArgs<($($function_argument_type,)*)>,$function_return_type,> = constructor.get_named_property($function_js_name)?;js_function.apply(constructor, bindgen_prelude::FnArgs::from(($($function_argument_name,)*)))})*}};}pub(crate) use static_class_method;
pub mod static_method;pub mod wrapper;
// TODO: https://github.com/tokio-rs/tracing/blob/main/examples/examples/panic_hook.rs// TODO: Use a custom language ID in `window.createOutputChannel` to better format log messagesuse napi::bindgen_prelude::{self, JsObjectValue};use napi::threadsafe_function::ThreadsafeFunctionCallMode;use tracing::{Level, Subscriber};use tracing_subscriber::Layer;use tracing_subscriber::fmt::{FormatFields, FormattedFields};use tracing_subscriber::layer::SubscriberExt;use tracing_subscriber::registry::LookupSpan;struct VscodeLayer<F>whereF: for<'writer> FormatFields<'writer> + 'static,{threadsafe_function: napi::threadsafe_function::ThreadsafeFunction<(&'static str, String),(),(&'static str, String),napi::Status,false,false,0,>,field_formatter: F,}impl<F> VscodeLayer<F>whereF: for<'writer> FormatFields<'writer> + 'static,{fn new(env: &napi::Env, name: &str, field_formatter: F) -> Result<Self, napi::Error> {let output_channel = super::window::create_log_output_channel(env, name)?;let threadsafe_function: bindgen_prelude::Function<(&str, String), ()> = env.create_function_from_closure("tracing_event_handler", |function_context| {let ((method, message),): ((String, String),) = function_context.args()?;let output_channel: bindgen_prelude::Object = function_context.this()?;let log_function: bindgen_prelude::Function<String, ()> =output_channel.get_named_property(&method)?;log_function.apply(output_channel, message)})?;// TODO: build_callback so can pass rust valueslet threadsafe_function = threadsafe_function.bind(output_channel)?.build_threadsafe_function().callee_handled::<false>().max_queue_size::<0>().weak::<false>().build()?;Ok(Self {threadsafe_function,field_formatter,})}fn call_output_channel<S: Into<String>>(&self, level: Level, message: S) {let level = match level {Level::TRACE => "trace",Level::DEBUG => "debug",Level::INFO => "info",Level::WARN => "warn",Level::ERROR => "error",};let status = self.threadsafe_function.call(// Ok((level, message.into())),(level, message.into()),ThreadsafeFunctionCallMode::Blocking,);}fn internal_message<S: core::fmt::Display>(&self, level: Level, message: S) {self.call_output_channel(level, format!("Internal tracing message: {message}"));}}impl<F, S> Layer<S> for VscodeLayer<F>whereF: for<'writer> FormatFields<'writer> + 'static,S: Subscriber + for<'registry> LookupSpan<'registry>,{fn on_new_span(&self,attributes: &tracing::span::Attributes<'_>,id: &tracing::span::Id,context: tracing_subscriber::layer::Context<'_, S>,) {let Some(span) = context.span(id) else {self.internal_message(Level::ERROR, format!("no matching span for ID: {id:#?}"));return;};let mut extensions = span.extensions_mut();if extensions.get_mut::<FormattedFields<F>>().is_none() {let mut formatted_fields: FormattedFields<F> = FormattedFields::new(String::new());let format_result = self.field_formatter.format_fields(formatted_fields.as_writer(), attributes);match format_result {Ok(()) => extensions.insert(formatted_fields),Err(error) => {self.internal_message(Level::ERROR, format!("failed to format fields: {error}"))}}}}fn on_event(&self,event: &tracing::Event<'_>,context: tracing_subscriber::layer::Context<'_, S>,) {let mut message = String::new();if let Some(event_scope) = context.event_scope(event) {for span in event_scope.from_root() {message.push_str(span.name());match span.extensions().get::<FormattedFields<F>>() {Some(formatted_fields) => {if !formatted_fields.is_empty() {message.push('{');message.push_str(formatted_fields);message.push('}');}}None => {self.internal_message(Level::WARN,format!("no formatted fields stored for {:#?}", span.id()),);message.push_str("{missing fields}");}}message.push(':');}}match event.metadata().module_path() {Some(module_path) => {if !message.is_empty() {message.push(' ');}message.push_str(module_path);message.push_str(": ");}None => {self.internal_message(Level::WARN,format!("missing module path for event at callsite {:#?}",event.metadata().callsite()),);}}// TODO: https://github.com/tokio-rs/tracing/issues/3335let writer = tracing_subscriber::fmt::format::Writer::new(&mut message);if let Err(error) = self.field_formatter.format_fields(writer, event) {self.internal_message(Level::ERROR,format!("failed to write event fields: {error}"),);}self.call_output_channel(*event.metadata().level(), message);}}pub fn init<F>(env: &napi::Env, name: &str, field_formatter: F) -> Result<(), napi::Error>whereF: for<'writer> FormatFields<'writer> + Send + Sync + 'static,{let vscode_layer = VscodeLayer::new(env, name, field_formatter)?;// TODO: https://docs.rs/tracing-appender/latest/tracing_appender/let subscriber = tracing_subscriber::registry().with(vscode_layer);tracing::subscriber::set_global_default(subscriber).map_err(|error| {napi::Error::from_reason(format!("Failed to set global default subscriber: {error}"))})?;Ok(())}
use std::collections::HashMap;use camino::{Utf8Path, Utf8PathBuf};use pijul_extension::FileSystemRepository;use crate::vscode_sys::reference::{SourceControlRef, SourceControlResourceGroupRef, TextEditorRef,};use crate::vscode_sys::{self, SourceControlResourceState};use crate::vscode_sys::{TextEditor, Uri};// TODO: remove public fieldspub struct OpenRepository {pub repository: FileSystemRepository,pub source_control: SourceControlRef,open_editors: HashMap<Utf8PathBuf, TextEditorRef>,unrecorded_changes: SourceControlResourceGroupRef,untracked_paths: SourceControlResourceGroupRef,}impl OpenRepository {#[tracing::instrument(skip_all)]pub fn new(env: &napi::Env,// TODO: pass SourceControl directly instead of URI?repository_uri: &Uri,// open_editors: HashMap<Utf8PathBuf, TextEditor>,// TODO: thiserror) -> Result<Self, napi::Error> {tracing::debug!(message = "Opening repository", uri = ?repository_uri.to_string()?);let repository_path = Utf8PathBuf::from(repository_uri.get_fs_path()?);let source_control =vscode_sys::scm::create_source_control(env, "pijul", "Pijul", repository_uri)?;let repository = FileSystemRepository::new(&repository_path).map_err(|error| {napi::Error::from_reason(format!("cannot open workspace at {repository_path}: {error}"))})?;tracing::debug!("repository");let mut unrecorded_changes = source_control.create_resource_group("changes", "Changes")?;let mut untracked_paths = source_control.create_resource_group("untracked", "Untracked")?;tracing::debug!("resource groups");let mut modified_resource_states = Vec::new();tracing::debug!("starting loop");for relative_modified_path in repository.iter_modified() {let absolute_modified_path = repository_path.join(relative_modified_path);let resource_uri = Uri::file(env, absolute_modified_path.as_str())?;let resource_state = SourceControlResourceState::new(env, &resource_uri)?;modified_resource_states.push(resource_state)}unrecorded_changes.set_resource_states(modified_resource_states)?;let mut untracked_resource_states = Vec::new();for relative_untracked_path in repository.iter_untracked() {let absolute_untracked_path = repository_path.join(relative_untracked_path);tracing::debug!(path = absolute_untracked_path.as_str());let resource_uri = Uri::file(env, absolute_untracked_path.as_str())?;let resource_state = SourceControlResourceState::new(env, &resource_uri)?;untracked_resource_states.push(resource_state)}untracked_paths.set_resource_states(untracked_resource_states)?;tracing::debug!("resource states");Ok(Self {source_control: source_control.create_ref()?,repository,unrecorded_changes: unrecorded_changes.create_ref()?,untracked_paths: untracked_paths.create_ref()?,open_editors: HashMap::new(),})}#[tracing::instrument(skip_all)]pub fn register_text_editor(&mut self,path: Utf8PathBuf,text_editor: TextEditor,) -> Result<(), napi::Error> {if self.repository.get_open_file(&path).is_none() {let document = text_editor.get_document()?;let file_contents = document.get_text(None)?;// TODO: proper error handlingself.repository.create_open_file(path.clone(), file_contents).map_err(|error| {napi::Error::from_reason(format!("Unable to create open file: {error}"))})?;let text_editor_reference = text_editor.create_ref()?;self.open_editors.try_insert(path, text_editor_reference).map_err(|_error| napi::Error::from_reason("Text editor already exists"))?;}Ok(())}#[tracing::instrument(skip_all)]pub fn get_text_editor<'env>(&self,env: &'env napi::Env,path: &Utf8Path,) -> Result<Option<TextEditor<'env>>, napi::Error> {self.open_editors.get(path).map(|reference| reference.get_inner(env)).transpose()}}
use std::collections::HashMap;use camino::Utf8PathBuf;use crate::repository::open_repository::OpenRepository;use crate::vscode_sys;mod open_repository;#[derive(Default)]pub struct OpenRepositories {// TODO: proper URIs// TODO: multiple repositories per workspace folderrepositories: HashMap<Utf8PathBuf, OpenRepository>,}impl OpenRepositories {#[tracing::instrument(skip_all)]pub fn new() -> Self {Self::default()}#[tracing::instrument(skip_all)]pub fn get_open_repository(&self,env: &napi::Env,uri: &vscode_sys::Uri,) -> Result<Option<(Utf8PathBuf, &OpenRepository)>, napi::Error> {let Some(workspace_folder) = vscode_sys::workspace::get_workspace_folder(env, uri)? else {tracing::debug!(message = "URI does not correspond to a workspace folder",uri = ?uri.to_string());return Ok(None);};let workspace_uri = workspace_folder.get_uri()?;let workspace_path = Utf8PathBuf::from(workspace_uri.get_fs_path()?);Ok(self.repositories.get(&workspace_path).map(|open_repository| (workspace_path, open_repository)))}#[tracing::instrument(skip_all)]pub fn get_open_repository_mut(&mut self,env: &napi::Env,uri: &vscode_sys::Uri,) -> Result<Option<(Utf8PathBuf, &mut OpenRepository)>, napi::Error> {let Some(workspace_folder) = vscode_sys::workspace::get_workspace_folder(env, uri)? else {tracing::debug!(message = "URI does not correspond to a workspace folder",uri = ?uri.to_string());return Ok(None);};let workspace_uri = workspace_folder.get_uri()?;let workspace_path = Utf8PathBuf::from(workspace_uri.get_fs_path()?);Ok(self.repositories.get_mut(&workspace_path).map(|open_repository| (workspace_path, open_repository)))}pub fn register_text_editors(&mut self,env: &napi::Env,text_editors: Vec<vscode_sys::TextEditor>,) -> Result<(), napi::Error> {for text_editor in text_editors {let document = text_editor.get_document()?;let uri = document.get_uri()?;if let Some((repository_path, open_repository)) =self.get_open_repository_mut(env, &uri)?{let absolute_editor_path = Utf8PathBuf::from(uri.get_fs_path()?);let relative_editor_path = absolute_editor_path.strip_prefix(&repository_path)// TODO: error handling.unwrap().to_path_buf();open_repository.register_text_editor(relative_editor_path, text_editor)?;tracing::debug!(message = "Registered text editor",?repository_path,uri = uri.to_string()?);} else {// Ignore documents not part of any workspace foldertracing::debug!(message = "Ignoring text editor without valid workspace",uri = uri.to_string()?);}}Ok(())}#[tracing::instrument(skip_all)]pub fn open_workspace_folder(&mut self,env: &napi::Env,workspace_folder: vscode_sys::WorkspaceFolder,) -> Result<(), napi::Error> {let repository_uri = workspace_folder.get_uri()?;let repository_path = Utf8PathBuf::from(repository_uri.get_fs_path()?);let open_repository = OpenRepository::new(env, &repository_uri)?;if self.repositories.try_insert(repository_path.clone(), open_repository).is_err(){tracing::error!(message = "Failed to insert duplicate repository",?repository_path);}Ok(())}#[tracing::instrument(skip_all)]pub fn close_workspace_folder(&mut self,workspace_folder: vscode_sys::WorkspaceFolder,) -> Result<(), napi::Error> {let repository_uri = workspace_folder.get_uri()?;let repository_path = Utf8PathBuf::from(repository_uri.get_fs_path()?);if self.repositories.remove(&repository_path).is_none() {tracing::error!(message = "Failed to remove repository that does not exist",?repository_path);}Ok(())}// TODO: remove this#[tracing::instrument(skip_all)]pub fn iter_repositories(&self) -> impl Iterator<Item = (&Utf8PathBuf, &OpenRepository)> {self.repositories.iter()}}
#![feature(map_try_insert)]#![feature(mapped_lock_guards)]// TODO: panic handler// TODO: fix credits in quick diff panel// TODO: quick diff untracked files// TODO: find a way to validate all subscriptions are disposed? or just standardize how they are registered// TODO: replace `get_repository_folder` with something that can handle nested repositories// TODO: consistent naming// TODO: handle adding/removing workspace folders (and adding/removing .pijul folders)// TODO: handle changing active text editors// TODO: color workspace root with `gitDecoration.submoduleResourceForeground`?// TODO: something breaks when opening quick diff// TODO: static handling of package.json contributions// TODO: move l10n into pijul-extensionuse std::sync::{Mutex, MutexGuard, OnceLock};use camino::Utf8PathBuf;use napi::bindgen_prelude;use napi_derive::napi;use pijul_extension::{PathState, TrackedState};use repository::OpenRepositories;mod decorations;mod repository;mod vscode_sys;static EXTENSION_STATE: OnceLock<Mutex<ExtensionState>> = OnceLock::new();pub const PIJUL_SCHEME: &str = "pijul";struct ExtensionState {decoration_type: vscode_sys::reference::TextEditorDecorationTypeRef,repositories: OpenRepositories,}impl ExtensionState {fn get() -> Result<MutexGuard<'static, Self>, napi::Error> {EXTENSION_STATE.get().ok_or_else(|| napi::Error::from_reason("Extension state is not set"))?.lock().map_err(|_error| napi::Error::from_reason("Extension state mutex has been poisoned"))}}fn provide_file_decoration<'env>(env: &'env napi::Env,uri: vscode_sys::Uri,_cancellation_token: bindgen_prelude::Object,) -> Result<Option<vscode_sys::FileDecoration<'env>>, napi::Error> {let program_state = ExtensionState::get()?;let Some((repository_path, open_repository)) =program_state.repositories.get_open_repository(env, &uri)?else {return Ok(None);};let absolute_file_path = Utf8PathBuf::from(uri.get_fs_path()?);let relative_file_path =absolute_file_path.strip_prefix(&repository_path).map_err(|error| {napi::Error::from_reason(format!("Failed to strip prefix {repository_path} from {absolute_file_path}: {error}"))})?;let Some(path_state) = open_repository.repository.get_path_state(relative_file_path)else {return Ok(None);};// TODO: l10n_embedlet (badge, tooltip, color_id) = match path_state {PathState::Untracked => ("U", "Untracked", "pijul.decorations.path.untracked"),PathState::Tracked(modified_state) => match modified_state {TrackedState::Added => ("A", "Added", "pijul.decorations.path.added"),TrackedState::Removed => ("RM", "Removed", "pijul.decorations.path.removed"),TrackedState::Modified => ("M", "Modified", "pijul.decorations.path.modified"),TrackedState::Moved => ("MV", "Moved", "pijul.decorations.path.moved"),TrackedState::ModifiedAndMoved => ("M,MV","Modified, Moved","pijul.decorations.path.modifiedAndMoved",),},};let color = vscode_sys::ThemeColor::new(env, color_id)?;let path_decoration = vscode_sys::FileDecoration::new(env, badge, tooltip, &color)?;Ok(Some(path_decoration))}fn provide_text_document_content(env: &napi::Env,pijul_uri: vscode_sys::Uri,_cancellation_token: bindgen_prelude::Object,) -> Result<Option<String>, napi::Error> {let program_state = ExtensionState::get()?;let uri_change = vscode_sys::UriWithChange::new(env)?.scheme("file")?;let uri = pijul_uri.with(uri_change)?;if let Some((workspace_path, workspace)) =program_state.repositories.get_open_repository(env, &uri)?{let absolute_path = Utf8PathBuf::from(uri.get_fs_path()?);let relative_path = absolute_path.strip_prefix(&workspace_path).map_err(|error| {napi::Error::from_reason(format!("Failed to strip prefix {workspace_path} from {absolute_path}: {error}"))})?;match workspace.repository.get_open_file(relative_path) {Some(open_file) => Ok(Some(open_file.tracked_contents())),None => {tracing::error!(message = "No tracked file state for {relative_path}",?workspace_path);Ok(None)}}} else {tracing::debug!(message = "Ignoring URI", uri = uri.to_string()?);Ok(None)}}fn provide_original_resource<'env>(env: &'env napi::Env,uri: vscode_sys::Uri<'env>,_cancellation_token: bindgen_prelude::Object,) -> Result<Option<vscode_sys::Uri<'env>>, napi::Error> {// TODO: create a proper uri that preserves everything, including the original schemelet uri_change = vscode_sys::UriWithChange::new(env)?.scheme(PIJUL_SCHEME)?;let pijul_uri = uri.with(uri_change)?;Ok(Some(pijul_uri))}#[tracing::instrument(skip_all)]fn on_did_change_text_document(env: &napi::Env,event: vscode_sys::TextDocumentChangeEvent,) -> Result<(), napi::Error> {let mut program_state = ExtensionState::get()?;let text_document = event.get_document()?;let document_uri = text_document.get_uri()?;// Ignore any messages printed to the `Output` channel (used by `tracing`)if document_uri.get_scheme()? == "output" {return Ok(());}if let Some((repository_path, open_repository)) = program_state.repositories.get_open_repository_mut(env, &document_uri)?{let absolute_document_path = Utf8PathBuf::from(document_uri.get_fs_path()?);tracing::debug!(?absolute_document_path);let relative_document_path = absolute_document_path.strip_prefix(&repository_path).map_err(|error| napi::Error::from_reason(format!("Failed to strip prefix {repository_path} from {absolute_document_path}: {error}")))?;let change_events = event.get_content_changes()?;for change_event in change_events {let character_offset = change_event.get_range_offset()?;let characters_replaced = change_event.get_range_length()?;let replacement_text = change_event.get_text()?;open_repository.repository.update_open_file(relative_document_path,character_offset as usize,characters_replaced as usize,&replacement_text,).map_err(|error| {napi::Error::from_reason(format!("Unable to update open file {relative_document_path} ({absolute_document_path}): {error}"))})?;}// TODO: avoid the flashing this causes// Re-render the inline credit annotationlet text_editor = open_repository.get_text_editor(env, relative_document_path)?.ok_or_else(|| {napi::Error::from_reason(format!("no open text editor for {absolute_document_path}"))})?;let selections = text_editor.get_selections()?;decorations::inline_credit::render(env, &program_state, &text_editor, selections)?;}Ok(())}#[tracing::instrument(skip_all)]fn on_did_change_text_editor_selections(env: &napi::Env,event: vscode_sys::TextEditorSelectionChangeEvent,) -> Result<(), napi::Error> {let program_state = ExtensionState::get()?;let editor = event.get_text_editor()?;let document = editor.get_document()?;let uri = document.get_uri()?;// Ignore any messages printed to the `Output` channel (used by `tracing`)if uri.get_scheme()? == "output" {return Ok(());}let selections = event.get_selections()?;decorations::inline_credit::render(env, &program_state, &editor, selections)}#[tracing::instrument(skip_all)]fn on_did_change_workspace_folders(env: &napi::Env,event: vscode_sys::WorkspaceFoldersChangeEvent,) -> Result<(), napi::Error> {let mut program_state = ExtensionState::get()?;let added_workspaces = event.get_added()?;let removed_workspaces = event.get_removed()?;for added_workspace in added_workspaces {program_state.repositories.open_workspace_folder(env, added_workspace)?;}for removed_workspace in removed_workspaces {program_state.repositories.close_workspace_folder(removed_workspace)?;}Ok(())}// TODO: handle closing text editors#[tracing::instrument(skip_all)]fn on_did_change_visible_text_editors(env: &napi::Env,visible_text_editors: Vec<vscode_sys::TextEditor>,) -> Result<(), napi::Error> {let mut extension_state = ExtensionState::get()?;extension_state.repositories.register_text_editors(env, visible_text_editors)}// TODO: make sure things are registered in order:// 1. Create extension state// 2. First-time init e.g. initial inline credit and open files// 3. Register extension state// 4. Providers// 5. Event handlers// TODO: remove catch_unwind (make activate_internal)#[napi(catch_unwind)]pub fn activate(env: &napi::Env,vscode_object: bindgen_prelude::Object,extension_context: bindgen_prelude::Object,) -> Result<(), napi::Error> {vscode_sys::activate(&vscode_object, &extension_context)?;vscode_sys::log::init(env,"Pijul",tracing_subscriber::fmt::format::DefaultFields::new(),)?;let mut repositories = OpenRepositories::new();for workspace_folder in vscode_sys::workspace::get_workspace_folders(env)? {repositories.open_workspace_folder(env, workspace_folder)?;}let visible_text_editors = vscode_sys::window::get_visible_text_editors(env)?;repositories.register_text_editors(env, visible_text_editors)?;let decoration_type = decorations::create_decoration_type(env)?;let extension_state = ExtensionState {decoration_type: decoration_type.create_ref()?,repositories,};if let Some(active_text_editor) = vscode_sys::window::get_active_text_editor(env)? {let selections = active_text_editor.get_selections()?;decorations::inline_credit::render(env, &extension_state, &active_text_editor, selections)?;}EXTENSION_STATE.set(Mutex::new(extension_state)).map_err(|_existing_object| {napi::Error::from_reason("Extension state has already been set")})?;let file_decoration_provider =vscode_sys::FileDecorationProvider::new(env, provide_file_decoration)?;vscode_sys::window::register_file_decoration_provider(env,&extension_context,file_decoration_provider,)?;let text_document_provider =vscode_sys::TextDocumentContentProvider::new(env, provide_text_document_content)?;vscode_sys::workspace::register_text_document_content_provider(env,&extension_context,PIJUL_SCHEME,text_document_provider,)?;let mut quick_diff_provider = vscode_sys::QuickDiffProvider::new(env)?;quick_diff_provider.set_provide_original_resource(env, provide_original_resource)?;let program_state = ExtensionState::get()?;for (_repository_path, open_repository) in program_state.repositories.iter_repositories() {let mut source_control = open_repository.source_control.get_inner(env)?;source_control.set_quick_diff_provider(quick_diff_provider)?;}vscode_sys::window::on_did_change_text_editor_selections(env,on_did_change_text_editor_selections,)?;vscode_sys::window::on_did_change_visible_text_editors(env,on_did_change_visible_text_editors,)?;vscode_sys::workspace::on_did_change_text_document(env, on_did_change_text_document)?;vscode_sys::workspace::on_did_change_workspace_folders(env, on_did_change_workspace_folders)?;tracing::info!("Extension activated");Ok(())}
// The module 'vscode' contains the VS Code extensibility API// Import the module and reference it with the alias vscode in your code belowimport * as vscode from "vscode";import nativeModule from "../out/native-module";// This method is called when your extension is activated// Your extension is activated the very first time the command is executedexport function activate(context: vscode.ExtensionContext) {// Use the console to output diagnostic information (console.log) and errors (console.error)// This line of code will only be executed once when your extension is activatedconsole.log('Congratulations, your extension "pijul-vscode" is now active!');nativeModule.activate(vscode, context);// The command has been defined in the package.json file// Now provide the implementation of the command with registerCommand// The commandId parameter must match the command field in package.jsonconst disposable = vscode.commands.registerCommand("pijul-vscode.helloWorld",() => {// The code you place here will be executed every time your command is executed// Display a message box to the uservscode.window.showInformationMessage("Hello World from pijul-vscode!");},);context.subscriptions.push(disposable);}// This method is called when your extension is deactivatedexport function deactivate() {}
use crate::vscode_sys;pub mod inline_credit;pub fn create_decoration_type<'env>(env: &'env napi::Env,) -> Result<vscode_sys::TextEditorDecorationType<'env>, napi::Error> {let theme_color =vscode_sys::ThemeColor::new(env, "pijul.decorations.inlineCredit.foreground")?;let after = vscode_sys::ThemableDecorationAttachmentRenderOptions::new(env)?// Margin of roughly 10 characters to the right// https://developer.mozilla.org/en-US/docs/Web/CSS/length#ch.margin("0 0 0 10ch")?.color(&theme_color)?;let render_options = vscode_sys::DecorationRenderOptions::new(env)?.after(after)?;let decoration_type =vscode_sys::window::create_text_editor_decoration_type(env, render_options)?;Ok(decoration_type)}
// TODO: better, localized hover messages// TODO: generate the enums in their own impl blocksuse std::ops::RangeInclusive;use camino::Utf8PathBuf;use icu_locale::locale;use jiff::Timestamp;use l10n_embed::Localize;use l10n_embed_derive::localize;use napi::bindgen_prelude::JsObjectValue;use pijul_extension::FileSystemRepository;use pijul_extension::file_system::changes::CreditSource;use pijul_extension::file_system::changes::Span;use pijul_extension::file_system::open_file::OpenFile;use crate::ExtensionState;use crate::vscode_sys;#[localize("l10n/**/inline_credit.ftl")]enum AuthorKind<'change_header> {Local,Remote {username: &'change_header str,},Unknown {public_key_signature: &'change_header str,},}#[localize("l10n/**/inline_credit.ftl")]enum InlineCreditAnnotation<'change_header> {Tracked {authors: l10n_embed::list::AndList<AuthorKind<'change_header>>,timestamp: Timestamp,message: &'change_header str,},Untracked {timestamp: Timestamp,},}fn get_lines_selected(editor_selections: Vec<vscode_sys::Selection>,) -> Result<Vec<RangeInclusive<usize>>, napi::Error> {let mut credits = Vec::with_capacity(editor_selections.len());for editor_selection in &editor_selections {let start_line = editor_selection.get_start()?.get_line()?;let end_line: u32 = editor_selection.get_end()?.get_line()?;credits.push((start_line as usize)..=(end_line as usize));}Ok(credits)}fn decoration_options<'env>(env: &napi::Env,localization_context: &l10n_embed::Context,repository: &FileSystemRepository,open_file: &OpenFile,credits: impl Iterator<Item = Span<CreditSource>>,) -> Result<Vec<vscode_sys::DecorationOptions<'env>>, napi::Error> {let mut decoration_options_list = Vec::new();for credit in credits {tracing::debug!(?credit);let annotation = match credit.value {CreditSource::Tracked(change_id) => {let change_header = repository.get_change_header(&change_id).ok_or_else(|| {napi::Error::from_reason(format!("unable to get change {change_id:#?}"))})?;let authors = repository.authors_for_change(change_header).into_iter().map(|author_source| match author_source {pijul_extension::author::AuthorSource::Local(_identity) => {AuthorKind::Local}pijul_extension::author::AuthorSource::Remote(identity) => {AuthorKind::Remote {username: &identity.config.author.username,}}pijul_extension::author::AuthorSource::Unknown(public_key_signature) => {AuthorKind::Unknown {public_key_signature,}}}).collect();InlineCreditAnnotation::Tracked {authors: l10n_embed::list::AndList::new(authors),timestamp: change_header.timestamp,message: &change_header.message,}}CreditSource::Untracked => InlineCreditAnnotation::Untracked {timestamp: Timestamp::try_from(open_file.contents.modified_time).map_err(|error| {napi::Error::from_reason(format!("Failed to parse timestamp {:#?}: {error}",open_file.contents.modified_time))},)?,},};let mut localized_annotation = String::new();annotation.localize(localization_context, &mut localized_annotation);let hover_message_text = match credit.value {CreditSource::Tracked(change_id) => {let change_header = repository.get_change_header(&change_id).ok_or_else(|| {napi::Error::from_reason(format!("unable to get change {change_id:#?}"))})?;match &change_header.description {Some(description) => {format!("<h2>{}</h2><p>{}</p>", change_header.message, description)}None => change_header.message.clone(),}}CreditSource::Untracked => String::new(),};for line in credit.lines {let current_line_contents = open_file.contents.text.get_line(line, ropey::LineType::LF_CR).ok_or_else(|| napi::Error::from_reason(format!("no contents for line {line}")))?;let final_character_offset = current_line_contents.len() as u32;let start = vscode_sys::Position::new(env, line as u32, final_character_offset)?;let end = vscode_sys::Position::new(env, line as u32, final_character_offset)?;let range = vscode_sys::Range::new(env, &start, &end)?;let mut hover_message =vscode_sys::MarkdownString::new(env, &hover_message_text, false)?;hover_message.inner.set_named_property("supportHtml", true)?;let after = vscode_sys::ThemableDecorationAttachmentRenderOptions::new(env)?.content_text(&localized_annotation)?;let render_options =vscode_sys::DecorationInstanceRenderOptions::new(env)?.after(after)?;let decoration_options = vscode_sys::DecorationOptions::new(env, &range)?.hover_message(&hover_message)?.render_options(render_options)?;decoration_options_list.push(decoration_options);}}Ok(decoration_options_list)}// TODO: different rendering modes? e.g. render only at boundaries between lines, render only on cursors, etcpub fn render(env: &napi::Env,program_state: &ExtensionState,editor: &vscode_sys::TextEditor,selections: Vec<vscode_sys::Selection>,) -> Result<(), napi::Error> {let editor_document = editor.get_document()?;let document_uri = editor_document.get_uri()?;let Some((repository_path, open_repository)) = program_state.repositories.get_open_repository(env, &document_uri)?else {return Ok(());};let absolute_file_path = Utf8PathBuf::from(document_uri.get_fs_path()?);let relative_file_path =absolute_file_path.strip_prefix(&repository_path).map_err(|error| {napi::Error::from_reason(format!("Failed to strip prefix {repository_path} from {absolute_file_path}: {error}"))})?;let localization_context = l10n_embed::Context::new(locale!("en-US"), false);let lines_selected = get_lines_selected(selections)?;let open_file = open_repository.repository.get_open_file(relative_file_path).ok_or_else(|| {napi::Error::from_reason(format!("unable to get open file for {relative_file_path}"))})?;let credits = lines_selected.into_iter().flat_map(|line_range| open_file.credit(line_range));let decoration_options = decoration_options(env,&localization_context,&open_repository.repository,open_file,credits,)?;let decoration_type = program_state.decoration_type.get_inner(env)?;editor.set_decorations(decoration_type, decoration_options)?;Ok(())}
lockfileVersion: '9.0'settings:autoInstallPeers: trueexcludeLinksFromLockfile: falseimporters:.:devDependencies:'@napi-rs/cli':specifier: ^3.3.1version: 3.4.1(@emnapi/runtime@1.7.1)(@types/node@22.19.1)'@types/node':specifier: 22.xversion: 22.19.1'@types/vscode':specifier: ^1.105.0version: 1.106.1typescript:specifier: ^5.9.3version: 5.9.3packages:'@emnapi/core@1.7.1':resolution: {integrity: sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==}'@emnapi/runtime@1.7.1':resolution: {integrity: sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==}'@emnapi/wasi-threads@1.1.0':resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==}'@inquirer/ansi@1.0.2':resolution: {integrity: sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==}engines: {node: '>=18'}'@inquirer/checkbox@4.3.2':resolution: {integrity: sha512-VXukHf0RR1doGe6Sm4F0Em7SWYLTHSsbGfJdS9Ja2bX5/D5uwVOEjr07cncLROdBvmnvCATYEWlHqYmXv2IlQA==}engines: {node: '>=18'}peerDependencies:'@types/node': '>=18'peerDependenciesMeta:'@types/node':optional: true'@inquirer/confirm@5.1.21':resolution: {integrity: sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==}engines: {node: '>=18'}peerDependencies:'@types/node': '>=18'peerDependenciesMeta:'@types/node':optional: true'@inquirer/core@10.3.2':resolution: {integrity: sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==}engines: {node: '>=18'}peerDependencies:'@types/node': '>=18'peerDependenciesMeta:'@types/node':optional: true'@inquirer/editor@4.2.23':resolution: {integrity: sha512-aLSROkEwirotxZ1pBaP8tugXRFCxW94gwrQLxXfrZsKkfjOYC1aRvAZuhpJOb5cu4IBTJdsCigUlf2iCOu4ZDQ==}engines: {node: '>=18'}peerDependencies:'@types/node': '>=18'peerDependenciesMeta:'@types/node':optional: true'@inquirer/expand@4.0.23':resolution: {integrity: sha512-nRzdOyFYnpeYTTR2qFwEVmIWypzdAx/sIkCMeTNTcflFOovfqUk+HcFhQQVBftAh9gmGrpFj6QcGEqrDMDOiew==}engines: {node: '>=18'}peerDependencies:'@types/node': '>=18'peerDependenciesMeta:'@types/node':optional: true'@inquirer/external-editor@1.0.3':resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==}engines: {node: '>=18'}peerDependencies:'@types/node': '>=18'peerDependenciesMeta:'@types/node':optional: true'@inquirer/figures@1.0.15':resolution: {integrity: sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==}engines: {node: '>=18'}'@inquirer/input@4.3.1':resolution: {integrity: sha512-kN0pAM4yPrLjJ1XJBjDxyfDduXOuQHrBB8aLDMueuwUGn+vNpF7Gq7TvyVxx8u4SHlFFj4trmj+a2cbpG4Jn1g==}engines: {node: '>=18'}peerDependencies:'@types/node': '>=18'peerDependenciesMeta:'@types/node':optional: true'@inquirer/number@3.0.23':resolution: {integrity: sha512-5Smv0OK7K0KUzUfYUXDXQc9jrf8OHo4ktlEayFlelCjwMXz0299Y8OrI+lj7i4gCBY15UObk76q0QtxjzFcFcg==}engines: {node: '>=18'}peerDependencies:'@types/node': '>=18'peerDependenciesMeta:'@types/node':optional: true'@inquirer/password@4.0.23':resolution: {integrity: sha512-zREJHjhT5vJBMZX/IUbyI9zVtVfOLiTO66MrF/3GFZYZ7T4YILW5MSkEYHceSii/KtRk+4i3RE7E1CUXA2jHcA==}engines: {node: '>=18'}peerDependencies:'@types/node': '>=18'peerDependenciesMeta:'@types/node':optional: true'@inquirer/prompts@7.10.1':resolution: {integrity: sha512-Dx/y9bCQcXLI5ooQ5KyvA4FTgeo2jYj/7plWfV5Ak5wDPKQZgudKez2ixyfz7tKXzcJciTxqLeK7R9HItwiByg==}engines: {node: '>=18'}peerDependencies:'@types/node': '>=18'peerDependenciesMeta:'@types/node':optional: true'@inquirer/rawlist@4.1.11':resolution: {integrity: sha512-+LLQB8XGr3I5LZN/GuAHo+GpDJegQwuPARLChlMICNdwW7OwV2izlCSCxN6cqpL0sMXmbKbFcItJgdQq5EBXTw==}engines: {node: '>=18'}peerDependencies:'@types/node': '>=18'peerDependenciesMeta:'@types/node':optional: true'@inquirer/search@3.2.2':resolution: {integrity: sha512-p2bvRfENXCZdWF/U2BXvnSI9h+tuA8iNqtUKb9UWbmLYCRQxd8WkvwWvYn+3NgYaNwdUkHytJMGG4MMLucI1kA==}engines: {node: '>=18'}peerDependencies:'@types/node': '>=18'peerDependenciesMeta:'@types/node':optional: true'@inquirer/select@4.4.2':resolution: {integrity: sha512-l4xMuJo55MAe+N7Qr4rX90vypFwCajSakx59qe/tMaC1aEHWLyw68wF4o0A4SLAY4E0nd+Vt+EyskeDIqu1M6w==}engines: {node: '>=18'}peerDependencies:'@types/node': '>=18'peerDependenciesMeta:'@types/node':optional: true'@inquirer/type@3.0.10':resolution: {integrity: sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==}engines: {node: '>=18'}peerDependencies:'@types/node': '>=18'peerDependenciesMeta:'@types/node':optional: true'@napi-rs/cli@3.4.1':resolution: {integrity: sha512-ayhm+NfrP5Hmh7vy5pfyYm/ktYtLh2PrgdLuqHTAubO7RoO2JkUE4F991AtgYxNewwXI8+guZLxU8itV7QnDrQ==}engines: {node: '>= 16'}hasBin: truepeerDependencies:'@emnapi/runtime': ^1.5.0peerDependenciesMeta:'@emnapi/runtime':optional: true'@napi-rs/cross-toolchain@1.0.3':resolution: {integrity: sha512-ENPfLe4937bsKVTDA6zdABx4pq9w0tHqRrJHyaGxgaPq03a2Bd1unD5XSKjXJjebsABJ+MjAv1A2OvCgK9yehg==}peerDependencies:'@napi-rs/cross-toolchain-arm64-target-aarch64': ^1.0.3'@napi-rs/cross-toolchain-arm64-target-armv7': ^1.0.3'@napi-rs/cross-toolchain-arm64-target-ppc64le': ^1.0.3'@napi-rs/cross-toolchain-arm64-target-s390x': ^1.0.3'@napi-rs/cross-toolchain-arm64-target-x86_64': ^1.0.3'@napi-rs/cross-toolchain-x64-target-aarch64': ^1.0.3'@napi-rs/cross-toolchain-x64-target-armv7': ^1.0.3'@napi-rs/cross-toolchain-x64-target-ppc64le': ^1.0.3'@napi-rs/cross-toolchain-x64-target-s390x': ^1.0.3'@napi-rs/cross-toolchain-x64-target-x86_64': ^1.0.3peerDependenciesMeta:'@napi-rs/cross-toolchain-arm64-target-aarch64':optional: true'@napi-rs/cross-toolchain-arm64-target-armv7':optional: true'@napi-rs/cross-toolchain-arm64-target-ppc64le':optional: true'@napi-rs/cross-toolchain-arm64-target-s390x':optional: true'@napi-rs/cross-toolchain-arm64-target-x86_64':optional: true'@napi-rs/cross-toolchain-x64-target-aarch64':optional: true'@napi-rs/cross-toolchain-x64-target-armv7':optional: true'@napi-rs/cross-toolchain-x64-target-ppc64le':optional: true'@napi-rs/cross-toolchain-x64-target-s390x':optional: true'@napi-rs/cross-toolchain-x64-target-x86_64':optional: true'@napi-rs/lzma-android-arm-eabi@1.4.5':resolution: {integrity: sha512-Up4gpyw2SacmyKWWEib06GhiDdF+H+CCU0LAV8pnM4aJIDqKKd5LHSlBht83Jut6frkB0vwEPmAkv4NjQ5u//Q==}engines: {node: '>= 10'}cpu: [arm]os: [android]'@napi-rs/lzma-android-arm64@1.4.5':resolution: {integrity: sha512-uwa8sLlWEzkAM0MWyoZJg0JTD3BkPknvejAFG2acUA1raXM8jLrqujWCdOStisXhqQjZ2nDMp3FV6cs//zjfuQ==}engines: {node: '>= 10'}cpu: [arm64]os: [android]'@napi-rs/lzma-darwin-arm64@1.4.5':resolution: {integrity: sha512-0Y0TQLQ2xAjVabrMDem1NhIssOZzF/y/dqetc6OT8mD3xMTDtF8u5BqZoX3MyPc9FzpsZw4ksol+w7DsxHrpMA==}engines: {node: '>= 10'}cpu: [arm64]os: [darwin]'@napi-rs/lzma-darwin-x64@1.4.5':resolution: {integrity: sha512-vR2IUyJY3En+V1wJkwmbGWcYiT8pHloTAWdW4pG24+51GIq+intst6Uf6D/r46citObGZrlX0QvMarOkQeHWpw==}engines: {node: '>= 10'}cpu: [x64]os: [darwin]'@napi-rs/lzma-freebsd-x64@1.4.5':resolution: {integrity: sha512-XpnYQC5SVovO35tF0xGkbHYjsS6kqyNCjuaLQ2dbEblFRr5cAZVvsJ/9h7zj/5FluJPJRDojVNxGyRhTp4z2lw==}engines: {node: '>= 10'}cpu: [x64]os: [freebsd]'@napi-rs/lzma-linux-arm-gnueabihf@1.4.5':resolution: {integrity: sha512-ic1ZZMoRfRMwtSwxkyw4zIlbDZGC6davC9r+2oX6x9QiF247BRqqT94qGeL5ZP4Vtz0Hyy7TEViWhx5j6Bpzvw==}engines: {node: '>= 10'}cpu: [arm]os: [linux]'@napi-rs/lzma-linux-arm64-gnu@1.4.5':resolution: {integrity: sha512-asEp7FPd7C1Yi6DQb45a3KPHKOFBSfGuJWXcAd4/bL2Fjetb2n/KK2z14yfW8YC/Fv6x3rBM0VAZKmJuz4tysg==}engines: {node: '>= 10'}cpu: [arm64]os: [linux]'@napi-rs/lzma-linux-arm64-musl@1.4.5':resolution: {integrity: sha512-yWjcPDgJ2nIL3KNvi4536dlT/CcCWO0DUyEOlBs/SacG7BeD6IjGh6yYzd3/X1Y3JItCbZoDoLUH8iB1lTXo3w==}engines: {node: '>= 10'}cpu: [arm64]os: [linux]'@napi-rs/lzma-linux-ppc64-gnu@1.4.5':resolution: {integrity: sha512-0XRhKuIU/9ZjT4WDIG/qnX7Xz7mSQHYZo9Gb3MP2gcvBgr6BA4zywQ9k3gmQaPn9ECE+CZg2V7DV7kT+x2pUMQ==}engines: {node: '>= 10'}cpu: [ppc64]os: [linux]'@napi-rs/lzma-linux-riscv64-gnu@1.4.5':resolution: {integrity: sha512-QrqDIPEUUB23GCpyQj/QFyMlr8SGxxyExeZz9OWFnHfb70kXdTLWrHS/hEI1Ru+lSbQ/6xRqeoGyQ4Aqdg+/RA==}engines: {node: '>= 10'}cpu: [riscv64]os: [linux]'@napi-rs/lzma-linux-s390x-gnu@1.4.5':resolution: {integrity: sha512-k8RVM5aMhW86E9H0QXdquwojew4H3SwPxbRVbl49/COJQWCUjGi79X6mYruMnMPEznZinUiT1jgKbFo2A00NdA==}engines: {node: '>= 10'}cpu: [s390x]os: [linux]'@napi-rs/lzma-linux-x64-gnu@1.4.5':resolution: {integrity: sha512-6rMtBgnIq2Wcl1rQdZsnM+rtCcVCbws1nF8S2NzaUsVaZv8bjrPiAa0lwg4Eqnn1d9lgwqT+cZgm5m+//K08Kw==}engines: {node: '>= 10'}cpu: [x64]os: [linux]'@napi-rs/lzma-linux-x64-musl@1.4.5':resolution: {integrity: sha512-eiadGBKi7Vd0bCArBUOO/qqRYPHt/VQVvGyYvDFt6C2ZSIjlD+HuOl+2oS1sjf4CFjK4eDIog6EdXnL0NE6iyQ==}engines: {node: '>= 10'}cpu: [x64]os: [linux]'@napi-rs/lzma-wasm32-wasi@1.4.5':resolution: {integrity: sha512-+VyHHlr68dvey6fXc2hehw9gHVFIW3TtGF1XkcbAu65qVXsA9D/T+uuoRVqhE+JCyFHFrO0ixRbZDRK1XJt1sA==}engines: {node: '>=14.0.0'}cpu: [wasm32]'@napi-rs/lzma-win32-arm64-msvc@1.4.5':resolution: {integrity: sha512-eewnqvIyyhHi3KaZtBOJXohLvwwN27gfS2G/YDWdfHlbz1jrmfeHAmzMsP5qv8vGB+T80TMHNkro4kYjeh6Deg==}engines: {node: '>= 10'}cpu: [arm64]os: [win32]'@napi-rs/lzma-win32-ia32-msvc@1.4.5':resolution: {integrity: sha512-OeacFVRCJOKNU/a0ephUfYZ2Yt+NvaHze/4TgOwJ0J0P4P7X1mHzN+ig9Iyd74aQDXYqc7kaCXA2dpAOcH87Cg==}engines: {node: '>= 10'}cpu: [ia32]os: [win32]'@napi-rs/lzma-win32-x64-msvc@1.4.5':resolution: {integrity: sha512-T4I1SamdSmtyZgDXGAGP+y5LEK5vxHUFwe8mz6D4R7Sa5/WCxTcCIgPJ9BD7RkpO17lzhlaM2vmVvMy96Lvk9Q==}engines: {node: '>= 10'}cpu: [x64]os: [win32]'@napi-rs/lzma@1.4.5':resolution: {integrity: sha512-zS5LuN1OBPAyZpda2ZZgYOEDC+xecUdAGnrvbYzjnLXkrq/OBC3B9qcRvlxbDR3k5H/gVfvef1/jyUqPknqjbg==}engines: {node: '>= 10'}'@napi-rs/tar-android-arm-eabi@1.1.0':resolution: {integrity: sha512-h2Ryndraj/YiKgMV/r5by1cDusluYIRT0CaE0/PekQ4u+Wpy2iUVqvzVU98ZPnhXaNeYxEvVJHNGafpOfaD0TA==}engines: {node: '>= 10'}cpu: [arm]os: [android]'@napi-rs/tar-android-arm64@1.1.0':resolution: {integrity: sha512-DJFyQHr1ZxNZorm/gzc1qBNLF/FcKzcH0V0Vwan5P+o0aE2keQIGEjJ09FudkF9v6uOuJjHCVDdK6S6uHtShAw==}engines: {node: '>= 10'}cpu: [arm64]os: [android]'@napi-rs/tar-darwin-arm64@1.1.0':resolution: {integrity: sha512-Zz2sXRzjIX4e532zD6xm2SjXEym6MkvfCvL2RMpG2+UwNVDVscHNcz3d47Pf3sysP2e2af7fBB3TIoK2f6trPw==}engines: {node: '>= 10'}cpu: [arm64]os: [darwin]'@napi-rs/tar-darwin-x64@1.1.0':resolution: {integrity: sha512-EI+CptIMNweT0ms9S3mkP/q+J6FNZ1Q6pvpJOEcWglRfyfQpLqjlC0O+dptruTPE8VamKYuqdjxfqD8hifZDOA==}engines: {node: '>= 10'}cpu: [x64]os: [darwin]'@napi-rs/tar-freebsd-x64@1.1.0':resolution: {integrity: sha512-J0PIqX+pl6lBIAckL/c87gpodLbjZB1OtIK+RDscKC9NLdpVv6VGOxzUV/fYev/hctcE8EfkLbgFOfpmVQPg2g==}engines: {node: '>= 10'}cpu: [x64]os: [freebsd]'@napi-rs/tar-linux-arm-gnueabihf@1.1.0':resolution: {integrity: sha512-SLgIQo3f3EjkZ82ZwvrEgFvMdDAhsxCYjyoSuWfHCz0U16qx3SuGCp8+FYOPYCECHN3ZlGjXnoAIt9ERd0dEUg==}engines: {node: '>= 10'}cpu: [arm]os: [linux]'@napi-rs/tar-linux-arm64-gnu@1.1.0':resolution: {integrity: sha512-d014cdle52EGaH6GpYTQOP9Py7glMO1zz/+ynJPjjzYFSxvdYx0byrjumZk2UQdIyGZiJO2MEFpCkEEKFSgPYA==}engines: {node: '>= 10'}cpu: [arm64]os: [linux]'@napi-rs/tar-linux-arm64-musl@1.1.0':resolution: {integrity: sha512-L/y1/26q9L/uBqiW/JdOb/Dc94egFvNALUZV2WCGKQXc6UByPBMgdiEyW2dtoYxYYYYc+AKD+jr+wQPcvX2vrQ==}engines: {node: '>= 10'}cpu: [arm64]os: [linux]'@napi-rs/tar-linux-ppc64-gnu@1.1.0':resolution: {integrity: sha512-EPE1K/80RQvPbLRJDJs1QmCIcH+7WRi0F73+oTe1582y9RtfGRuzAkzeBuAGRXAQEjRQw/RjtNqr6UTJ+8UuWQ==}engines: {node: '>= 10'}cpu: [ppc64]os: [linux]'@napi-rs/tar-linux-s390x-gnu@1.1.0':resolution: {integrity: sha512-B2jhWiB1ffw1nQBqLUP1h4+J1ovAxBOoe5N2IqDMOc63fsPZKNqF1PvO/dIem8z7LL4U4bsfmhy3gBfu547oNQ==}engines: {node: '>= 10'}cpu: [s390x]os: [linux]'@napi-rs/tar-linux-x64-gnu@1.1.0':resolution: {integrity: sha512-tbZDHnb9617lTnsDMGo/eAMZxnsQFnaRe+MszRqHguKfMwkisc9CCJnks/r1o84u5fECI+J/HOrKXgczq/3Oww==}engines: {node: '>= 10'}cpu: [x64]os: [linux]'@napi-rs/tar-linux-x64-musl@1.1.0':resolution: {integrity: sha512-dV6cODlzbO8u6Anmv2N/ilQHq/AWz0xyltuXoLU3yUyXbZcnWYZuB2rL8OBGPmqNcD+x9NdScBNXh7vWN0naSQ==}engines: {node: '>= 10'}cpu: [x64]os: [linux]'@napi-rs/tar-wasm32-wasi@1.1.0':resolution: {integrity: sha512-jIa9nb2HzOrfH0F8QQ9g3WE4aMH5vSI5/1NYVNm9ysCmNjCCtMXCAhlI3WKCdm/DwHf0zLqdrrtDFXODcNaqMw==}engines: {node: '>=14.0.0'}cpu: [wasm32]'@napi-rs/tar-win32-arm64-msvc@1.1.0':resolution: {integrity: sha512-vfpG71OB0ijtjemp3WTdmBKJm9R70KM8vsSExMsIQtV0lVzP07oM1CW6JbNRPXNLhRoue9ofYLiUDk8bE0Hckg==}engines: {node: '>= 10'}cpu: [arm64]os: [win32]'@napi-rs/tar-win32-ia32-msvc@1.1.0':resolution: {integrity: sha512-hGPyPW60YSpOSgzfy68DLBHgi6HxkAM+L59ZZZPMQ0TOXjQg+p2EW87+TjZfJOkSpbYiEkULwa/f4a2hcVjsqQ==}engines: {node: '>= 10'}cpu: [ia32]os: [win32]'@napi-rs/tar-win32-x64-msvc@1.1.0':resolution: {integrity: sha512-L6Ed1DxXK9YSCMyvpR8MiNAyKNkQLjsHsHK9E0qnHa8NzLFqzDKhvs5LfnWxM2kJ+F7m/e5n9zPm24kHb3LsVw==}engines: {node: '>= 10'}cpu: [x64]os: [win32]'@napi-rs/tar@1.1.0':resolution: {integrity: sha512-7cmzIu+Vbupriudo7UudoMRH2OA3cTw67vva8MxeoAe5S7vPFI7z0vp0pMXiA25S8IUJefImQ90FeJjl8fjEaQ==}engines: {node: '>= 10'}'@napi-rs/wasm-runtime@1.0.7':resolution: {integrity: sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==}'@napi-rs/wasm-tools-android-arm-eabi@1.0.1':resolution: {integrity: sha512-lr07E/l571Gft5v4aA1dI8koJEmF1F0UigBbsqg9OWNzg80H3lDPO+auv85y3T/NHE3GirDk7x/D3sLO57vayw==}engines: {node: '>= 10'}cpu: [arm]os: [android]'@napi-rs/wasm-tools-android-arm64@1.0.1':resolution: {integrity: sha512-WDR7S+aRLV6LtBJAg5fmjKkTZIdrEnnQxgdsb7Cf8pYiMWBHLU+LC49OUVppQ2YSPY0+GeYm9yuZWW3kLjJ7Bg==}engines: {node: '>= 10'}cpu: [arm64]os: [android]'@napi-rs/wasm-tools-darwin-arm64@1.0.1':resolution: {integrity: sha512-qWTI+EEkiN0oIn/N2gQo7+TVYil+AJ20jjuzD2vATS6uIjVz+Updeqmszi7zq7rdFTLp6Ea3/z4kDKIfZwmR9g==}engines: {node: '>= 10'}cpu: [arm64]os: [darwin]'@napi-rs/wasm-tools-darwin-x64@1.0.1':resolution: {integrity: sha512-bA6hubqtHROR5UI3tToAF/c6TDmaAgF0SWgo4rADHtQ4wdn0JeogvOk50gs2TYVhKPE2ZD2+qqt7oBKB+sxW3A==}engines: {node: '>= 10'}cpu: [x64]os: [darwin]'@napi-rs/wasm-tools-freebsd-x64@1.0.1':resolution: {integrity: sha512-90+KLBkD9hZEjPQW1MDfwSt5J1L46EUKacpCZWyRuL6iIEO5CgWU0V/JnEgFsDOGyyYtiTvHc5bUdUTWd4I9Vg==}engines: {node: '>= 10'}cpu: [x64]os: [freebsd]'@napi-rs/wasm-tools-linux-arm64-gnu@1.0.1':resolution: {integrity: sha512-rG0QlS65x9K/u3HrKafDf8cFKj5wV2JHGfl8abWgKew0GVPyp6vfsDweOwHbWAjcHtp2LHi6JHoW80/MTHm52Q==}engines: {node: '>= 10'}cpu: [arm64]os: [linux]'@napi-rs/wasm-tools-linux-arm64-musl@1.0.1':resolution: {integrity: sha512-jAasbIvjZXCgX0TCuEFQr+4D6Lla/3AAVx2LmDuMjgG4xoIXzjKWl7c4chuaD+TI+prWT0X6LJcdzFT+ROKGHQ==}engines: {node: '>= 10'}cpu: [arm64]os: [linux]'@napi-rs/wasm-tools-linux-x64-gnu@1.0.1':resolution: {integrity: sha512-Plgk5rPqqK2nocBGajkMVbGm010Z7dnUgq0wtnYRZbzWWxwWcXfZMPa8EYxrK4eE8SzpI7VlZP1tdVsdjgGwMw==}engines: {node: '>= 10'}cpu: [x64]os: [linux]'@napi-rs/wasm-tools-linux-x64-musl@1.0.1':resolution: {integrity: sha512-GW7AzGuWxtQkyHknHWYFdR0CHmW6is8rG2Rf4V6GNmMpmwtXt/ItWYWtBe4zqJWycMNazpfZKSw/BpT7/MVCXQ==}engines: {node: '>= 10'}cpu: [x64]os: [linux]'@napi-rs/wasm-tools-wasm32-wasi@1.0.1':resolution: {integrity: sha512-/nQVSTrqSsn7YdAc2R7Ips/tnw5SPUcl3D7QrXCNGPqjbatIspnaexvaOYNyKMU6xPu+pc0BTnKVmqhlJJCPLA==}engines: {node: '>=14.0.0'}cpu: [wasm32]'@napi-rs/wasm-tools-win32-arm64-msvc@1.0.1':resolution: {integrity: sha512-PFi7oJIBu5w7Qzh3dwFea3sHRO3pojMsaEnUIy22QvsW+UJfNQwJCryVrpoUt8m4QyZXI+saEq/0r4GwdoHYFQ==}engines: {node: '>= 10'}cpu: [arm64]os: [win32]'@napi-rs/wasm-tools-win32-ia32-msvc@1.0.1':resolution: {integrity: sha512-gXkuYzxQsgkj05Zaq+KQTkHIN83dFAwMcTKa2aQcpYPRImFm2AQzEyLtpXmyCWzJ0F9ZYAOmbSyrNew8/us6bw==}engines: {node: '>= 10'}cpu: [ia32]os: [win32]'@napi-rs/wasm-tools-win32-x64-msvc@1.0.1':resolution: {integrity: sha512-rEAf05nol3e3eei2sRButmgXP+6ATgm0/38MKhz9Isne82T4rPIMYsCIFj0kOisaGeVwoi2fnm7O9oWp5YVnYQ==}engines: {node: '>= 10'}cpu: [x64]os: [win32]'@napi-rs/wasm-tools@1.0.1':resolution: {integrity: sha512-enkZYyuCdo+9jneCPE/0fjIta4wWnvVN9hBo2HuiMpRF0q3lzv1J6b/cl7i0mxZUKhBrV3aCKDBQnCOhwKbPmQ==}engines: {node: '>= 10'}'@octokit/auth-token@6.0.0':resolution: {integrity: sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w==}engines: {node: '>= 20'}'@octokit/core@7.0.6':resolution: {integrity: sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q==}engines: {node: '>= 20'}'@octokit/endpoint@11.0.2':resolution: {integrity: sha512-4zCpzP1fWc7QlqunZ5bSEjxc6yLAlRTnDwKtgXfcI/FxxGoqedDG8V2+xJ60bV2kODqcGB+nATdtap/XYq2NZQ==}engines: {node: '>= 20'}'@octokit/graphql@9.0.3':resolution: {integrity: sha512-grAEuupr/C1rALFnXTv6ZQhFuL1D8G5y8CN04RgrO4FIPMrtm+mcZzFG7dcBm+nq+1ppNixu+Jd78aeJOYxlGA==}engines: {node: '>= 20'}'@octokit/openapi-types@27.0.0':resolution: {integrity: sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA==}'@octokit/plugin-paginate-rest@14.0.0':resolution: {integrity: sha512-fNVRE7ufJiAA3XUrha2omTA39M6IXIc6GIZLvlbsm8QOQCYvpq/LkMNGyFlB1d8hTDzsAXa3OKtybdMAYsV/fw==}engines: {node: '>= 20'}peerDependencies:'@octokit/core': '>=6''@octokit/plugin-request-log@6.0.0':resolution: {integrity: sha512-UkOzeEN3W91/eBq9sPZNQ7sUBvYCqYbrrD8gTbBuGtHEuycE4/awMXcYvx6sVYo7LypPhmQwwpUe4Yyu4QZN5Q==}engines: {node: '>= 20'}peerDependencies:'@octokit/core': '>=6''@octokit/plugin-rest-endpoint-methods@17.0.0':resolution: {integrity: sha512-B5yCyIlOJFPqUUeiD0cnBJwWJO8lkJs5d8+ze9QDP6SvfiXSz1BF+91+0MeI1d2yxgOhU/O+CvtiZ9jSkHhFAw==}engines: {node: '>= 20'}peerDependencies:'@octokit/core': '>=6''@octokit/request-error@7.1.0':resolution: {integrity: sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw==}engines: {node: '>= 20'}'@octokit/request@10.0.7':resolution: {integrity: sha512-v93h0i1yu4idj8qFPZwjehoJx4j3Ntn+JhXsdJrG9pYaX6j/XRz2RmasMUHtNgQD39nrv/VwTWSqK0RNXR8upA==}engines: {node: '>= 20'}'@octokit/rest@22.0.1':resolution: {integrity: sha512-Jzbhzl3CEexhnivb1iQ0KJ7s5vvjMWcmRtq5aUsKmKDrRW6z3r84ngmiFKFvpZjpiU/9/S6ITPFRpn5s/3uQJw==}engines: {node: '>= 20'}'@octokit/types@16.0.0':resolution: {integrity: sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg==}'@tybys/wasm-util@0.10.1':resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==}'@types/node@22.19.1':resolution: {integrity: sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==}'@types/vscode@1.106.1':resolution: {integrity: sha512-R/HV8u2h8CAddSbX8cjpdd7B8/GnE4UjgjpuGuHcbp1xV6yh4OeqU4L1pKjlwujCrSFS0MOpwJAIs/NexMB1fQ==}ansi-regex@5.0.1:resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}engines: {node: '>=8'}ansi-styles@4.3.0:resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}engines: {node: '>=8'}argparse@2.0.1:resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}before-after-hook@4.0.0:resolution: {integrity: sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ==}chardet@2.1.1:resolution: {integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==}cli-width@4.1.0:resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==}engines: {node: '>= 12'}clipanion@4.0.0-rc.4:resolution: {integrity: sha512-CXkMQxU6s9GklO/1f714dkKBMu1lopS1WFF0B8o4AxPykR1hpozxSiUZ5ZUeBjfPgCWqbcNOtZVFhB8Lkfp1+Q==}peerDependencies:typanion: '*'color-convert@2.0.1:resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}engines: {node: '>=7.0.0'}color-name@1.1.4:resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}colorette@2.0.20:resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==}debug@4.4.3:resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}engines: {node: '>=6.0'}peerDependencies:supports-color: '*'peerDependenciesMeta:supports-color:optional: trueemnapi@1.7.1:resolution: {integrity: sha512-wlLK2xFq+T+rCBlY6+lPlFVDEyE93b7hSn9dMrfWBIcPf4ArwUvymvvMnN9M5WWuiryYQe9M+UJrkqw4trdyRA==}peerDependencies:node-addon-api: '>= 6.1.0'peerDependenciesMeta:node-addon-api:optional: trueemoji-regex@8.0.0:resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}es-toolkit@1.42.0:resolution: {integrity: sha512-SLHIyY7VfDJBM8clz4+T2oquwTQxEzu263AyhVK4jREOAwJ+8eebaa4wM3nlvnAqhDrMm2EsA6hWHaQsMPQ1nA==}fast-content-type-parse@3.0.0:resolution: {integrity: sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg==}iconv-lite@0.7.0:resolution: {integrity: sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==}engines: {node: '>=0.10.0'}is-fullwidth-code-point@3.0.0:resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}engines: {node: '>=8'}js-yaml@4.1.1:resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==}hasBin: truems@2.1.3:resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}mute-stream@2.0.0:resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==}engines: {node: ^18.17.0 || >=20.5.0}safer-buffer@2.1.2:resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}semver@7.7.3:resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==}engines: {node: '>=10'}hasBin: truesignal-exit@4.1.0:resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}engines: {node: '>=14'}string-width@4.2.3:resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}engines: {node: '>=8'}strip-ansi@6.0.1:resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}engines: {node: '>=8'}tslib@2.8.1:resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}typanion@3.14.0:resolution: {integrity: sha512-ZW/lVMRabETuYCd9O9ZvMhAh8GslSqaUjxmK/JLPCh6l73CvLBiuXswj/+7LdnWOgYsQ130FqLzFz5aGT4I3Ug==}typescript@5.9.3:resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}engines: {node: '>=14.17'}hasBin: trueundici-types@6.21.0:resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}universal-user-agent@7.0.3:resolution: {integrity: sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==}wrap-ansi@6.2.0:resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}engines: {node: '>=8'}yoctocolors-cjs@2.1.3:resolution: {integrity: sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==}engines: {node: '>=18'}snapshots:'@emnapi/core@1.7.1':dependencies:'@emnapi/wasi-threads': 1.1.0tslib: 2.8.1optional: true'@emnapi/runtime@1.7.1':dependencies:tslib: 2.8.1optional: true'@emnapi/wasi-threads@1.1.0':dependencies:tslib: 2.8.1optional: true'@inquirer/ansi@1.0.2': {}'@inquirer/checkbox@4.3.2(@types/node@22.19.1)':dependencies:'@inquirer/ansi': 1.0.2'@inquirer/core': 10.3.2(@types/node@22.19.1)'@inquirer/figures': 1.0.15'@inquirer/type': 3.0.10(@types/node@22.19.1)yoctocolors-cjs: 2.1.3optionalDependencies:'@types/node': 22.19.1'@inquirer/confirm@5.1.21(@types/node@22.19.1)':dependencies:'@inquirer/core': 10.3.2(@types/node@22.19.1)'@inquirer/type': 3.0.10(@types/node@22.19.1)optionalDependencies:'@types/node': 22.19.1'@inquirer/core@10.3.2(@types/node@22.19.1)':dependencies:'@inquirer/ansi': 1.0.2'@inquirer/figures': 1.0.15'@inquirer/type': 3.0.10(@types/node@22.19.1)cli-width: 4.1.0mute-stream: 2.0.0signal-exit: 4.1.0wrap-ansi: 6.2.0yoctocolors-cjs: 2.1.3optionalDependencies:'@types/node': 22.19.1'@inquirer/editor@4.2.23(@types/node@22.19.1)':dependencies:'@inquirer/core': 10.3.2(@types/node@22.19.1)'@inquirer/external-editor': 1.0.3(@types/node@22.19.1)'@inquirer/type': 3.0.10(@types/node@22.19.1)optionalDependencies:'@types/node': 22.19.1'@inquirer/expand@4.0.23(@types/node@22.19.1)':dependencies:'@inquirer/core': 10.3.2(@types/node@22.19.1)'@inquirer/type': 3.0.10(@types/node@22.19.1)yoctocolors-cjs: 2.1.3optionalDependencies:'@types/node': 22.19.1'@inquirer/external-editor@1.0.3(@types/node@22.19.1)':dependencies:chardet: 2.1.1iconv-lite: 0.7.0optionalDependencies:'@types/node': 22.19.1'@inquirer/figures@1.0.15': {}'@inquirer/input@4.3.1(@types/node@22.19.1)':dependencies:'@inquirer/core': 10.3.2(@types/node@22.19.1)'@inquirer/type': 3.0.10(@types/node@22.19.1)optionalDependencies:'@types/node': 22.19.1'@inquirer/number@3.0.23(@types/node@22.19.1)':dependencies:'@inquirer/core': 10.3.2(@types/node@22.19.1)'@inquirer/type': 3.0.10(@types/node@22.19.1)optionalDependencies:'@types/node': 22.19.1'@inquirer/password@4.0.23(@types/node@22.19.1)':dependencies:'@inquirer/ansi': 1.0.2'@inquirer/core': 10.3.2(@types/node@22.19.1)'@inquirer/type': 3.0.10(@types/node@22.19.1)optionalDependencies:'@types/node': 22.19.1'@inquirer/prompts@7.10.1(@types/node@22.19.1)':dependencies:'@inquirer/checkbox': 4.3.2(@types/node@22.19.1)'@inquirer/confirm': 5.1.21(@types/node@22.19.1)'@inquirer/editor': 4.2.23(@types/node@22.19.1)'@inquirer/expand': 4.0.23(@types/node@22.19.1)'@inquirer/input': 4.3.1(@types/node@22.19.1)'@inquirer/number': 3.0.23(@types/node@22.19.1)'@inquirer/password': 4.0.23(@types/node@22.19.1)'@inquirer/rawlist': 4.1.11(@types/node@22.19.1)'@inquirer/search': 3.2.2(@types/node@22.19.1)'@inquirer/select': 4.4.2(@types/node@22.19.1)optionalDependencies:'@types/node': 22.19.1'@inquirer/rawlist@4.1.11(@types/node@22.19.1)':dependencies:'@inquirer/core': 10.3.2(@types/node@22.19.1)'@inquirer/type': 3.0.10(@types/node@22.19.1)yoctocolors-cjs: 2.1.3optionalDependencies:'@types/node': 22.19.1'@inquirer/search@3.2.2(@types/node@22.19.1)':dependencies:'@inquirer/core': 10.3.2(@types/node@22.19.1)'@inquirer/figures': 1.0.15'@inquirer/type': 3.0.10(@types/node@22.19.1)yoctocolors-cjs: 2.1.3optionalDependencies:'@types/node': 22.19.1'@inquirer/select@4.4.2(@types/node@22.19.1)':dependencies:'@inquirer/ansi': 1.0.2'@inquirer/core': 10.3.2(@types/node@22.19.1)'@inquirer/figures': 1.0.15'@inquirer/type': 3.0.10(@types/node@22.19.1)yoctocolors-cjs: 2.1.3optionalDependencies:'@types/node': 22.19.1'@inquirer/type@3.0.10(@types/node@22.19.1)':optionalDependencies:'@types/node': 22.19.1'@napi-rs/cli@3.4.1(@emnapi/runtime@1.7.1)(@types/node@22.19.1)':dependencies:'@inquirer/prompts': 7.10.1(@types/node@22.19.1)'@napi-rs/cross-toolchain': 1.0.3'@napi-rs/wasm-tools': 1.0.1'@octokit/rest': 22.0.1clipanion: 4.0.0-rc.4(typanion@3.14.0)colorette: 2.0.20debug: 4.4.3emnapi: 1.7.1es-toolkit: 1.42.0js-yaml: 4.1.1semver: 7.7.3typanion: 3.14.0optionalDependencies:'@emnapi/runtime': 1.7.1transitivePeerDependencies:- '@napi-rs/cross-toolchain-arm64-target-aarch64'- '@napi-rs/cross-toolchain-arm64-target-armv7'- '@napi-rs/cross-toolchain-arm64-target-ppc64le'- '@napi-rs/cross-toolchain-arm64-target-s390x'- '@napi-rs/cross-toolchain-arm64-target-x86_64'- '@napi-rs/cross-toolchain-x64-target-aarch64'- '@napi-rs/cross-toolchain-x64-target-armv7'- '@napi-rs/cross-toolchain-x64-target-ppc64le'- '@napi-rs/cross-toolchain-x64-target-s390x'- '@napi-rs/cross-toolchain-x64-target-x86_64'- '@types/node'- node-addon-api- supports-color'@napi-rs/cross-toolchain@1.0.3':dependencies:'@napi-rs/lzma': 1.4.5'@napi-rs/tar': 1.1.0debug: 4.4.3transitivePeerDependencies:- supports-color'@napi-rs/lzma-android-arm-eabi@1.4.5':optional: true'@napi-rs/lzma-android-arm64@1.4.5':optional: true'@napi-rs/lzma-darwin-arm64@1.4.5':optional: true'@napi-rs/lzma-darwin-x64@1.4.5':optional: true'@napi-rs/lzma-freebsd-x64@1.4.5':optional: true'@napi-rs/lzma-linux-arm-gnueabihf@1.4.5':optional: true'@napi-rs/lzma-linux-arm64-gnu@1.4.5':optional: true'@napi-rs/lzma-linux-arm64-musl@1.4.5':optional: true'@napi-rs/lzma-linux-ppc64-gnu@1.4.5':optional: true'@napi-rs/lzma-linux-riscv64-gnu@1.4.5':optional: true'@napi-rs/lzma-linux-s390x-gnu@1.4.5':optional: true'@napi-rs/lzma-linux-x64-gnu@1.4.5':optional: true'@napi-rs/lzma-linux-x64-musl@1.4.5':optional: true'@napi-rs/lzma-wasm32-wasi@1.4.5':dependencies:'@napi-rs/wasm-runtime': 1.0.7optional: true'@napi-rs/lzma-win32-arm64-msvc@1.4.5':optional: true'@napi-rs/lzma-win32-ia32-msvc@1.4.5':optional: true'@napi-rs/lzma-win32-x64-msvc@1.4.5':optional: true'@napi-rs/lzma@1.4.5':optionalDependencies:'@napi-rs/lzma-android-arm-eabi': 1.4.5'@napi-rs/lzma-android-arm64': 1.4.5'@napi-rs/lzma-darwin-arm64': 1.4.5'@napi-rs/lzma-darwin-x64': 1.4.5'@napi-rs/lzma-freebsd-x64': 1.4.5'@napi-rs/lzma-linux-arm-gnueabihf': 1.4.5'@napi-rs/lzma-linux-arm64-gnu': 1.4.5'@napi-rs/lzma-linux-arm64-musl': 1.4.5'@napi-rs/lzma-linux-ppc64-gnu': 1.4.5'@napi-rs/lzma-linux-riscv64-gnu': 1.4.5'@napi-rs/lzma-linux-s390x-gnu': 1.4.5'@napi-rs/lzma-linux-x64-gnu': 1.4.5'@napi-rs/lzma-linux-x64-musl': 1.4.5'@napi-rs/lzma-wasm32-wasi': 1.4.5'@napi-rs/lzma-win32-arm64-msvc': 1.4.5'@napi-rs/lzma-win32-ia32-msvc': 1.4.5'@napi-rs/lzma-win32-x64-msvc': 1.4.5'@napi-rs/tar-android-arm-eabi@1.1.0':optional: true'@napi-rs/tar-android-arm64@1.1.0':optional: true'@napi-rs/tar-darwin-arm64@1.1.0':optional: true'@napi-rs/tar-darwin-x64@1.1.0':optional: true'@napi-rs/tar-freebsd-x64@1.1.0':optional: true'@napi-rs/tar-linux-arm-gnueabihf@1.1.0':optional: true'@napi-rs/tar-linux-arm64-gnu@1.1.0':optional: true'@napi-rs/tar-linux-arm64-musl@1.1.0':optional: true'@napi-rs/tar-linux-ppc64-gnu@1.1.0':optional: true'@napi-rs/tar-linux-s390x-gnu@1.1.0':optional: true'@napi-rs/tar-linux-x64-gnu@1.1.0':optional: true'@napi-rs/tar-linux-x64-musl@1.1.0':optional: true'@napi-rs/tar-wasm32-wasi@1.1.0':dependencies:'@napi-rs/wasm-runtime': 1.0.7optional: true'@napi-rs/tar-win32-arm64-msvc@1.1.0':optional: true'@napi-rs/tar-win32-ia32-msvc@1.1.0':optional: true'@napi-rs/tar-win32-x64-msvc@1.1.0':optional: true'@napi-rs/tar@1.1.0':optionalDependencies:'@napi-rs/tar-android-arm-eabi': 1.1.0'@napi-rs/tar-android-arm64': 1.1.0'@napi-rs/tar-darwin-arm64': 1.1.0'@napi-rs/tar-darwin-x64': 1.1.0'@napi-rs/tar-freebsd-x64': 1.1.0'@napi-rs/tar-linux-arm-gnueabihf': 1.1.0'@napi-rs/tar-linux-arm64-gnu': 1.1.0'@napi-rs/tar-linux-arm64-musl': 1.1.0'@napi-rs/tar-linux-ppc64-gnu': 1.1.0'@napi-rs/tar-linux-s390x-gnu': 1.1.0'@napi-rs/tar-linux-x64-gnu': 1.1.0'@napi-rs/tar-linux-x64-musl': 1.1.0'@napi-rs/tar-wasm32-wasi': 1.1.0'@napi-rs/tar-win32-arm64-msvc': 1.1.0'@napi-rs/tar-win32-ia32-msvc': 1.1.0'@napi-rs/tar-win32-x64-msvc': 1.1.0'@napi-rs/wasm-runtime@1.0.7':dependencies:'@emnapi/core': 1.7.1'@emnapi/runtime': 1.7.1'@tybys/wasm-util': 0.10.1optional: true'@napi-rs/wasm-tools-android-arm-eabi@1.0.1':optional: true'@napi-rs/wasm-tools-android-arm64@1.0.1':optional: true'@napi-rs/wasm-tools-darwin-arm64@1.0.1':optional: true'@napi-rs/wasm-tools-darwin-x64@1.0.1':optional: true'@napi-rs/wasm-tools-freebsd-x64@1.0.1':optional: true'@napi-rs/wasm-tools-linux-arm64-gnu@1.0.1':optional: true'@napi-rs/wasm-tools-linux-arm64-musl@1.0.1':optional: true'@napi-rs/wasm-tools-linux-x64-gnu@1.0.1':optional: true'@napi-rs/wasm-tools-linux-x64-musl@1.0.1':optional: true'@napi-rs/wasm-tools-wasm32-wasi@1.0.1':dependencies:'@napi-rs/wasm-runtime': 1.0.7optional: true'@napi-rs/wasm-tools-win32-arm64-msvc@1.0.1':optional: true'@napi-rs/wasm-tools-win32-ia32-msvc@1.0.1':optional: true'@napi-rs/wasm-tools-win32-x64-msvc@1.0.1':optional: true'@napi-rs/wasm-tools@1.0.1':optionalDependencies:'@napi-rs/wasm-tools-android-arm-eabi': 1.0.1'@napi-rs/wasm-tools-android-arm64': 1.0.1'@napi-rs/wasm-tools-darwin-arm64': 1.0.1'@napi-rs/wasm-tools-darwin-x64': 1.0.1'@napi-rs/wasm-tools-freebsd-x64': 1.0.1'@napi-rs/wasm-tools-linux-arm64-gnu': 1.0.1'@napi-rs/wasm-tools-linux-arm64-musl': 1.0.1'@napi-rs/wasm-tools-linux-x64-gnu': 1.0.1'@napi-rs/wasm-tools-linux-x64-musl': 1.0.1'@napi-rs/wasm-tools-wasm32-wasi': 1.0.1'@napi-rs/wasm-tools-win32-arm64-msvc': 1.0.1'@napi-rs/wasm-tools-win32-ia32-msvc': 1.0.1'@napi-rs/wasm-tools-win32-x64-msvc': 1.0.1'@octokit/auth-token@6.0.0': {}'@octokit/core@7.0.6':dependencies:'@octokit/auth-token': 6.0.0'@octokit/graphql': 9.0.3'@octokit/request': 10.0.7'@octokit/request-error': 7.1.0'@octokit/types': 16.0.0before-after-hook: 4.0.0universal-user-agent: 7.0.3'@octokit/endpoint@11.0.2':dependencies:'@octokit/types': 16.0.0universal-user-agent: 7.0.3'@octokit/graphql@9.0.3':dependencies:'@octokit/request': 10.0.7'@octokit/types': 16.0.0universal-user-agent: 7.0.3'@octokit/openapi-types@27.0.0': {}'@octokit/plugin-paginate-rest@14.0.0(@octokit/core@7.0.6)':dependencies:'@octokit/core': 7.0.6'@octokit/types': 16.0.0'@octokit/plugin-request-log@6.0.0(@octokit/core@7.0.6)':dependencies:'@octokit/core': 7.0.6'@octokit/plugin-rest-endpoint-methods@17.0.0(@octokit/core@7.0.6)':dependencies:'@octokit/core': 7.0.6'@octokit/types': 16.0.0'@octokit/request-error@7.1.0':dependencies:'@octokit/types': 16.0.0'@octokit/request@10.0.7':dependencies:'@octokit/endpoint': 11.0.2'@octokit/request-error': 7.1.0'@octokit/types': 16.0.0fast-content-type-parse: 3.0.0universal-user-agent: 7.0.3'@octokit/rest@22.0.1':dependencies:'@octokit/core': 7.0.6'@octokit/plugin-paginate-rest': 14.0.0(@octokit/core@7.0.6)'@octokit/plugin-request-log': 6.0.0(@octokit/core@7.0.6)'@octokit/plugin-rest-endpoint-methods': 17.0.0(@octokit/core@7.0.6)'@octokit/types@16.0.0':dependencies:'@octokit/openapi-types': 27.0.0'@tybys/wasm-util@0.10.1':dependencies:tslib: 2.8.1optional: true'@types/node@22.19.1':dependencies:undici-types: 6.21.0'@types/vscode@1.106.1': {}ansi-regex@5.0.1: {}ansi-styles@4.3.0:dependencies:color-convert: 2.0.1argparse@2.0.1: {}before-after-hook@4.0.0: {}chardet@2.1.1: {}cli-width@4.1.0: {}clipanion@4.0.0-rc.4(typanion@3.14.0):dependencies:typanion: 3.14.0color-convert@2.0.1:dependencies:color-name: 1.1.4color-name@1.1.4: {}colorette@2.0.20: {}debug@4.4.3:dependencies:ms: 2.1.3emnapi@1.7.1: {}emoji-regex@8.0.0: {}es-toolkit@1.42.0: {}fast-content-type-parse@3.0.0: {}iconv-lite@0.7.0:dependencies:safer-buffer: 2.1.2is-fullwidth-code-point@3.0.0: {}js-yaml@4.1.1:dependencies:argparse: 2.0.1ms@2.1.3: {}mute-stream@2.0.0: {}safer-buffer@2.1.2: {}semver@7.7.3: {}signal-exit@4.1.0: {}string-width@4.2.3:dependencies:emoji-regex: 8.0.0is-fullwidth-code-point: 3.0.0strip-ansi: 6.0.1strip-ansi@6.0.1:dependencies:ansi-regex: 5.0.1tslib@2.8.1:optional: truetypanion@3.14.0: {}typescript@5.9.3: {}undici-types@6.21.0: {}universal-user-agent@7.0.3: {}wrap-ansi@6.2.0:dependencies:ansi-styles: 4.3.0string-width: 4.2.3strip-ansi: 6.0.1yoctocolors-cjs@2.1.3: {}
{"name": "pijul","displayName": "Pijul","description": "The Pijul version control system","version": "0.0.1","engines": {"node": ">= 12.22.0 < 13 || >= 14.17.0 < 15 || >= 15.12.0 < 16 || >= 16.0.0","vscode": "^1.105.0"},"categories": ["SCM Providers"],"activationEvents": ["*"],"main": "./out/extension.js","contributes": {"colors": [{"id": "pijul.decorations.path.untracked","description": "Color of untracked paths in the file explorer","defaults": {"light": "gitDecoration.untrackedResourceForeground","dark": "gitDecoration.untrackedResourceForeground"}},{"id": "pijul.decorations.path.added","description": "Color of added paths in the file explorer","defaults": {"light": "gitDecoration.addedResourceForeground","dark": "gitDecoration.addedResourceForeground"}},{"id": "pijul.decorations.path.removed","description": "Color of removed paths in the file explorer","defaults": {"light": "gitDecoration.deletedResourceForeground","dark": "gitDecoration.deletedResourceForeground"}},{"id": "pijul.decorations.path.modified","description": "Color of modified paths in the file explorer","defaults": {"light": "gitDecoration.modifiedResourceForeground","dark": "gitDecoration.modifiedResourceForeground"}},{"id": "pijul.decorations.path.moved","description": "Color of moved paths in the file explorer","defaults": {"light": "gitDecoration.renamedResourceForeground","dark": "gitDecoration.renamedResourceForeground"}},{"id": "pijul.decorations.path.modifiedAndMoved","description": "Color of paths that have been both modified and moved in the file explorer","defaults": {"light": "gitDecoration.modifiedResourceForeground","dark": "gitDecoration.modifiedResourceForeground"}},{"id": "pijul.decorations.inlineCredit.foreground","description": "Color of inline credit annotations rendered beside text selections","defaults": {"light": "git.blame.editorDecorationForeground","dark": "git.blame.editorDecorationForeground"}}],"commands": [{"command": "pijul-vscode.helloWorld","title": "Hello World"}]},"napi": {"binaryName": "pijul-vscode"},"devDependencies": {"@napi-rs/cli": "^3.3.1","@types/node": "22.x","@types/vscode": "^1.105.0","typescript": "^5.9.3"}}
local = Youremote = { $username }unknown = { $public-key-signature }tracked = { $authors }, { $timestamp } • { $message }untracked = { $timestamp } • Untracked changes
fn main() {napi_build::setup();}
[package]name = "pijul-vscode"description = "Pijul version control support for Visual Studio Code"# Keys inherited from workspaceauthors.workspace = truecategories.workspace = trueedition.workspace = truekeywords.workspace = truelicense.workspace = truerepository.workspace = trueversion.workspace = true[lib]crate-type = ["cdylib"][dependencies]pijul-extension.workspace = truecamino.workspace = trueicu_locale.workspace = truejiff.workspace = truel10n_embed.workspace = truel10n_embed_derive.workspace = truenapi.workspace = truenapi-derive.workspace = truenapi-sys.workspace = trueropey.workspace = truetracing.workspace = truetracing-subscriber.workspace = true[build-dependencies]napi-build.workspace = true
[workspace]resolver = "3"members = ["xtask", "pijul-extension", "extensions/vscode"][workspace.package]authors = ["Finchie <rust@finchie.dev>"]categories = ["development-tools", "text-editors"]edition = "2024"keywords = ["version control", "vcs", "editor"]repository = "https://nest.pijul.com/finchie/extension"license = "MIT OR Apache-2.0"version = "0.1.0"[workspace.lints.clippy]all = "deny"pedantic = "warn"nursery = "warn"cargo = "warn"[workspace.dependencies]pijul-extension.path = "pijul-extension"anyhow = "1.0"camino = "1.1"canonical-path = "2.0"cargo_metadata = "0.23"clap = { version = "4.5", features = ["derive"] }icu_locale = "2.0"jiff = "0.2"l10n_embed = "0.2"l10n_embed_derive = "0.2"# TODO: remove unused featureslibpijul.path = "../pijul/libpijul"napi = { version = "3.0", features = ["napi5"] }napi-build = "2"napi-derive = "3.0"napi-sys = "3.0"path-slash = "0.2"pijul-identity.path = "../pijul/pijul-identity"ropey = "2.0.0-beta"serde_json = "1.0"thiserror = "2"tracing = "0.1"tracing-subscriber = "0.3"
# This file is automatically @generated by Cargo.# It is not intended for manual editing.version = 4[[package]]name = "addr2line"version = "0.25.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b"dependencies = ["gimli",][[package]]name = "adler2"version = "2.0.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"[[package]]name = "adler32"version = "1.2.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"[[package]]name = "aes"version = "0.7.5"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8"dependencies = ["cfg-if","cipher 0.3.0","cpufeatures","ctr","opaque-debug",][[package]]name = "aho-corasick"version = "1.1.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"dependencies = ["memchr",][[package]]name = "android_system_properties"version = "0.1.5"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"dependencies = ["libc",][[package]]name = "anstream"version = "0.6.21"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a"dependencies = ["anstyle","anstyle-parse","anstyle-query","anstyle-wincon","colorchoice","is_terminal_polyfill","utf8parse",][[package]]name = "anstyle"version = "1.0.13"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78"[[package]]name = "anstyle-parse"version = "0.2.7"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"dependencies = ["utf8parse",][[package]]name = "anstyle-query"version = "1.1.4"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2"dependencies = ["windows-sys 0.60.2",][[package]]name = "anstyle-wincon"version = "3.0.10"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a"dependencies = ["anstyle","once_cell_polyfill","windows-sys 0.60.2",][[package]]name = "anyhow"version = "1.0.100"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"[[package]]name = "arrayref"version = "0.3.9"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"[[package]]name = "arrayvec"version = "0.7.6"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"[[package]]name = "atomic"version = "0.6.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "a89cbf775b137e9b968e67227ef7f775587cde3fd31b0d8599dbd0f598a48340"dependencies = ["bytemuck",][[package]]name = "autocfg"version = "1.5.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"[[package]]name = "backtrace"version = "0.3.76"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6"dependencies = ["addr2line","cfg-if","libc","miniz_oxide","object","rustc-demangle","windows-link",][[package]]name = "backtrace-ext"version = "0.2.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50"dependencies = ["backtrace",][[package]]name = "base64"version = "0.22.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"[[package]]name = "base64ct"version = "1.8.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba"[[package]]name = "bcrypt-pbkdf"version = "0.10.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "6aeac2e1fe888769f34f05ac343bbef98b14d1ffb292ab69d4608b3abc86f2a2"dependencies = ["blowfish","pbkdf2 0.12.2","sha2 0.10.9",][[package]]name = "bincode"version = "1.3.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"dependencies = ["serde",][[package]]name = "bit-vec"version = "0.6.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"[[package]]name = "bitflags"version = "1.3.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"[[package]]name = "bitflags"version = "2.9.4"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394"dependencies = ["serde",][[package]]name = "blake3"version = "1.8.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "3888aaa89e4b2a40fca9848e400f6a658a5a3978de7be858e209cafa8be9a4a0"dependencies = ["arrayref","arrayvec","cc","cfg-if","constant_time_eq",][[package]]name = "block-buffer"version = "0.9.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"dependencies = ["generic-array",][[package]]name = "block-buffer"version = "0.10.4"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"dependencies = ["generic-array",][[package]]name = "block-modes"version = "0.8.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "2cb03d1bed155d89dce0f845b7899b18a9a163e148fd004e1c28421a783e2d8e"dependencies = ["block-padding","cipher 0.3.0",][[package]]name = "block-padding"version = "0.2.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae"[[package]]name = "blowfish"version = "0.9.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7"dependencies = ["byteorder","cipher 0.4.4",][[package]]name = "bs58"version = "0.4.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3"[[package]]name = "bstr"version = "1.12.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4"dependencies = ["memchr","serde",][[package]]name = "bumpalo"version = "3.19.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"[[package]]name = "bytemuck"version = "1.24.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4"[[package]]name = "byteorder"version = "1.5.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"[[package]]name = "bytes"version = "1.11.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3"[[package]]name = "camino"version = "1.2.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "276a59bf2b2c967788139340c9f0c5b12d7fd6630315c15c217e559de85d2609"dependencies = ["serde_core",][[package]]name = "canonical-path"version = "2.0.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "e6e9e01327e6c86e92ec72b1c798d4a94810f147209bbe3ffab6a86954937a6f"[[package]]name = "cargo-platform"version = "0.3.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "122ec45a44b270afd1402f351b782c676b173e3c3fb28d86ff7ebfb4d86a4ee4"dependencies = ["serde",][[package]]name = "cargo_metadata"version = "0.23.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "981a6f317983eec002839b90fae7411a85621410ae591a9cab2ecf5cb5744873"dependencies = ["camino","cargo-platform","semver","serde","serde_json","thiserror 2.0.17",][[package]]name = "cc"version = "1.2.41"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "ac9fe6cdbb24b6ade63616c0a0688e45bb56732262c158df3c0c4bea4ca47cb7"dependencies = ["find-msvc-tools","shlex",][[package]]name = "cfg-if"version = "1.0.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"[[package]]name = "chardetng"version = "0.1.17"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "14b8f0b65b7b08ae3c8187e8d77174de20cb6777864c6b832d8ad365999cf1ea"dependencies = ["cfg-if","encoding_rs","memchr",][[package]]name = "chrono"version = "0.4.42"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2"dependencies = ["iana-time-zone","num-traits","serde","windows-link",][[package]]name = "cipher"version = "0.3.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7"dependencies = ["generic-array",][[package]]name = "cipher"version = "0.4.4"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"dependencies = ["crypto-common","inout",][[package]]name = "clap"version = "4.5.49"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "f4512b90fa68d3a9932cea5184017c5d200f5921df706d45e853537dea51508f"dependencies = ["clap_builder","clap_derive",][[package]]name = "clap_builder"version = "4.5.49"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "0025e98baa12e766c67ba13ff4695a887a1eba19569aad00a472546795bd6730"dependencies = ["anstream","anstyle","clap_lex","strsim",][[package]]name = "clap_derive"version = "4.5.49"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671"dependencies = ["heck","proc-macro2","quote","syn",][[package]]name = "clap_lex"version = "0.7.6"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d"[[package]]name = "colorchoice"version = "1.0.4"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"[[package]]name = "console"version = "0.15.11"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8"dependencies = ["encode_unicode","libc","once_cell","unicode-width 0.2.2","windows-sys 0.59.0",][[package]]name = "const_format"version = "0.2.35"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "7faa7469a93a566e9ccc1c73fe783b4a65c274c5ace346038dca9c39fe0030ad"dependencies = ["const_format_proc_macros",][[package]]name = "const_format_proc_macros"version = "0.2.34"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744"dependencies = ["proc-macro2","quote","unicode-xid",][[package]]name = "constant_time_eq"version = "0.3.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6"[[package]]name = "convert_case"version = "0.8.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "baaaa0ecca5b51987b9423ccdc971514dd8b0bb7b4060b983d3664dad3f1f89f"dependencies = ["unicode-segmentation",][[package]]name = "core-foundation"version = "0.9.4"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"dependencies = ["core-foundation-sys","libc",][[package]]name = "core-foundation"version = "0.10.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6"dependencies = ["core-foundation-sys","libc",][[package]]name = "core-foundation-sys"version = "0.8.7"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"[[package]]name = "cpufeatures"version = "0.2.17"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"dependencies = ["libc",][[package]]name = "crc32fast"version = "1.5.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"dependencies = ["cfg-if",][[package]]name = "crossbeam-deque"version = "0.8.6"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"dependencies = ["crossbeam-epoch","crossbeam-utils",][[package]]name = "crossbeam-epoch"version = "0.9.18"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"dependencies = ["crossbeam-utils",][[package]]name = "crossbeam-utils"version = "0.8.21"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"[[package]]name = "crypto-common"version = "0.1.7"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"dependencies = ["generic-array","typenum",][[package]]name = "crypto-mac"version = "0.11.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714"dependencies = ["generic-array","subtle",][[package]]name = "cryptovec"version = "0.6.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "ccc7fa13a6bbb2322d325292c57f4c8e7291595506f8289968a0eb61c3130bdf"dependencies = ["libc","winapi",][[package]]name = "ctor"version = "0.5.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "67773048316103656a637612c4a62477603b777d91d9c62ff2290f9cde178fdb"dependencies = ["ctor-proc-macro","dtor",][[package]]name = "ctor-proc-macro"version = "0.0.6"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "e2931af7e13dc045d8e9d26afccc6fa115d64e115c9c84b1166288b46f6782c2"[[package]]name = "ctr"version = "0.8.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea"dependencies = ["cipher 0.3.0",][[package]]name = "curve25519-dalek"version = "3.2.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0"dependencies = ["byteorder","digest 0.9.0","rand_core 0.5.1","serde","subtle","zeroize",][[package]]name = "darling"version = "0.21.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0"dependencies = ["darling_core","darling_macro",][[package]]name = "darling_core"version = "0.21.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4"dependencies = ["fnv","ident_case","proc-macro2","quote","strsim","syn",][[package]]name = "darling_macro"version = "0.21.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81"dependencies = ["darling_core","quote","syn",][[package]]name = "data-encoding"version = "2.9.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476"[[package]]name = "dbus"version = "0.9.9"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "190b6255e8ab55a7b568df5a883e9497edc3e4821c06396612048b430e5ad1e9"dependencies = ["libc","libdbus-sys","windows-sys 0.59.0",][[package]]name = "dbus-secret-service"version = "4.0.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b42a16374481d92aed73ae45b1f120207d8e71d24fb89f357fadbd8f946fd84b"dependencies = ["dbus","futures-util","num","once_cell","rand 0.8.5",][[package]]name = "deranged"version = "0.5.5"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587"dependencies = ["powerfmt","serde_core",][[package]]name = "dialoguer"version = "0.10.4"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "59c6f2989294b9a498d3ad5491a79c6deb604617378e1cdc4bfc1c1361fe2f87"dependencies = ["console","fuzzy-matcher","shell-words","tempfile","zeroize",][[package]]name = "diffs"version = "0.5.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "ff116c9781d74b71b9b8958281309dd2faaeabad2f0a3df27e50bd79ce5dc805"[[package]]name = "digest"version = "0.9.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"dependencies = ["generic-array",][[package]]name = "digest"version = "0.10.7"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"dependencies = ["block-buffer 0.10.4","crypto-common","subtle",][[package]]name = "dirs"version = "3.0.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309"dependencies = ["dirs-sys",][[package]]name = "dirs-next"version = "2.0.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"dependencies = ["cfg-if","dirs-sys-next",][[package]]name = "dirs-sys"version = "0.3.7"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"dependencies = ["libc","redox_users","winapi",][[package]]name = "dirs-sys-next"version = "0.1.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"dependencies = ["libc","redox_users","winapi",][[package]]name = "displaydoc"version = "0.2.5"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"dependencies = ["proc-macro2","quote","syn",][[package]]name = "dtor"version = "0.1.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "e58a0764cddb55ab28955347b45be00ade43d4d6f3ba4bf3dc354e4ec9432934"dependencies = ["dtor-proc-macro",][[package]]name = "dtor-proc-macro"version = "0.0.6"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5"[[package]]name = "duplicate"version = "2.0.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "8e92f10a49176cbffacaedabfaa11d51db1ea0f80a83c26e1873b43cd1742c24"dependencies = ["heck","proc-macro2","proc-macro2-diagnostics",][[package]]name = "dyn-clone"version = "1.0.20"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555"[[package]]name = "ed25519"version = "1.5.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7"dependencies = ["serde","signature",][[package]]name = "ed25519-dalek"version = "1.0.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d"dependencies = ["curve25519-dalek","ed25519","rand 0.7.3","serde","serde_bytes","sha2 0.9.9","zeroize",][[package]]name = "either"version = "1.15.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"[[package]]name = "encode_unicode"version = "1.0.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0"[[package]]name = "encoding_rs"version = "0.8.35"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3"dependencies = ["cfg-if",][[package]]name = "equivalent"version = "1.0.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"[[package]]name = "errno"version = "0.3.14"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"dependencies = ["libc","windows-sys 0.61.2",][[package]]name = "fastrand"version = "2.3.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"[[package]]name = "figment"version = "0.10.19"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "8cb01cd46b0cf372153850f4c6c272d9cbea2da513e07538405148f95bd789f3"dependencies = ["atomic","serde","toml","uncased","version_check",][[package]]name = "find-msvc-tools"version = "0.1.4"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127"[[package]]name = "fixed_decimal"version = "0.7.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "35943d22b2f19c0cb198ecf915910a8158e94541c89dcc63300d7799d46c2c5e"dependencies = ["displaydoc","ryu","smallvec","writeable",][[package]]name = "fluent-syntax"version = "0.12.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "54f0d287c53ffd184d04d8677f590f4ac5379785529e5e08b1c8083acdd5c198"dependencies = ["memchr","thiserror 2.0.17",][[package]]name = "fnv"version = "1.0.7"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"[[package]]name = "foldhash"version = "0.1.5"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"[[package]]name = "foreign-types"version = "0.3.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"dependencies = ["foreign-types-shared",][[package]]name = "foreign-types-shared"version = "0.1.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"[[package]]name = "form_urlencoded"version = "1.2.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf"dependencies = ["percent-encoding",][[package]]name = "fs2"version = "0.4.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"dependencies = ["libc","winapi",][[package]]name = "futures"version = "0.3.31"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"dependencies = ["futures-channel","futures-core","futures-executor","futures-io","futures-sink","futures-task","futures-util",][[package]]name = "futures-channel"version = "0.3.31"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"dependencies = ["futures-core","futures-sink",][[package]]name = "futures-core"version = "0.3.31"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"[[package]]name = "futures-executor"version = "0.3.31"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"dependencies = ["futures-core","futures-task","futures-util",][[package]]name = "futures-io"version = "0.3.31"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"[[package]]name = "futures-macro"version = "0.3.31"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"dependencies = ["proc-macro2","quote","syn",][[package]]name = "futures-sink"version = "0.3.31"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"[[package]]name = "futures-task"version = "0.3.31"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"[[package]]name = "futures-util"version = "0.3.31"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"dependencies = ["futures-channel","futures-core","futures-io","futures-macro","futures-sink","futures-task","memchr","pin-project-lite","pin-utils","slab",][[package]]name = "fuzzy-matcher"version = "0.3.7"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "54614a3312934d066701a80f20f15fa3b56d67ac7722b39eea5b4c9dd1d66c94"dependencies = ["thread_local",][[package]]name = "generic-array"version = "0.14.7"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"dependencies = ["typenum","version_check",][[package]]name = "getrandom"version = "0.1.16"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"dependencies = ["cfg-if","libc","wasi 0.9.0+wasi-snapshot-preview1",][[package]]name = "getrandom"version = "0.2.16"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"dependencies = ["cfg-if","js-sys","libc","wasi 0.11.1+wasi-snapshot-preview1","wasm-bindgen",][[package]]name = "getrandom"version = "0.3.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"dependencies = ["cfg-if","libc","r-efi","wasi 0.14.7+wasi-0.2.4",][[package]]name = "gimli"version = "0.32.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7"[[package]]name = "globset"version = "0.4.16"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "54a1028dfc5f5df5da8a56a73e6c153c9a9708ec57232470703592a3f18e49f5"dependencies = ["aho-corasick","bstr","log","regex-automata","regex-syntax",][[package]]name = "hashbrown"version = "0.12.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"[[package]]name = "hashbrown"version = "0.15.5"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"dependencies = ["foldhash",][[package]]name = "hashbrown"version = "0.16.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d"[[package]]name = "heck"version = "0.5.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"[[package]]name = "hermit-abi"version = "0.5.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"[[package]]name = "hex"version = "0.4.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"[[package]]name = "hmac"version = "0.11.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b"dependencies = ["crypto-mac","digest 0.9.0",][[package]]name = "iana-time-zone"version = "0.1.64"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb"dependencies = ["android_system_properties","core-foundation-sys","iana-time-zone-haiku","js-sys","log","wasm-bindgen","windows-core",][[package]]name = "iana-time-zone-haiku"version = "0.1.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"dependencies = ["cc",][[package]]name = "icu_casemap"version = "2.0.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "6dc5e74b3c9d7b63e0d7c5fd54ee8c135705df2ea2aa558082dd555dc9747a97"dependencies = ["displaydoc","icu_casemap_data","icu_collections","icu_locale_core","icu_properties","icu_provider","potential_utf","writeable","zerovec",][[package]]name = "icu_casemap_data"version = "2.0.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "f7584067558ab4c60c95d1ac2abd1588689cb4bcd4e099507f62dae86ae8d2c0"[[package]]name = "icu_collections"version = "2.0.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47"dependencies = ["displaydoc","potential_utf","serde","yoke","zerofrom","zerovec",][[package]]name = "icu_decimal"version = "2.0.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "fec61c43fdc4e368a9f450272833123a8ef0d7083a44597660ce94d791b8a2e2"dependencies = ["displaydoc","fixed_decimal","icu_decimal_data","icu_locale","icu_locale_core","icu_provider","tinystr","writeable","zerovec",][[package]]name = "icu_decimal_data"version = "2.0.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b70963bc35f9bdf1bc66a5c1f458f4991c1dc71760e00fa06016b2c76b2738d5"[[package]]name = "icu_experimental"version = "0.3.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "ebe3d7e64892a434b08d5a58b53127e47a095ff780305f563c8c01798a1051b0"dependencies = ["displaydoc","either","fixed_decimal","icu_casemap","icu_collections","icu_decimal","icu_experimental_data","icu_list","icu_locale","icu_locale_core","icu_normalizer","icu_pattern","icu_plurals","icu_properties","icu_provider","litemap","num-bigint","num-rational","num-traits","potential_utf","smallvec","tinystr","writeable","zerofrom","zerotrie","zerovec",][[package]]name = "icu_experimental_data"version = "0.3.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b60d32ba5610adfc2083f5a759f55d9a9082ebf72750f126cb1630844eea1acf"[[package]]name = "icu_list"version = "2.0.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "e26f94ec776bb8b28cedc7dcf91033b822c5cb4c1783cf7a3f796fc168aa0c8b"dependencies = ["displaydoc","icu_list_data","icu_locale","icu_provider","regex-automata","writeable","zerovec",][[package]]name = "icu_list_data"version = "2.0.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "5a456a2412458ca45e181d9d51c5090ef8cd90f5692e11d34bafab3b3be1c76b"[[package]]name = "icu_locale"version = "2.0.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "6ae5921528335e91da1b6c695dbf1ec37df5ac13faa3f91e5640be93aa2fbefd"dependencies = ["displaydoc","icu_collections","icu_locale_core","icu_locale_data","icu_provider","potential_utf","serde","tinystr","zerovec",][[package]]name = "icu_locale_core"version = "2.0.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a"dependencies = ["displaydoc","litemap","serde","tinystr","writeable","zerovec",][[package]]name = "icu_locale_data"version = "2.0.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "4fdef0c124749d06a743c69e938350816554eb63ac979166590e2b4ee4252765"[[package]]name = "icu_normalizer"version = "2.0.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979"dependencies = ["displaydoc","icu_collections","icu_normalizer_data","icu_properties","icu_provider","smallvec","zerovec",][[package]]name = "icu_normalizer_data"version = "2.0.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3"[[package]]name = "icu_pattern"version = "0.4.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "983825f401e6bc4a13c45d552ffd9ad6f3f6b6bc0ec03f31d6835a90a46deb1f"dependencies = ["displaydoc","either","writeable","yoke","zerovec",][[package]]name = "icu_plurals"version = "2.0.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "0fd83a65f58b6f28e1f3da8c6ada6b415ee3ad5cb480b75bdb669f34d72dd179"dependencies = ["displaydoc","fixed_decimal","icu_locale","icu_plurals_data","icu_provider","zerovec",][[package]]name = "icu_plurals_data"version = "2.0.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "9ec552d761eaf4a1c39ad28936e0af77a41bf01ff756ea54be4f8bfc21c265d7"[[package]]name = "icu_properties"version = "2.0.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b"dependencies = ["displaydoc","icu_collections","icu_locale_core","icu_properties_data","icu_provider","potential_utf","zerotrie","zerovec",][[package]]name = "icu_properties_data"version = "2.0.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632"[[package]]name = "icu_provider"version = "2.0.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af"dependencies = ["displaydoc","icu_locale_core","serde","stable_deref_trait","tinystr","writeable","yoke","zerofrom","zerotrie","zerovec",][[package]]name = "ident_case"version = "1.0.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"[[package]]name = "idna"version = "1.1.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de"dependencies = ["idna_adapter","smallvec","utf8_iter",][[package]]name = "idna_adapter"version = "1.2.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344"dependencies = ["icu_normalizer","icu_properties",][[package]]name = "ignore"version = "0.4.23"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "6d89fd380afde86567dfba715db065673989d6253f42b88179abd3eae47bda4b"dependencies = ["crossbeam-deque","globset","log","memchr","regex-automata","same-file","walkdir","winapi-util",][[package]]name = "imara-diff"version = "0.1.8"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "17d34b7d42178945f775e84bc4c36dde7c1c6cdfea656d3354d009056f2bb3d2"dependencies = ["hashbrown 0.15.5",][[package]]name = "indexmap"version = "1.9.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"dependencies = ["autocfg","hashbrown 0.12.3","serde",][[package]]name = "indexmap"version = "2.11.4"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5"dependencies = ["equivalent","hashbrown 0.16.0","serde","serde_core",][[package]]name = "indicatif"version = "0.17.11"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235"dependencies = ["console","number_prefix","portable-atomic","unicode-segmentation","unicode-width 0.2.2","web-time",][[package]]name = "inout"version = "0.1.4"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"dependencies = ["generic-array",][[package]]name = "instant"version = "0.1.13"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"dependencies = ["cfg-if",][[package]]name = "is_ci"version = "1.2.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45"[[package]]name = "is_terminal_polyfill"version = "1.70.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"[[package]]name = "itertools"version = "0.11.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57"dependencies = ["either",][[package]]name = "itoa"version = "1.0.15"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"[[package]]name = "jiff"version = "0.2.15"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49"dependencies = ["jiff-static","jiff-tzdb-platform","log","portable-atomic","portable-atomic-util","serde","windows-sys 0.59.0",][[package]]name = "jiff-static"version = "0.2.15"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4"dependencies = ["proc-macro2","quote","syn",][[package]]name = "jiff-tzdb"version = "0.1.4"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "c1283705eb0a21404d2bfd6eef2a7593d240bc42a0bdb39db0ad6fa2ec026524"[[package]]name = "jiff-tzdb-platform"version = "0.1.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8"dependencies = ["jiff-tzdb",][[package]]name = "js-sys"version = "0.3.81"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305"dependencies = ["once_cell","wasm-bindgen",][[package]]name = "keyring"version = "3.6.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "1961983669d57bdfe6c0f3ef8e4c229b5ef751afcc7d87e4271d2f71f6ccfa8b"dependencies = ["byteorder","dbus-secret-service","linux-keyutils","log","security-framework 2.11.1","security-framework 3.5.1","windows-sys 0.59.0",][[package]]name = "l10n_embed"version = "0.2.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "27e524acc0bf1aa0fd5608dfb4c5af944ef81bc5fd6241f68a6df3db004a4b57"dependencies = ["anstyle","camino","fixed_decimal","icu_decimal","icu_experimental","icu_list","icu_locale","icu_plurals","jiff","serde","writeable",][[package]]name = "l10n_embed_derive"version = "0.2.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "80a1f091c73d5861392a5bb327086370bca82a36f58f54781a8530707dad07ca"dependencies = ["camino","fixed_decimal","fluent-syntax","heck","icu_locale","l10n_embed","miette","proc-macro-error2","proc-macro2","quote","syn","thiserror 2.0.17","wax",][[package]]name = "lazy_static"version = "1.5.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"[[package]]name = "libc"version = "0.2.177"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"[[package]]name = "libdbus-sys"version = "0.2.6"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "5cbe856efeb50e4681f010e9aaa2bf0a644e10139e54cde10fc83a307c23bd9f"dependencies = ["pkg-config",][[package]]name = "libloading"version = "0.8.9"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55"dependencies = ["cfg-if","windows-link",][[package]]name = "libpijul"version = "1.0.0-beta.10"dependencies = ["adler32","aes","bincode","bitflags 2.9.4","blake3","bs58","byteorder","canonical-path","chardetng","crossbeam-deque","curve25519-dalek","data-encoding","diffs","ed25519-dalek","encoding_rs","generic-array","getrandom 0.2.16","hmac","ignore","imara-diff","jiff","log","lru-cache","nom","parking_lot 0.12.5","path-slash","pbkdf2 0.9.0","pijul-macros","rand 0.8.5","regex","sanakirja","serde","serde_derive","serde_json","sha2 0.9.9","tempfile","thiserror 2.0.17","toml","twox-hash","zstd-seekable",][[package]]name = "libredox"version = "0.1.10"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb"dependencies = ["bitflags 2.9.4","libc","redox_syscall 0.5.18",][[package]]name = "libsodium-sys"version = "0.2.7"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "6b779387cd56adfbc02ea4a668e704f729be8d6a6abd2c27ca5ee537849a92fd"dependencies = ["cc","libc","pkg-config","walkdir",][[package]]name = "linked-hash-map"version = "0.5.6"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"[[package]]name = "linux-keyutils"version = "0.2.4"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "761e49ec5fd8a5a463f9b84e877c373d888935b71c6be78f3767fe2ae6bed18e"dependencies = ["bitflags 2.9.4","libc",][[package]]name = "linux-raw-sys"version = "0.11.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"[[package]]name = "litemap"version = "0.8.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956"[[package]]name = "lock_api"version = "0.4.14"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"dependencies = ["scopeguard",][[package]]name = "log"version = "0.4.28"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"[[package]]name = "lru-cache"version = "0.1.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c"dependencies = ["linked-hash-map",][[package]]name = "md5"version = "0.7.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771"[[package]]name = "memchr"version = "2.7.6"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"[[package]]name = "memmap2"version = "0.9.8"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "843a98750cd611cc2965a8213b53b43e715f13c37a9e096c6408e69990961db7"dependencies = ["libc",][[package]]name = "miette"version = "7.6.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "5f98efec8807c63c752b5bd61f862c165c115b0a35685bdcfd9238c7aeb592b7"dependencies = ["backtrace","backtrace-ext","cfg-if","miette-derive","owo-colors","supports-color","supports-hyperlinks","supports-unicode","terminal_size","textwrap","unicode-width 0.1.14",][[package]]name = "miette-derive"version = "7.6.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b"dependencies = ["proc-macro2","quote","syn",][[package]]name = "minimal-lexical"version = "0.2.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"[[package]]name = "miniz_oxide"version = "0.8.9"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"dependencies = ["adler2",][[package]]name = "mio"version = "1.1.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873"dependencies = ["libc","wasi 0.11.1+wasi-snapshot-preview1","windows-sys 0.61.2",][[package]]name = "napi"version = "3.3.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "f1b74e3dce5230795bb4d2821b941706dee733c7308752507254b0497f39cad7"dependencies = ["bitflags 2.9.4","ctor","napi-build","napi-sys","nohash-hasher","rustc-hash",][[package]]name = "napi-build"version = "2.2.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "dcae8ad5609d14afb3a3b91dee88c757016261b151e9dcecabf1b2a31a6cab14"[[package]]name = "napi-derive"version = "3.2.5"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "7552d5a579b834614bbd496db5109f1b9f1c758f08224b0dee1e408333adf0d0"dependencies = ["convert_case","ctor","napi-derive-backend","proc-macro2","quote","syn",][[package]]name = "napi-derive-backend"version = "2.2.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "5f6a81ac7486b70f2532a289603340862c06eea5a1e650c1ffeda2ce1238516a"dependencies = ["convert_case","proc-macro2","quote","semver","syn",][[package]]name = "napi-sys"version = "3.0.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "3e4e7135a8f97aa0f1509cce21a8a1f9dcec1b50d8dee006b48a5adb69a9d64d"dependencies = ["libloading",][[package]]name = "nohash-hasher"version = "0.2.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451"[[package]]name = "nom"version = "7.1.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"dependencies = ["memchr","minimal-lexical",][[package]]name = "nu-ansi-term"version = "0.50.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"dependencies = ["windows-sys 0.61.2",][[package]]name = "num"version = "0.4.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23"dependencies = ["num-bigint","num-complex","num-integer","num-iter","num-rational","num-traits",][[package]]name = "num-bigint"version = "0.4.6"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"dependencies = ["num-integer","num-traits",][[package]]name = "num-complex"version = "0.4.6"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"dependencies = ["num-traits",][[package]]name = "num-conv"version = "0.1.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"[[package]]name = "num-integer"version = "0.1.46"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"dependencies = ["num-traits",][[package]]name = "num-iter"version = "0.1.45"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"dependencies = ["autocfg","num-integer","num-traits",][[package]]name = "num-rational"version = "0.4.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"dependencies = ["num-bigint","num-integer","num-traits",][[package]]name = "num-traits"version = "0.2.19"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"dependencies = ["autocfg",][[package]]name = "num_cpus"version = "1.17.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b"dependencies = ["hermit-abi","libc",][[package]]name = "number_prefix"version = "0.4.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"[[package]]name = "object"version = "0.37.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe"dependencies = ["memchr",][[package]]name = "once_cell"version = "1.21.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"[[package]]name = "once_cell_polyfill"version = "1.70.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"[[package]]name = "opaque-debug"version = "0.3.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"[[package]]name = "openssl"version = "0.10.75"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328"dependencies = ["bitflags 2.9.4","cfg-if","foreign-types","libc","once_cell","openssl-macros","openssl-sys",][[package]]name = "openssl-macros"version = "0.1.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"dependencies = ["proc-macro2","quote","syn",][[package]]name = "openssl-sys"version = "0.9.111"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321"dependencies = ["cc","libc","pkg-config","vcpkg",][[package]]name = "owo-colors"version = "4.2.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52"[[package]]name = "parking_lot"version = "0.11.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"dependencies = ["instant","lock_api","parking_lot_core 0.8.6",][[package]]name = "parking_lot"version = "0.12.5"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"dependencies = ["lock_api","parking_lot_core 0.9.12",][[package]]name = "parking_lot_core"version = "0.8.6"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc"dependencies = ["cfg-if","instant","libc","redox_syscall 0.2.16","smallvec","winapi",][[package]]name = "parking_lot_core"version = "0.9.12"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"dependencies = ["cfg-if","libc","redox_syscall 0.5.18","smallvec","windows-link",][[package]]name = "password-hash"version = "0.2.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "77e0b28ace46c5a396546bcf443bf422b57049617433d8854227352a4a9b24e7"dependencies = ["base64ct","rand_core 0.6.4","subtle",][[package]]name = "path-slash"version = "0.2.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "1e91099d4268b0e11973f036e885d652fb0b21fedcf69738c627f94db6a44f42"[[package]]name = "pbkdf2"version = "0.8.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "d95f5254224e617595d2cc3cc73ff0a5eaf2637519e25f03388154e9378b6ffa"dependencies = ["base64ct","crypto-mac","hmac","password-hash","sha2 0.9.9",][[package]]name = "pbkdf2"version = "0.9.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "f05894bce6a1ba4be299d0c5f29563e08af2bc18bb7d48313113bed71e904739"dependencies = ["crypto-mac",][[package]]name = "pbkdf2"version = "0.12.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2"dependencies = ["digest 0.10.7",][[package]]name = "percent-encoding"version = "2.3.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"[[package]]name = "pijul-config"version = "1.0.0-beta.10"dependencies = ["anyhow","dialoguer","dirs-next","figment","icu_locale","libpijul","log","serde","serde_derive","serde_with","toml","whoami",][[package]]name = "pijul-extension"version = "0.1.0"dependencies = ["camino","canonical-path","libpijul","path-slash","pijul-identity","ropey","serde_json","thiserror 2.0.17","tracing",][[package]]name = "pijul-identity"version = "1.0.0-beta.10"dependencies = ["anyhow","dirs-next","jiff","keyring","libpijul","log","pijul-config","pijul-interaction","serde","serde_derive","serde_json","thiserror 2.0.17","thrussh-keys","toml","validator","whoami",][[package]]name = "pijul-interaction"version = "1.0.0-beta.10"dependencies = ["dialoguer","duplicate","indicatif","log","pijul-config","thiserror 2.0.17",][[package]]name = "pijul-macros"version = "1.0.0-beta.10"dependencies = ["proc-macro2","quote","syn",][[package]]name = "pijul-vscode"version = "0.1.0"dependencies = ["camino","icu_locale","jiff","l10n_embed","l10n_embed_derive","napi","napi-build","napi-derive","napi-sys","pijul-extension","ropey","tracing","tracing-subscriber",][[package]]name = "pin-project-lite"version = "0.2.16"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"[[package]]name = "pin-utils"version = "0.1.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"[[package]]name = "pkg-config"version = "0.3.32"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"[[package]]name = "pori"version = "0.0.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "a4a63d338dec139f56dacc692ca63ad35a6be6a797442479b55acd611d79e906"dependencies = ["nom",][[package]]name = "portable-atomic"version = "1.11.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483"[[package]]name = "portable-atomic-util"version = "0.2.4"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507"dependencies = ["portable-atomic",][[package]]name = "potential_utf"version = "0.1.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a"dependencies = ["serde","zerovec",][[package]]name = "powerfmt"version = "0.2.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"[[package]]name = "ppv-lite86"version = "0.2.21"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"dependencies = ["zerocopy",][[package]]name = "proc-macro-error-attr2"version = "2.0.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5"dependencies = ["proc-macro2","quote",][[package]]name = "proc-macro-error2"version = "2.0.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802"dependencies = ["proc-macro-error-attr2","proc-macro2","quote","syn",][[package]]name = "proc-macro2"version = "1.0.101"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"dependencies = ["unicode-ident",][[package]]name = "proc-macro2-diagnostics"version = "0.10.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8"dependencies = ["proc-macro2","quote","syn","version_check",][[package]]name = "quote"version = "1.0.41"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"dependencies = ["proc-macro2",][[package]]name = "r-efi"version = "5.3.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"[[package]]name = "rand"version = "0.7.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"dependencies = ["getrandom 0.1.16","libc","rand_chacha 0.2.2","rand_core 0.5.1","rand_hc",][[package]]name = "rand"version = "0.8.5"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"dependencies = ["libc","rand_chacha 0.3.1","rand_core 0.6.4",][[package]]name = "rand_chacha"version = "0.2.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"dependencies = ["ppv-lite86","rand_core 0.5.1",][[package]]name = "rand_chacha"version = "0.3.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"dependencies = ["ppv-lite86","rand_core 0.6.4",][[package]]name = "rand_core"version = "0.5.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"dependencies = ["getrandom 0.1.16",][[package]]name = "rand_core"version = "0.6.4"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"dependencies = ["getrandom 0.2.16",][[package]]name = "rand_hc"version = "0.2.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"dependencies = ["rand_core 0.5.1",][[package]]name = "redox_syscall"version = "0.2.16"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"dependencies = ["bitflags 1.3.2",][[package]]name = "redox_syscall"version = "0.5.18"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"dependencies = ["bitflags 2.9.4",][[package]]name = "redox_users"version = "0.4.6"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43"dependencies = ["getrandom 0.2.16","libredox","thiserror 1.0.69",][[package]]name = "ref-cast"version = "1.0.25"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d"dependencies = ["ref-cast-impl",][[package]]name = "ref-cast-impl"version = "1.0.25"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da"dependencies = ["proc-macro2","quote","syn",][[package]]name = "regex"version = "1.12.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "4a52d8d02cacdb176ef4678de6c052efb4b3da14b78e4db683a4252762be5433"dependencies = ["aho-corasick","memchr","regex-automata","regex-syntax",][[package]]name = "regex-automata"version = "0.4.12"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "722166aa0d7438abbaa4d5cc2c649dac844e8c56d82fb3d33e9c34b5cd268fc6"dependencies = ["aho-corasick","memchr","regex-syntax",][[package]]name = "regex-syntax"version = "0.8.7"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "c3160422bbd54dd5ecfdca71e5fd59b7b8fe2b1697ab2baf64f6d05dcc66d298"[[package]]name = "ropey"version = "2.0.0-beta.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "4045a00dc327d084a2bbf126976e14125b54f23bd30511d45b842eba76c52d74"dependencies = ["str_indices",][[package]]name = "rustc-demangle"version = "0.1.26"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace"[[package]]name = "rustc-hash"version = "2.1.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"[[package]]name = "rustix"version = "1.1.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e"dependencies = ["bitflags 2.9.4","errno","libc","linux-raw-sys","windows-sys 0.61.2",][[package]]name = "rustversion"version = "1.0.22"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"[[package]]name = "ryu"version = "1.0.20"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"[[package]]name = "same-file"version = "1.0.6"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"dependencies = ["winapi-util",][[package]]name = "sanakirja"version = "1.4.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "81aaf70d064e2122209f04d01fd91e8908e7a327b516236e1cbc0c3f34ac6d11"dependencies = ["crc32fast","fs2","lazy_static","log","memmap2","parking_lot 0.11.2","sanakirja-core","serde","thiserror 1.0.69",][[package]]name = "sanakirja-core"version = "1.4.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "8376db34ae3eac6e7bd91168bc638450073b708ce9fb46940de676f552238bf5"dependencies = ["crc32fast",][[package]]name = "schemars"version = "0.9.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f"dependencies = ["dyn-clone","ref-cast","serde","serde_json",][[package]]name = "schemars"version = "1.1.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "9558e172d4e8533736ba97870c4b2cd63f84b382a3d6eb063da41b91cce17289"dependencies = ["dyn-clone","ref-cast","serde","serde_json",][[package]]name = "scopeguard"version = "1.2.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"[[package]]name = "security-framework"version = "2.11.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"dependencies = ["bitflags 2.9.4","core-foundation 0.9.4","core-foundation-sys","libc","security-framework-sys",][[package]]name = "security-framework"version = "3.5.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef"dependencies = ["bitflags 2.9.4","core-foundation 0.10.1","core-foundation-sys","libc","security-framework-sys",][[package]]name = "security-framework-sys"version = "2.15.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0"dependencies = ["core-foundation-sys","libc",][[package]]name = "semver"version = "1.0.27"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"dependencies = ["serde","serde_core",][[package]]name = "serde"version = "1.0.228"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"dependencies = ["serde_core","serde_derive",][[package]]name = "serde_bytes"version = "0.11.19"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8"dependencies = ["serde","serde_core",][[package]]name = "serde_core"version = "1.0.228"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"dependencies = ["serde_derive",][[package]]name = "serde_derive"version = "1.0.228"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"dependencies = ["proc-macro2","quote","syn",][[package]]name = "serde_json"version = "1.0.145"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c"dependencies = ["itoa","memchr","ryu","serde","serde_core",][[package]]name = "serde_spanned"version = "0.6.9"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3"dependencies = ["serde",][[package]]name = "serde_with"version = "3.16.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "10574371d41b0d9b2cff89418eda27da52bcaff2cc8741db26382a77c29131f1"dependencies = ["base64","chrono","hex","indexmap 1.9.3","indexmap 2.11.4","schemars 0.9.0","schemars 1.1.0","serde_core","serde_json","serde_with_macros","time",][[package]]name = "serde_with_macros"version = "3.16.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "08a72d8216842fdd57820dc78d840bef99248e35fb2554ff923319e60f2d686b"dependencies = ["darling","proc-macro2","quote","syn",][[package]]name = "sha2"version = "0.9.9"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800"dependencies = ["block-buffer 0.9.0","cfg-if","cpufeatures","digest 0.9.0","opaque-debug",][[package]]name = "sha2"version = "0.10.9"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"dependencies = ["cfg-if","cpufeatures","digest 0.10.7",][[package]]name = "sharded-slab"version = "0.1.7"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"dependencies = ["lazy_static",][[package]]name = "shell-words"version = "1.1.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"[[package]]name = "shlex"version = "1.3.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"[[package]]name = "signature"version = "1.6.4"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c"[[package]]name = "slab"version = "0.4.11"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"[[package]]name = "smallvec"version = "1.15.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"[[package]]name = "socket2"version = "0.6.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881"dependencies = ["libc","windows-sys 0.60.2",][[package]]name = "stable_deref_trait"version = "1.2.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"[[package]]name = "static_assertions"version = "1.1.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"[[package]]name = "str_indices"version = "0.4.4"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "d08889ec5408683408db66ad89e0e1f93dff55c73a4ccc71c427d5b277ee47e6"[[package]]name = "strsim"version = "0.11.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"[[package]]name = "subtle"version = "2.4.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"[[package]]name = "supports-color"version = "3.0.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "c64fc7232dd8d2e4ac5ce4ef302b1d81e0b80d055b9d77c7c4f51f6aa4c867d6"dependencies = ["is_ci",][[package]]name = "supports-hyperlinks"version = "3.1.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "804f44ed3c63152de6a9f90acbea1a110441de43006ea51bcce8f436196a288b"[[package]]name = "supports-unicode"version = "3.0.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2"[[package]]name = "syn"version = "2.0.106"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"dependencies = ["proc-macro2","quote","unicode-ident",][[package]]name = "synstructure"version = "0.13.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"dependencies = ["proc-macro2","quote","syn",][[package]]name = "tempfile"version = "3.23.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16"dependencies = ["fastrand","getrandom 0.3.3","once_cell","rustix","windows-sys 0.61.2",][[package]]name = "terminal_size"version = "0.4.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "60b8cb979cb11c32ce1603f8137b22262a9d131aaa5c37b5678025f22b8becd0"dependencies = ["rustix","windows-sys 0.60.2",][[package]]name = "textwrap"version = "0.16.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057"dependencies = ["unicode-linebreak","unicode-width 0.2.2",][[package]]name = "thiserror"version = "1.0.69"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"dependencies = ["thiserror-impl 1.0.69",][[package]]name = "thiserror"version = "2.0.17"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8"dependencies = ["thiserror-impl 2.0.17",][[package]]name = "thiserror-impl"version = "1.0.69"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"dependencies = ["proc-macro2","quote","syn",][[package]]name = "thiserror-impl"version = "2.0.17"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"dependencies = ["proc-macro2","quote","syn",][[package]]name = "thread_local"version = "1.1.9"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185"dependencies = ["cfg-if",][[package]]name = "threadpool"version = "1.8.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa"dependencies = ["num_cpus",][[package]]name = "thrussh-keys"version = "0.22.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "c43d59b13e4c08db0e379bced99bda596ac5ed33651d919bf3916d34ad4259bb"dependencies = ["aes","bcrypt-pbkdf","bit-vec","block-modes","byteorder","cryptovec","data-encoding","dirs","futures","hmac","log","md5","num-bigint","num-integer","openssl","pbkdf2 0.8.0","rand 0.8.5","serde","serde_derive","sha2 0.9.9","thiserror 1.0.69","thrussh-libsodium","tokio","tokio-stream","yasna",][[package]]name = "thrussh-libsodium"version = "0.2.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "5f4f9c0eb4cff7225e782f7c4930c7b1f9caedf45c182e2d8602c0ec34679a1e"dependencies = ["lazy_static","libc","libsodium-sys","pkg-config","vcpkg",][[package]]name = "time"version = "0.3.44"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d"dependencies = ["deranged","itoa","num-conv","powerfmt","serde","time-core","time-macros",][[package]]name = "time-core"version = "0.1.6"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b"[[package]]name = "time-macros"version = "0.2.24"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3"dependencies = ["num-conv","time-core",][[package]]name = "tinystr"version = "0.8.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b"dependencies = ["displaydoc","serde","zerovec",][[package]]name = "tokio"version = "1.48.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408"dependencies = ["bytes","libc","mio","pin-project-lite","socket2","windows-sys 0.61.2",][[package]]name = "tokio-stream"version = "0.1.17"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047"dependencies = ["futures-core","pin-project-lite","tokio",][[package]]name = "toml"version = "0.8.23"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362"dependencies = ["indexmap 2.11.4","serde","serde_spanned","toml_datetime","toml_edit",][[package]]name = "toml_datetime"version = "0.6.11"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"dependencies = ["serde",][[package]]name = "toml_edit"version = "0.22.27"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"dependencies = ["indexmap 2.11.4","serde","serde_spanned","toml_datetime","toml_write","winnow",][[package]]name = "toml_write"version = "0.1.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"[[package]]name = "tracing"version = "0.1.41"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"dependencies = ["pin-project-lite","tracing-attributes","tracing-core",][[package]]name = "tracing-attributes"version = "0.1.30"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903"dependencies = ["proc-macro2","quote","syn",][[package]]name = "tracing-core"version = "0.1.34"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678"dependencies = ["once_cell","valuable",][[package]]name = "tracing-log"version = "0.2.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"dependencies = ["log","once_cell","tracing-core",][[package]]name = "tracing-subscriber"version = "0.3.20"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5"dependencies = ["nu-ansi-term","sharded-slab","smallvec","thread_local","tracing-core","tracing-log",][[package]]name = "twox-hash"version = "1.6.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"dependencies = ["cfg-if","rand 0.8.5","static_assertions",][[package]]name = "typenum"version = "1.19.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"[[package]]name = "uncased"version = "0.9.10"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "e1b88fcfe09e89d3866a5c11019378088af2d24c3fbd4f0543f96b479ec90697"dependencies = ["version_check",][[package]]name = "unicode-ident"version = "1.0.19"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"[[package]]name = "unicode-linebreak"version = "0.1.5"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"[[package]]name = "unicode-segmentation"version = "1.12.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"[[package]]name = "unicode-width"version = "0.1.14"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"[[package]]name = "unicode-width"version = "0.2.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"[[package]]name = "unicode-xid"version = "0.2.6"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"[[package]]name = "url"version = "2.5.7"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b"dependencies = ["form_urlencoded","idna","percent-encoding","serde",][[package]]name = "utf8_iter"version = "1.0.4"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"[[package]]name = "utf8parse"version = "0.2.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"[[package]]name = "validator"version = "0.20.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "43fb22e1a008ece370ce08a3e9e4447a910e92621bb49b85d6e48a45397e7cfa"dependencies = ["idna","once_cell","regex","serde","serde_derive","serde_json","url",][[package]]name = "valuable"version = "0.1.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"[[package]]name = "vcpkg"version = "0.2.15"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"[[package]]name = "version_check"version = "0.9.5"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"[[package]]name = "walkdir"version = "2.5.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"dependencies = ["same-file","winapi-util",][[package]]name = "wasi"version = "0.9.0+wasi-snapshot-preview1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"[[package]]name = "wasi"version = "0.11.1+wasi-snapshot-preview1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"[[package]]name = "wasi"version = "0.14.7+wasi-0.2.4"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c"dependencies = ["wasip2",][[package]]name = "wasip2"version = "1.0.1+wasi-0.2.4"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7"dependencies = ["wit-bindgen",][[package]]name = "wasite"version = "0.1.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b"[[package]]name = "wasm-bindgen"version = "0.2.104"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d"dependencies = ["cfg-if","once_cell","rustversion","wasm-bindgen-macro","wasm-bindgen-shared",][[package]]name = "wasm-bindgen-backend"version = "0.2.104"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19"dependencies = ["bumpalo","log","proc-macro2","quote","syn","wasm-bindgen-shared",][[package]]name = "wasm-bindgen-macro"version = "0.2.104"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119"dependencies = ["quote","wasm-bindgen-macro-support",][[package]]name = "wasm-bindgen-macro-support"version = "0.2.104"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7"dependencies = ["proc-macro2","quote","syn","wasm-bindgen-backend","wasm-bindgen-shared",][[package]]name = "wasm-bindgen-shared"version = "0.2.104"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1"dependencies = ["unicode-ident",][[package]]name = "wax"version = "0.6.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "8d12a78aa0bab22d2f26ed1a96df7ab58e8a93506a3e20adb47c51a93b4e1357"dependencies = ["const_format","itertools","nom","pori","regex","thiserror 1.0.69","walkdir",][[package]]name = "web-time"version = "1.1.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb"dependencies = ["js-sys","wasm-bindgen",][[package]]name = "whoami"version = "1.6.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d"dependencies = ["libredox","wasite",][[package]]name = "winapi"version = "0.3.9"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"dependencies = ["winapi-i686-pc-windows-gnu","winapi-x86_64-pc-windows-gnu",][[package]]name = "winapi-i686-pc-windows-gnu"version = "0.4.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"[[package]]name = "winapi-util"version = "0.1.11"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"dependencies = ["windows-sys 0.61.2",][[package]]name = "winapi-x86_64-pc-windows-gnu"version = "0.4.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"[[package]]name = "windows-core"version = "0.62.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"dependencies = ["windows-implement","windows-interface","windows-link","windows-result","windows-strings",][[package]]name = "windows-implement"version = "0.60.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"dependencies = ["proc-macro2","quote","syn",][[package]]name = "windows-interface"version = "0.59.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"dependencies = ["proc-macro2","quote","syn",][[package]]name = "windows-link"version = "0.2.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"[[package]]name = "windows-result"version = "0.4.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"dependencies = ["windows-link",][[package]]name = "windows-strings"version = "0.5.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"dependencies = ["windows-link",][[package]]name = "windows-sys"version = "0.59.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"dependencies = ["windows-targets 0.52.6",][[package]]name = "windows-sys"version = "0.60.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"dependencies = ["windows-targets 0.53.5",][[package]]name = "windows-sys"version = "0.61.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"dependencies = ["windows-link",][[package]]name = "windows-targets"version = "0.52.6"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"dependencies = ["windows_aarch64_gnullvm 0.52.6","windows_aarch64_msvc 0.52.6","windows_i686_gnu 0.52.6","windows_i686_gnullvm 0.52.6","windows_i686_msvc 0.52.6","windows_x86_64_gnu 0.52.6","windows_x86_64_gnullvm 0.52.6","windows_x86_64_msvc 0.52.6",][[package]]name = "windows-targets"version = "0.53.5"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3"dependencies = ["windows-link","windows_aarch64_gnullvm 0.53.1","windows_aarch64_msvc 0.53.1","windows_i686_gnu 0.53.1","windows_i686_gnullvm 0.53.1","windows_i686_msvc 0.53.1","windows_x86_64_gnu 0.53.1","windows_x86_64_gnullvm 0.53.1","windows_x86_64_msvc 0.53.1",][[package]]name = "windows_aarch64_gnullvm"version = "0.52.6"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"[[package]]name = "windows_aarch64_gnullvm"version = "0.53.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"[[package]]name = "windows_aarch64_msvc"version = "0.52.6"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"[[package]]name = "windows_aarch64_msvc"version = "0.53.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"[[package]]name = "windows_i686_gnu"version = "0.52.6"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"[[package]]name = "windows_i686_gnu"version = "0.53.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3"[[package]]name = "windows_i686_gnullvm"version = "0.52.6"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"[[package]]name = "windows_i686_gnullvm"version = "0.53.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"[[package]]name = "windows_i686_msvc"version = "0.52.6"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"[[package]]name = "windows_i686_msvc"version = "0.53.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"[[package]]name = "windows_x86_64_gnu"version = "0.52.6"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"[[package]]name = "windows_x86_64_gnu"version = "0.53.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"[[package]]name = "windows_x86_64_gnullvm"version = "0.52.6"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"[[package]]name = "windows_x86_64_gnullvm"version = "0.53.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"[[package]]name = "windows_x86_64_msvc"version = "0.52.6"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"[[package]]name = "windows_x86_64_msvc"version = "0.53.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"[[package]]name = "winnow"version = "0.7.13"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf"dependencies = ["memchr",][[package]]name = "wit-bindgen"version = "0.46.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"[[package]]name = "writeable"version = "0.6.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb"dependencies = ["either",][[package]]name = "xtask"version = "0.1.0"dependencies = ["anyhow","camino","cargo_metadata","clap",][[package]]name = "yasna"version = "0.4.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "e262a29d0e61ccf2b6190d7050d4b237535fc76ce4c1210d9caa316f71dffa75"dependencies = ["bit-vec","num-bigint",][[package]]name = "yoke"version = "0.8.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc"dependencies = ["serde","stable_deref_trait","yoke-derive","zerofrom",][[package]]name = "yoke-derive"version = "0.8.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6"dependencies = ["proc-macro2","quote","syn","synstructure",][[package]]name = "zerocopy"version = "0.8.27"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c"dependencies = ["zerocopy-derive",][[package]]name = "zerocopy-derive"version = "0.8.27"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"dependencies = ["proc-macro2","quote","syn",][[package]]name = "zerofrom"version = "0.1.6"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"dependencies = ["zerofrom-derive",][[package]]name = "zerofrom-derive"version = "0.1.6"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"dependencies = ["proc-macro2","quote","syn","synstructure",][[package]]name = "zeroize"version = "1.3.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd"dependencies = ["zeroize_derive",][[package]]name = "zeroize_derive"version = "1.4.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"dependencies = ["proc-macro2","quote","syn",][[package]]name = "zerotrie"version = "0.2.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595"dependencies = ["displaydoc","yoke","zerofrom",][[package]]name = "zerovec"version = "0.11.4"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b"dependencies = ["serde","yoke","zerofrom","zerovec-derive",][[package]]name = "zerovec-derive"version = "0.11.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f"dependencies = ["proc-macro2","quote","syn",][[package]]name = "zstd-seekable"version = "0.1.23"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "574a117c5cdb88d1f13381ee3a19a6a45fb6ca0c98436d3a95df852b7ca6c3c2"dependencies = ["bincode","cc","libc","pkg-config","serde","serde_derive","thiserror 1.0.69","threadpool",]
// https://code.visualstudio.com/docs/debugtest/tasks{"version": "2.0.0","tasks": [{"label": "Build VSCode Extension","type": "process","command": "cargo","args": ["xtask", "build", "vscode"],"isBackground": false,"presentation": {"close": true,"reveal": "always","focus": false},"group": {"kind": "build"}}]}
// https://code.visualstudio.com/docs/debugtest/debugging-configuration{"version": "0.2.0","configurations": [{"name": "Run VSCode Extension","type": "extensionHost","request": "launch","args": ["--extensionDevelopmentPath=${workspaceFolder}/extensions/vscode"],"preLaunchTask": "Build VSCode Extension"}]}
# JavaScript/TypeScriptnode_modules/out/# Rusttarget/
[alias]xtask = "run --package xtask --"