diff --git a/TODO.txt b/TODO.txt index c3dab351..3fec4988 100644 --- a/TODO.txt +++ b/TODO.txt @@ -129,3 +129,21 @@ DEBUG Prefetch I/O: read 248397 files in 702.5ms, canonicalize 322970 paths in 3 DEBUG Prefetch maps: 322970 is_file + 74573 children dirs built DEBUG Prefetch total: 248397 files + 322970 canonical paths in 7.9s get rid of this bulk path canonaclize where possible, it seems utterly pointless in most cases +we should still have the canonaclize go through a helper function as it is so we dont have to modify like 9000 locations, but just get rid of the system it blows. + +[optimize git metadata fetching] + INFO librojo::change_processor: VFS event SUPPRESSED (API syncback echo): D:\UserGenerated\steal-a-brainrot\src\ServerScriptService\UserGenerated\Analytics\init.luau +DEBUG librojo::web::api: [TIMING] handle_api_rojo: total 0ms +DEBUG librojo::web::api: Git metadata: using 1 project prefixes: ["src"] +DEBUG librojo::git: [TIMING] compute_git_metadata: git_changed_files_impl 2106ms (2 tracked, 0 untracked) +DEBUG librojo::git: [TIMING] compute_git_metadata: git_changed_files_impl 2106ms (2 tracked, 0 untracked) +DEBUG librojo::git: [TIMING] compute_git_metadata: tree resolution 0ms (2 changed -> 2 resolved) +DEBUG librojo::git: [TIMING] compute_git_metadata: batch_check_hashes 71ms (6 refs) +DEBUG librojo::git: [TIMING] compute_git_metadata: total 2179ms (2 changed_ids, 2 script_hashes, 0 new_file_ids) + INFO roblox: [Studio] [Rojo] One-shot mode: skipping all auto-accept paths, requiring explicit confirmation +DEBUG librojo::web::api: WebSocket subscription established for session 99102267-df96-4f2d-a2c3-6ea78fe97bed +DEBUG librojo::serve_session: Tree validation skipped (VALIDATE_TREE_ON_CONNECT = false) +DEBUG librojo::web::api: WebSocket subscription closed by client + INFO roblox: [Studio] [Rojo] User selections: 0 push, 0 pull, 0 ignored + INFO roblox: [Studio] [Rojo] One-shot sync: disconnecting after initial sync complete + \ No newline at end of file diff --git a/src/git.rs b/src/git.rs index 2f5dfe68..e416068f 100644 --- a/src/git.rs +++ b/src/git.rs @@ -80,46 +80,58 @@ fn git_changed_files_impl( let mut tracked = HashSet::new(); let mut untracked = HashSet::new(); - let base = initial_head.unwrap_or("HEAD"); - - let t = Instant::now(); - - let mut diff_cmd = Command::new("git"); - diff_cmd - .args(["diff", base, "--name-only"]) + let mut status_cmd = Command::new("git"); + status_cmd + .args(["status", "--porcelain", "--no-renames", "-uall"]) .current_dir(repo_root); if !project_prefixes.is_empty() { - diff_cmd.arg("--"); + status_cmd.arg("--"); for prefix in project_prefixes { - diff_cmd.arg(prefix); + status_cmd.arg(prefix); } } - let diff_output = diff_cmd.output().ok()?; - if diff_output.status.success() { - for line in String::from_utf8_lossy(&diff_output.stdout).lines() { - let trimmed = line.trim(); - if !trimmed.is_empty() { - tracked.insert(PathBuf::from(trimmed)); + let (status_output, diff_output) = if let Some(ih) = initial_head { + let mut diff_cmd = Command::new("git"); + diff_cmd + .args(["diff", ih, "--name-only"]) + .current_dir(repo_root); + if !project_prefixes.is_empty() { + diff_cmd.arg("--"); + for prefix in project_prefixes { + diff_cmd.arg(prefix); } } - } else { - log::debug!("git diff {} failed (possibly no commits yet)", base); - } - let mut cached_cmd = Command::new("git"); - cached_cmd - .args(["diff", "--cached", "--name-only"]) - .current_dir(repo_root); - if !project_prefixes.is_empty() { - cached_cmd.arg("--"); - for prefix in project_prefixes { - cached_cmd.arg(prefix); + std::thread::scope(|s| { + let diff_handle = s.spawn(move || diff_cmd.output().ok()); + let status = status_cmd.output().ok(); + let diff = diff_handle.join().ok().flatten(); + (status, diff) + }) + } else { + (status_cmd.output().ok(), None) + }; + + let output = status_output?; + if output.status.success() { + for line in String::from_utf8_lossy(&output.stdout).lines() { + if line.len() < 4 { + continue; + } + let xy = &line[..2]; + let path = &line[3..]; + if xy == "??" { + untracked.insert(PathBuf::from(path)); + } else { + tracked.insert(PathBuf::from(path)); + } } } - if let Ok(cached_output) = cached_cmd.output() { - if cached_output.status.success() { - for line in String::from_utf8_lossy(&cached_output.stdout).lines() { + + if let Some(output) = diff_output { + if output.status.success() { + for line in String::from_utf8_lossy(&output.stdout).lines() { let trimmed = line.trim(); if !trimmed.is_empty() { tracked.insert(PathBuf::from(trimmed)); @@ -128,34 +140,6 @@ fn git_changed_files_impl( } } - let mut ls_cmd = Command::new("git"); - ls_cmd - .args(["ls-files", "--others", "--exclude-standard"]) - .current_dir(repo_root); - if !project_prefixes.is_empty() { - ls_cmd.arg("--"); - for prefix in project_prefixes { - ls_cmd.arg(prefix); - } - } - if let Ok(untracked_output) = ls_cmd.output() { - if untracked_output.status.success() { - for line in String::from_utf8_lossy(&untracked_output.stdout).lines() { - let trimmed = line.trim(); - if !trimmed.is_empty() { - untracked.insert(PathBuf::from(trimmed)); - } - } - } - } - - log::debug!( - "[TIMING] compute_git_metadata: git_changed_files_impl {}ms ({} tracked, {} untracked)", - t.elapsed().as_millis(), - tracked.len(), - untracked.len() - ); - Some(ChangedFiles { tracked, untracked }) }