diff --git a/crates/tty7-gateway/src/serve.rs b/crates/tty7-gateway/src/serve.rs index 3c5c6988..9933a977 100644 --- a/crates/tty7-gateway/src/serve.rs +++ b/crates/tty7-gateway/src/serve.rs @@ -343,10 +343,13 @@ fn read_diff(cwd: &str) -> io::Result { let truncated = out.stdout.len() > MAX_DIFF; let mut patch = out.stdout; patch.truncate(MAX_DIFF); + // A new directory is one entry, as `git status` shows it, not every + // file under it: a generated folder would bury the rest. let untracked = git(&[ "ls-files", "--others", "--exclude-standard", + "--directory", "--full-name", ":/", ])?; diff --git a/crates/tty7-gateway/tests/bridge.rs b/crates/tty7-gateway/tests/bridge.rs index 8a97ec0b..75aaf56d 100644 --- a/crates/tty7-gateway/tests/bridge.rs +++ b/crates/tty7-gateway/tests/bridge.rs @@ -583,12 +583,19 @@ async fn a_paired_phone_reads_a_working_trees_changes() { run(&["commit", "-qm", "first"]); std::fs::write(repo.join("src/a.txt"), "one\ntwo\n").unwrap(); std::fs::write(repo.join("new.txt"), "hi\n").unwrap(); + std::fs::create_dir_all(repo.join("made/deep")).unwrap(); + std::fs::write(repo.join("made/deep/x.txt"), "x\n").unwrap(); + std::fs::write(repo.join("made/y.txt"), "y\n").unwrap(); // Asked from a directory inside the repository, as a pane's cwd often is. let cwd = repo.join("src").to_string_lossy().into_owned(); let diff = within(session.diff(None, &cwd)).await.unwrap(); assert!(diff.patch.contains("+two"), "{}", diff.patch); - assert_eq!(diff.untracked, vec!["new.txt".to_string()]); + // A new directory comes as itself, not as each file in it. + assert_eq!( + diff.untracked, + vec!["made/".to_string(), "new.txt".to_string()] + ); assert!(!diff.truncated); let err = within(session.diff(None, &std::env::temp_dir().to_string_lossy())) diff --git a/mobile/src/main.ts b/mobile/src/main.ts index 8fa2d75d..acb2c333 100644 --- a/mobile/src/main.ts +++ b/mobile/src/main.ts @@ -1899,7 +1899,20 @@ function renderDiff(d: api.Diff): Node[] { out.push( section( `Not tracked yet · ${d.untracked.length}`, - ...d.untracked.slice(0, 200).map((p) => h("div", { class: "row choice static" }, h("span", { class: "row-title diff-name" }, p))), + ...d.untracked.slice(0, 200).map((p) => { + // A name to read and where it is, as the folder lists say it; a + // new directory keeps its slash. + const dir = p.endsWith("/"); + const parts = p.replace(/\/$/, "").split("/"); + const leaf = parts.pop() + (dir ? "/" : ""); + return h( + "div", + { class: "row choice static" }, + h("span", { class: "row-title" }, leaf), + // The end of the folder is the part that tells them apart. + parts.length > 0 && h("span", { class: "row-meta" }, parts.length > 2 ? `…/${parts.slice(-2).join("/")}` : parts.join("/")), + ); + }), ), ); }