(
path: Option<String>,
force: bool,
skip_folders: Vec<String>,
include_folders: Vec<String>,
doctor: bool,
verbose: bool,
)
| 1013 | } |
| 1014 | |
| 1015 | pub(crate) async fn handle_sync( |
| 1016 | path: Option<String>, |
| 1017 | force: bool, |
| 1018 | skip_folders: Vec<String>, |
| 1019 | include_folders: Vec<String>, |
| 1020 | doctor: bool, |
| 1021 | verbose: bool, |
| 1022 | ) -> tracedecay::errors::Result<()> { |
| 1023 | let project_path = tracedecay::config::resolve_path_with_discovery(path); |
| 1024 | if !TraceDecay::has_initialized_store(&project_path).await { |
| 1025 | eprintln!( |
| 1026 | "\x1b[31merror:\x1b[0m no TraceDecay index found at '{}'.\n\ |
| 1027 | Run \x1b[1mtracedecay init\x1b[0m to create one first.", |
| 1028 | project_path.display() |
| 1029 | ); |
| 1030 | std::process::exit(1); |
| 1031 | } |
| 1032 | if project_path.join(".codegraph").is_dir() { |
| 1033 | eprintln!( |
| 1034 | "warning: found legacy .codegraph/ directory at '{}'. \ |
| 1035 | tracedecay now uses .tracedecay/ — the old directory can be safely deleted.", |
| 1036 | project_path.display() |
| 1037 | ); |
| 1038 | } |
| 1039 | |
| 1040 | let version_handle = std::thread::spawn(tracedecay::cloud::fetch_latest_version); |
| 1041 | |
| 1042 | if force { |
| 1043 | let cg = init_and_index(&project_path, &skip_folders, &include_folders, verbose).await?; |
| 1044 | close_project_graph(cg).await?; |
| 1045 | } else { |
| 1046 | let mut cg = TraceDecay::open(&project_path).await?; |
| 1047 | cg.add_skip_folders(&skip_folders); |
| 1048 | cg.add_include_folders(&include_folders); |
| 1049 | let spinner = Spinner::new(); |
| 1050 | let sync_start = std::time::Instant::now(); |
| 1051 | let result = cg |
| 1052 | .sync_with_progress_verbose( |
| 1053 | |current, total, detail| { |
| 1054 | if current == 0 { |
| 1055 | spinner.set_message(detail); |
| 1056 | } else { |
| 1057 | let elapsed = sync_start.elapsed().as_secs_f64(); |
| 1058 | let eta = if current > 1 { |
| 1059 | let per_file = elapsed / (current - 1) as f64; |
| 1060 | let remaining = per_file * (total - current) as f64; |
| 1061 | if remaining >= 1.0 { |
| 1062 | format!(" (ETA: {remaining:.0}s)") |
| 1063 | } else { |
| 1064 | String::new() |
| 1065 | } |
| 1066 | } else { |
| 1067 | String::new() |
| 1068 | }; |
| 1069 | spinner.set_message(&format!("[{current}/{total}] syncing {detail}{eta}")); |
| 1070 | } |
| 1071 | }, |
| 1072 | |msg| { |
no test coverage detected