Skip to content

Commit

Permalink
windows: avoid UNC paths in run_ui_editor
Browse files Browse the repository at this point in the history
See jj-vcs#3986 for more details. This is a no-op for non-Windows.
  • Loading branch information
mlcui-corp committed Jul 1, 2024
1 parent 7096247 commit 1543cba
Show file tree
Hide file tree
Showing 12 changed files with 185 additions and 3 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ criterion = "0.5.1"
crossterm = { version = "0.27", default-features = false }
digest = "0.10.7"
dirs = "5.0.1"
dunce = "1.0.4"
either = "1.13.0"
esl01-renderdag = "0.3.0"
futures = "0.3.30"
Expand Down
1 change: 1 addition & 0 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ config = { workspace = true }
criterion = { workspace = true, optional = true }
crossterm = { workspace = true }
dirs = { workspace = true }
dunce = { workspace = true }
esl01-renderdag = { workspace = true }
futures = { workspace = true }
git2 = { workspace = true }
Expand Down
5 changes: 4 additions & 1 deletion cli/src/cli_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2137,7 +2137,10 @@ pub fn get_new_config_file_path(
Ok(edit_path)
}

pub fn run_ui_editor(settings: &UserSettings, edit_path: &PathBuf) -> Result<(), CommandError> {
pub fn run_ui_editor(settings: &UserSettings, edit_path: &Path) -> Result<(), CommandError> {
// Work around UNC paths not being well supported on Windows (no-op for
// non-Windows): https://github.com/martinvonz/jj/issues/3986
let edit_path = dunce::simplified(edit_path);
let editor: CommandNameAndArgs = settings
.config()
.get("ui.editor")
Expand Down
21 changes: 21 additions & 0 deletions cli/tests/test_commit_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,27 @@ fn test_commit_with_editor() {
"###);
}

#[test]
#[cfg(windows)]
fn test_commit_with_editor_avoids_unc() {
use std::path::Path;

let mut test_env = TestEnvironment::default();
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
let workspace_path = test_env.env_root().join("repo");
let edit_script = test_env.set_up_fake_editor();

std::fs::write(edit_script, "dump-path path").unwrap();
test_env.jj_cmd_ok(&workspace_path, &["commit"]);

let edited_path = std::fs::read_to_string(test_env.env_root().join("path")).unwrap();
let edited_path = Path::new(&edited_path);
// While `assert!(!edited_path.starts_with("//?/"))` could work here in most
// cases, it fails when it is not safe to strip the prefix, such as paths
// over 260 chars.
assert_eq!(edited_path, dunce::simplified(Path::new(&edited_path)));
}

#[test]
fn test_commit_interactive() {
let mut test_env = TestEnvironment::default();
Expand Down
7 changes: 5 additions & 2 deletions cli/tests/test_config_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -628,7 +628,7 @@ fn test_config_edit_user() {

let edited_path = std::fs::read_to_string(test_env.env_root().join("path")).unwrap();
let edited_path = Path::new(&edited_path);
assert_eq!(edited_path, test_env.config_path());
assert_eq!(edited_path, dunce::simplified(test_env.config_path()));
}

#[test]
Expand All @@ -643,7 +643,10 @@ fn test_config_edit_repo() {

let edited_path = std::fs::read_to_string(test_env.env_root().join("path")).unwrap();
let edited_path = Path::new(&edited_path);
assert_eq!(edited_path, repo_path.join(".jj/repo/config.toml"));
assert_eq!(
edited_path,
dunce::simplified(&repo_path.join(".jj/repo/config.toml"))
);
}

#[test]
Expand Down
21 changes: 21 additions & 0 deletions cli/tests/test_describe_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,3 +323,24 @@ fn test_describe_author() {
~
"###);
}

#[test]
#[cfg(windows)]
fn test_describe_avoids_unc() {
use std::path::Path;

let mut test_env = TestEnvironment::default();
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
let workspace_path = test_env.env_root().join("repo");
let edit_script = test_env.set_up_fake_editor();

std::fs::write(edit_script, "dump-path path").unwrap();
test_env.jj_cmd_ok(&workspace_path, &["describe"]);

let edited_path = std::fs::read_to_string(test_env.env_root().join("path")).unwrap();
let edited_path = Path::new(&edited_path);
// While `assert!(!edited_path.starts_with("//?/"))` could work here in most
// cases, it fails when it is not safe to strip the prefix, such as paths
// over 260 chars.
assert_eq!(edited_path, dunce::simplified(Path::new(&edited_path)));
}
29 changes: 29 additions & 0 deletions cli/tests/test_move_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,35 @@ fn test_move_description() {
"###);
}

#[test]
#[cfg(windows)]
fn test_move_description_editor_avoids_unc() {
use std::path::Path;

let mut test_env = TestEnvironment::default();
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
let repo_path = test_env.env_root().join("repo");

let edit_script = test_env.set_up_fake_editor();
std::fs::write(repo_path.join("file1"), "a\n").unwrap();
std::fs::write(repo_path.join("file2"), "a\n").unwrap();
test_env.jj_cmd_ok(&repo_path, &["new"]);
std::fs::write(repo_path.join("file1"), "b\n").unwrap();
std::fs::write(repo_path.join("file2"), "b\n").unwrap();
test_env.jj_cmd_ok(&repo_path, &["describe", "@-", "-m", "destination"]);
test_env.jj_cmd_ok(&repo_path, &["describe", "-m", "source"]);

std::fs::write(&edit_script, "dump-path path").unwrap();
test_env.jj_cmd_ok(&repo_path, &["move", "--to", "@-"]);

let edited_path = std::fs::read_to_string(test_env.env_root().join("path")).unwrap();
let edited_path = Path::new(&edited_path);
// While `assert!(!edited_path.starts_with("//?/"))` could work here in most
// cases, it fails when it is not safe to strip the prefix, such as paths
// over 260 chars.
assert_eq!(edited_path, dunce::simplified(Path::new(&edited_path)));
}

fn get_description(test_env: &TestEnvironment, repo_path: &Path, rev: &str) -> String {
test_env.jj_cmd_success(
repo_path,
Expand Down
20 changes: 20 additions & 0 deletions cli/tests/test_sparse_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,3 +174,23 @@ fn test_sparse_manage_patterns() {
file3
"###);
}

#[test]
fn test_sparse_editor_avoids_unc() {
use std::path::Path;

let mut test_env = TestEnvironment::default();
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
let repo_path = test_env.env_root().join("repo");
let edit_script = test_env.set_up_fake_editor();

std::fs::write(&edit_script, "dump-path path").unwrap();
test_env.jj_cmd_ok(&repo_path, &["sparse", "edit"]);

let edited_path = std::fs::read_to_string(test_env.env_root().join("path")).unwrap();
let edited_path = Path::new(&edited_path);
// While `assert!(!edited_path.starts_with("//?/"))` could work here in most
// cases, it fails when it is not safe to strip the prefix, such as paths
// over 260 chars.
assert_eq!(edited_path, dunce::simplified(Path::new(&edited_path)));
}
24 changes: 24 additions & 0 deletions cli/tests/test_split_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -538,3 +538,27 @@ fn test_split_empty() {
Hint: Use `jj new` if you want to create another empty commit.
"###);
}

#[test]
#[cfg(windows)]
fn test_split_message_editor_avoids_unc() {
use std::path::Path;

let mut test_env = TestEnvironment::default();
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
let repo_path = test_env.env_root().join("repo");

std::fs::write(repo_path.join("file1"), "foo").unwrap();
std::fs::write(repo_path.join("file2"), "foo").unwrap();

let edit_script = test_env.set_up_fake_editor();
std::fs::write(edit_script, "dump-path path").unwrap();
test_env.jj_cmd_ok(&repo_path, &["split", "file2"]);

let edited_path = std::fs::read_to_string(test_env.env_root().join("path")).unwrap();
let edited_path = Path::new(&edited_path);
// While `assert!(!edited_path.starts_with("//?/"))` could work here in most
// cases, it fails when it is not safe to strip the prefix, such as paths
// over 260 chars.
assert_eq!(edited_path, dunce::simplified(Path::new(&edited_path)));
}
29 changes: 29 additions & 0 deletions cli/tests/test_squash_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1030,6 +1030,35 @@ fn test_squash_description() {
"###);
}

#[test]
#[cfg(windows)]
fn test_squash_description_editor_avoids_unc() {
use std::path::Path;

let mut test_env = TestEnvironment::default();
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
let repo_path = test_env.env_root().join("repo");

let edit_script = test_env.set_up_fake_editor();
std::fs::write(repo_path.join("file1"), "a\n").unwrap();
std::fs::write(repo_path.join("file2"), "a\n").unwrap();
test_env.jj_cmd_ok(&repo_path, &["new"]);
std::fs::write(repo_path.join("file1"), "b\n").unwrap();
std::fs::write(repo_path.join("file2"), "b\n").unwrap();
test_env.jj_cmd_ok(&repo_path, &["describe", "@-", "-m", "destination"]);
test_env.jj_cmd_ok(&repo_path, &["describe", "-m", "source"]);

std::fs::write(&edit_script, "dump-path path").unwrap();
test_env.jj_cmd_ok(&repo_path, &["squash"]);

let edited_path = std::fs::read_to_string(test_env.env_root().join("path")).unwrap();
let edited_path = Path::new(&edited_path);
// While `assert!(!edited_path.starts_with("//?/"))` could work here in most
// cases, it fails when it is not safe to strip the prefix, such as paths
// over 260 chars.
assert_eq!(edited_path, dunce::simplified(Path::new(&edited_path)));
}

#[test]
fn test_squash_empty() {
let mut test_env = TestEnvironment::default();
Expand Down
29 changes: 29 additions & 0 deletions cli/tests/test_unsquash_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,35 @@ fn test_unsquash_description() {
"###);
}

#[test]
#[cfg(windows)]
fn test_unsquash_description_editor_avoids_unc() {
use std::path::Path;

let mut test_env = TestEnvironment::default();
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
let repo_path = test_env.env_root().join("repo");

let edit_script = test_env.set_up_fake_editor();
std::fs::write(repo_path.join("file1"), "a\n").unwrap();
std::fs::write(repo_path.join("file2"), "a\n").unwrap();
test_env.jj_cmd_ok(&repo_path, &["new"]);
std::fs::write(repo_path.join("file1"), "b\n").unwrap();
std::fs::write(repo_path.join("file2"), "b\n").unwrap();
test_env.jj_cmd_ok(&repo_path, &["describe", "@-", "-m", "destination"]);
test_env.jj_cmd_ok(&repo_path, &["describe", "-m", "source"]);

std::fs::write(&edit_script, "dump-path path").unwrap();
test_env.jj_cmd_ok(&repo_path, &["unsquash"]);

let edited_path = std::fs::read_to_string(test_env.env_root().join("path")).unwrap();
let edited_path = Path::new(&edited_path);
// While `assert!(!edited_path.starts_with("//?/"))` could work here in most
// cases, it fails when it is not safe to strip the prefix, such as paths
// over 260 chars.
assert_eq!(edited_path, dunce::simplified(Path::new(&edited_path)));
}

fn get_description(test_env: &TestEnvironment, repo_path: &Path, rev: &str) -> String {
test_env.jj_cmd_success(
repo_path,
Expand Down

0 comments on commit 1543cba

Please sign in to comment.