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

repo: propagate error when current working-copy commit is not found

This should fix the panic in the case reported in #1107. It's a bit
hard to reproduce because we normally notice the missing commit when
we snapshot the working copy, but it's possible to reproduce it using
`--no-commit-working-copy`.

I suspect the added test is too brittle because it checks the exact
error message. On the other hand, it might be useful to have one test
case like this so we catch accidental changes in the format.
This commit is contained in:
Martin von Zweigbergk 2023-01-22 22:13:16 -08:00 committed by Martin von Zweigbergk
parent 63aa484046
commit ce094c618b
2 changed files with 49 additions and 2 deletions

View file

@ -767,7 +767,10 @@ impl MutableRepo {
.view
.with_ref(|v| v.get_wc_commit_id(&workspace_id).cloned());
if let Some(wc_commit_id) = maybe_wc_commit_id {
let wc_commit = self.store().get_commit(&wc_commit_id).unwrap();
let wc_commit = self
.store()
.get_commit(&wc_commit_id)
.map_err(EditCommitError::WorkingCopyCommitNotFound)?;
if wc_commit.is_empty()
&& wc_commit.description().is_empty()
&& self.view().heads().contains(wc_commit.id())
@ -1108,6 +1111,8 @@ pub struct RewriteRootCommit;
/// Error from attempts to edit a commit
#[derive(Debug, Error)]
pub enum EditCommitError {
#[error("Current working-copy commit not found: {0}")]
WorkingCopyCommitNotFound(BackendError),
#[error("Cannot rewrite the root commit")]
RewriteRootCommit,
}

View file

@ -14,7 +14,7 @@
use std::path::Path;
use crate::common::TestEnvironment;
use crate::common::{get_stderr_string, TestEnvironment};
pub mod common;
@ -62,6 +62,48 @@ fn test_edit() {
"###);
}
#[test]
// Windows says "Access is denied" when trying to delete the object file.
#[cfg(unix)]
fn test_edit_current_wc_commit_missing() {
// Test that we get a reasonable error message when the current working-copy
// commit is missing
let test_env = TestEnvironment::default();
test_env.jj_cmd_success(test_env.env_root(), &["init", "repo", "--git"]);
let repo_path = test_env.env_root().join("repo");
test_env.jj_cmd_success(&repo_path, &["commit", "-m", "first"]);
test_env.jj_cmd_success(&repo_path, &["describe", "-m", "second"]);
test_env.jj_cmd_success(&repo_path, &["edit", "@-"]);
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
o 5c52832c3483 second
@ 69542c1984c1 first
o 000000000000 (no description set)
"###);
// Make the Git backend fail to read the current working copy commit
let commit_object_path = repo_path
.join(".jj")
.join("repo")
.join("store")
.join("git")
.join("objects")
.join("69")
.join("542c1984c1f9d91f7c6c9c9e6941782c944bd9");
std::fs::remove_file(commit_object_path).unwrap();
// Pass --no-commit-working-copy to avoid triggering the error at snapshot time
let assert = test_env
.jj_cmd(
&repo_path,
&["edit", "--no-commit-working-copy", "5c52832c3483"],
)
.assert()
.code(255);
insta::assert_snapshot!(get_stderr_string(&assert), @r###"
Internal error: Failed to edit a commit: Current working-copy commit not found: Object 69542c1984c1f9d91f7c6c9c9e6941782c944bd9 of type commit not found: object not found - no match for id (69542c1984c1f9d91f7c6c9c9e6941782c944bd9); class=Odb (9); code=NotFound (-3)
"###);
}
fn read_file(path: &Path) -> String {
String::from_utf8(std::fs::read(path).unwrap()).unwrap()
}