Skip to content

Commit e393b5c

Browse files
committed
fix(git): support diff preview for deleted files tracked in Git
1 parent fe76a02 commit e393b5c

4 files changed

Lines changed: 44 additions & 2 deletions

File tree

anycode-backend/src/code.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,22 @@ impl Code {
7474
code
7575
}
7676

77+
pub fn new_empty(path: &str, conf: &Config) -> Self {
78+
let mut code = Self::new();
79+
code.abs_path = utils::abs_file(path).unwrap_or_else(|_| path.to_string());
80+
code.file_name = utils::get_file_name(path);
81+
code.lang = detect_lang::from_path(path)
82+
.map(|lang| lang.id().to_lowercase())
83+
.unwrap_or_else(|| {
84+
conf.language
85+
.iter()
86+
.find(|l| l.types.iter().any(|t| path.ends_with(t)))
87+
.map(|lang| lang.name.clone())
88+
.unwrap_or_else(|| "text".to_string())
89+
});
90+
code
91+
}
92+
7793
pub fn from_file(path: &str, conf: &Config) -> std::io::Result<Self> {
7894
let file = File::open(path)?;
7995
let text = Rope::from_reader(BufReader::new(file))?;

anycode-backend/src/handlers/git_handler.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,3 +163,11 @@ pub async fn handle_git_unstage(
163163
};
164164
send_response(ack, result);
165165
}
166+
167+
pub async fn is_file_tracked(abs_path: &str, state: &AppState) -> bool {
168+
let git = state.git_manager.lock().await;
169+
match git.file_original(abs_path) {
170+
Ok(file) => !file.is_new,
171+
Err(_) => false,
172+
}
173+
}

anycode-backend/src/handlers/io_handler.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::{
99
use lsp_types::{Position, Range, TextDocumentContentChangeEvent};
1010
use serde::{Deserialize, Serialize};
1111
use serde_json::{self, json};
12+
use crate::handlers::git_handler::is_file_tracked;
1213
use socketioxide::extract::{AckSender, Data, SocketRef, State};
1314
use std::path::PathBuf;
1415
use tracing::{error, info, warn};
@@ -95,6 +96,14 @@ pub async fn handle_file_open(
9596
Err(e) => error_ack!(ack, &request.path, "Failed to resolve file: {:?}", e),
9697
};
9798

99+
let file_exists = std::path::Path::new(&abs_path).exists();
100+
if !file_exists && is_file_tracked(&abs_path, &state).await {
101+
let mut f2c = state.file2code.lock().await;
102+
f2c.entry(abs_path.clone()).or_insert_with(|| {
103+
Code::new_empty(&abs_path, &state.config)
104+
});
105+
}
106+
98107
let mut f2c = state.file2code.lock().await;
99108
let code = match get_or_create_code(&mut f2c, &abs_path, &state.config) {
100109
Ok(c) => c,

anycode-backend/src/utils.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,17 @@ pub fn is_search_ignored_dir(path: &std::path::Path) -> bool {
191191

192192
pub fn abs_file(input: &str) -> anyhow::Result<String> {
193193
let srcdir = std::path::PathBuf::from(input);
194-
let c = std::fs::canonicalize(&srcdir)?;
195-
Ok(c.to_string_lossy().to_string())
194+
match std::fs::canonicalize(&srcdir) {
195+
Ok(c) => Ok(c.to_string_lossy().to_string()),
196+
Err(e) => {
197+
if e.kind() == std::io::ErrorKind::NotFound {
198+
let normalized = normalize_watch_path(&srcdir);
199+
Ok(normalized.to_string_lossy().to_string())
200+
} else {
201+
Err(anyhow::Error::new(e))
202+
}
203+
}
204+
}
196205
}
197206

198207
/// Normalize a path for watcher comparisons without requiring the file to exist.

0 commit comments

Comments
 (0)