ok/jj
1
0
Fork 0
forked from mirrors/jj

working_copy: fix crash when updating and only executable bit changed

This commit is contained in:
Martin von Zweigbergk 2022-04-14 23:03:08 -07:00 committed by Martin von Zweigbergk
parent bd035004b9
commit 53911b076b
3 changed files with 29 additions and 15 deletions

View file

@ -44,6 +44,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Errors are now printed to stderr (they used to be printed to stdout).
* Updating the working copy to a commit where a file's executable bit changed
but the contents was the same used to lead to a crash. That has now been
fixed.
* `jj untrack` now requires at least one path (allowing no arguments was a UX
bug).

View file

@ -592,10 +592,7 @@ impl TreeState {
self.file_states.insert(path.clone(), file_state);
stats.added_files += 1;
}
Diff::Modified(before, after) => {
fs::remove_file(&disk_path).ok();
let file_state = match (before, after) {
(
Diff::Modified(
TreeValue::Normal {
id: old_id,
executable: old_executable,
@ -605,10 +602,13 @@ impl TreeState {
// Optimization for when only the executable bit changed
assert_ne!(executable, old_executable);
self.set_executable(&disk_path, executable);
let mut file_state = self.file_states.get(&path).unwrap().clone();
let file_state = self.file_states.get_mut(&path).unwrap();
file_state.mark_executable(executable);
file_state
stats.updated_files += 1;
}
Diff::Modified(before, after) => {
fs::remove_file(&disk_path).ok();
let file_state = match (before, after) {
(_, TreeValue::Normal { id, executable }) => {
self.write_file(&disk_path, &path, &id, executable)
}

View file

@ -66,6 +66,8 @@ fn test_checkout_file_transitions(use_git: bool) {
Missing,
Normal,
Executable,
// Executable, but same content as Normal, to test transition where only the bit changed
ExecutableNormalContent,
Conflict,
#[cfg_attr(windows, allow(dead_code))]
Symlink,
@ -99,6 +101,13 @@ fn test_checkout_file_transitions(use_git: bool) {
executable: true,
}
}
Kind::ExecutableNormalContent => {
let id = testutils::write_file(store, path, "normal file contents");
TreeValue::Normal {
id,
executable: true,
}
}
Kind::Conflict => {
let base_file_id = testutils::write_file(store, path, "base file contents");
let left_file_id = testutils::write_file(store, path, "left file contents");
@ -162,6 +171,7 @@ fn test_checkout_file_transitions(use_git: bool) {
Kind::Missing,
Kind::Normal,
Kind::Executable,
Kind::ExecutableNormalContent,
Kind::Conflict,
Kind::Tree,
];
@ -217,7 +227,7 @@ fn test_checkout_file_transitions(use_git: bool) {
path
);
}
Kind::Executable => {
Kind::Executable | Kind::ExecutableNormalContent => {
assert!(maybe_metadata.is_ok(), "{:?} should exist", path);
let metadata = maybe_metadata.unwrap();
assert!(metadata.is_file(), "{:?} should be a file", path);