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

cli: on init, give a proper error message instead crashing when repo exists

This commit is contained in:
Martin von Zweigbergk 2021-05-19 14:30:50 -07:00
parent f0cec5ddc8
commit 1fe8f6ac27
5 changed files with 52 additions and 27 deletions

View file

@ -131,6 +131,12 @@ impl Debug for ReadonlyRepo {
}
}
#[derive(Error, Debug, PartialEq)]
pub enum RepoInitError {
#[error("The destination repo ({0}) already exists")]
DestinationExists(PathBuf),
}
#[derive(Error, Debug, PartialEq)]
pub enum RepoLoadError {
#[error("There is no Jujutsu repo in {0}")]
@ -138,19 +144,23 @@ pub enum RepoLoadError {
}
impl ReadonlyRepo {
pub fn init_local(settings: &UserSettings, wc_path: PathBuf) -> Arc<ReadonlyRepo> {
let repo_path = wc_path.join(".jj");
fs::create_dir(repo_path.clone()).unwrap();
pub fn init_local(
settings: &UserSettings,
wc_path: PathBuf,
) -> Result<Arc<ReadonlyRepo>, RepoInitError> {
let repo_path = ReadonlyRepo::init_repo_dir(&wc_path)?;
let store_path = repo_path.join("store");
fs::create_dir(&store_path).unwrap();
let store = Box::new(LocalStore::init(store_path));
ReadonlyRepo::init(settings, repo_path, wc_path, store)
Ok(ReadonlyRepo::init(settings, repo_path, wc_path, store))
}
/// Initializes a repo with a new Git store in .jj/git/ (bare Git repo)
pub fn init_internal_git(settings: &UserSettings, wc_path: PathBuf) -> Arc<ReadonlyRepo> {
let repo_path = wc_path.join(".jj");
fs::create_dir(repo_path.clone()).unwrap();
pub fn init_internal_git(
settings: &UserSettings,
wc_path: PathBuf,
) -> Result<Arc<ReadonlyRepo>, RepoInitError> {
let repo_path = ReadonlyRepo::init_repo_dir(&wc_path)?;
let git_store_path = repo_path.join("git");
git2::Repository::init_bare(&git_store_path).unwrap();
let store_path = repo_path.join("store");
@ -158,7 +168,7 @@ impl ReadonlyRepo {
let mut store_file = File::create(store_path).unwrap();
store_file.write_all(b"git: git").unwrap();
let store = Box::new(GitStore::load(&git_store_path));
ReadonlyRepo::init(settings, repo_path, wc_path, store)
Ok(ReadonlyRepo::init(settings, repo_path, wc_path, store))
}
/// Initializes a repo with an existing Git store at the specified path
@ -166,9 +176,8 @@ impl ReadonlyRepo {
settings: &UserSettings,
wc_path: PathBuf,
git_store_path: PathBuf,
) -> Arc<ReadonlyRepo> {
let repo_path = wc_path.join(".jj");
fs::create_dir(repo_path.clone()).unwrap();
) -> Result<Arc<ReadonlyRepo>, RepoInitError> {
let repo_path = ReadonlyRepo::init_repo_dir(&wc_path)?;
let store_path = repo_path.join("store");
let git_store_path = fs::canonicalize(git_store_path).unwrap();
let mut store_file = File::create(store_path).unwrap();
@ -176,7 +185,17 @@ impl ReadonlyRepo {
.write_all(format!("git: {}", git_store_path.to_str().unwrap()).as_bytes())
.unwrap();
let store = Box::new(GitStore::load(&git_store_path));
ReadonlyRepo::init(settings, repo_path, wc_path, store)
Ok(ReadonlyRepo::init(settings, repo_path, wc_path, store))
}
fn init_repo_dir(wc_path: &Path) -> Result<PathBuf, RepoInitError> {
let repo_path = wc_path.join(".jj");
if repo_path.exists() {
Err(RepoInitError::DestinationExists(repo_path))
} else {
fs::create_dir(&repo_path).unwrap();
Ok(repo_path)
}
}
fn init(

View file

@ -53,9 +53,9 @@ pub fn init_repo(settings: &UserSettings, use_git: bool) -> (TempDir, Arc<Readon
let repo = if use_git {
let git_path = temp_dir.path().join("git-repo");
git2::Repository::init(&git_path).unwrap();
ReadonlyRepo::init_external_git(&settings, wc_path, git_path)
ReadonlyRepo::init_external_git(&settings, wc_path, git_path).unwrap()
} else {
ReadonlyRepo::init_local(&settings, wc_path)
ReadonlyRepo::init_local(&settings, wc_path).unwrap()
};
(temp_dir, repo)

View file

@ -277,7 +277,7 @@ fn test_import_refs_empty_git_repo() {
let git_repo = git2::Repository::init_bare(&git_repo_dir).unwrap();
std::fs::create_dir(&jj_repo_dir).unwrap();
let repo = ReadonlyRepo::init_external_git(&settings, jj_repo_dir, git_repo_dir);
let repo = ReadonlyRepo::init_external_git(&settings, jj_repo_dir, git_repo_dir).unwrap();
let heads_before = repo.view().heads().clone();
let mut tx = repo.start_transaction("test");
let mut_repo = tx.mut_repo();
@ -297,7 +297,7 @@ fn test_init() {
let initial_git_commit = empty_git_commit(&git_repo, "refs/heads/main", &[]);
let initial_commit_id = commit_id(&initial_git_commit);
std::fs::create_dir(&jj_repo_dir).unwrap();
let repo = ReadonlyRepo::init_external_git(&settings, jj_repo_dir, git_repo_dir);
let repo = ReadonlyRepo::init_external_git(&settings, jj_repo_dir, git_repo_dir).unwrap();
// The refs were *not* imported -- it's the caller's responsibility to import
// any refs they care about.
assert!(!repo.view().heads().contains(&initial_commit_id));
@ -315,7 +315,7 @@ fn test_fetch_success() {
let clone_git_repo =
git2::Repository::clone(&source_repo_dir.to_str().unwrap(), &clone_repo_dir).unwrap();
std::fs::create_dir(&jj_repo_dir).unwrap();
ReadonlyRepo::init_external_git(&settings, jj_repo_dir.clone(), clone_repo_dir);
ReadonlyRepo::init_external_git(&settings, jj_repo_dir.clone(), clone_repo_dir).unwrap();
let new_git_commit =
empty_git_commit(&source_git_repo, "refs/heads/main", &[&initial_git_commit]);
@ -341,7 +341,7 @@ fn test_fetch_no_such_remote() {
let jj_repo_dir = temp_dir.path().join("jj");
let git_repo = git2::Repository::init_bare(&source_repo_dir).unwrap();
std::fs::create_dir(&jj_repo_dir).unwrap();
let jj_repo = ReadonlyRepo::init_external_git(&settings, jj_repo_dir, source_repo_dir);
let jj_repo = ReadonlyRepo::init_external_git(&settings, jj_repo_dir, source_repo_dir).unwrap();
let mut tx = jj_repo.start_transaction("test");
let result = git::fetch(tx.mut_repo(), &git_repo, "invalid-remote");
@ -365,7 +365,7 @@ fn set_up_push_repos(settings: &UserSettings, temp_dir: &TempDir) -> PushTestSet
let initial_commit_id = commit_id(&initial_git_commit);
git2::Repository::clone(&source_repo_dir.to_str().unwrap(), &clone_repo_dir).unwrap();
std::fs::create_dir(&jj_repo_dir).unwrap();
let jj_repo = ReadonlyRepo::init_external_git(&settings, jj_repo_dir, clone_repo_dir);
let jj_repo = ReadonlyRepo::init_external_git(&settings, jj_repo_dir, clone_repo_dir).unwrap();
let new_commit = testutils::create_random_commit(&settings, &jj_repo)
.set_parents(vec![initial_commit_id])
.write_to_new_transaction(&jj_repo, "test");

View file

@ -22,7 +22,7 @@ fn test_init_local() {
let settings = testutils::user_settings();
let temp_dir = tempfile::tempdir().unwrap();
let wc_path = temp_dir.path().to_owned();
let repo = ReadonlyRepo::init_local(&settings, wc_path.clone());
let repo = ReadonlyRepo::init_local(&settings, wc_path.clone()).unwrap();
assert!(repo.store().git_repo().is_none());
assert_eq!(repo.working_copy_path(), &wc_path);
assert_eq!(repo.repo_path(), &wc_path.join(".jj"));
@ -38,7 +38,7 @@ fn test_init_internal_git() {
let settings = testutils::user_settings();
let temp_dir = tempfile::tempdir().unwrap();
let wc_path = temp_dir.path().to_owned();
let repo = ReadonlyRepo::init_internal_git(&settings, wc_path.clone());
let repo = ReadonlyRepo::init_internal_git(&settings, wc_path.clone()).unwrap();
assert!(repo.store().git_repo().is_some());
assert_eq!(repo.working_copy_path(), &wc_path);
assert_eq!(repo.repo_path(), &wc_path.join(".jj"));
@ -57,7 +57,7 @@ fn test_init_external_git() {
git2::Repository::init(&git_repo_path).unwrap();
let wc_path = temp_dir.path().join("jj");
std::fs::create_dir(&wc_path).unwrap();
let repo = ReadonlyRepo::init_external_git(&settings, wc_path.clone(), git_repo_path);
let repo = ReadonlyRepo::init_external_git(&settings, wc_path.clone(), git_repo_path).unwrap();
assert!(repo.store().git_repo().is_some());
assert_eq!(repo.working_copy_path(), &wc_path);
assert_eq!(repo.repo_path(), &wc_path.join(".jj"));

View file

@ -40,7 +40,7 @@ use jujutsu_lib::git::GitFetchError;
use jujutsu_lib::index::HexPrefix;
use jujutsu_lib::op_store::{OpStore, OpStoreError, OperationId};
use jujutsu_lib::operation::Operation;
use jujutsu_lib::repo::{MutableRepo, ReadonlyRepo, RepoLoadError, RepoLoader};
use jujutsu_lib::repo::{MutableRepo, ReadonlyRepo, RepoInitError, RepoLoadError, RepoLoader};
use jujutsu_lib::repo_path::RepoPath;
use jujutsu_lib::revset::{RevsetError, RevsetParseError};
use jujutsu_lib::revset_graph_iterator::RevsetGraphEdgeType;
@ -87,6 +87,12 @@ impl From<StoreError> for CommandError {
}
}
impl From<RepoInitError> for CommandError {
fn from(_: RepoInitError) -> Self {
CommandError::UserError("The target repo already exists".to_string())
}
}
impl From<DiffEditError> for CommandError {
fn from(err: DiffEditError) -> Self {
CommandError::UserError(format!("Failed to edit diff: {}", err))
@ -785,7 +791,7 @@ fn cmd_init(
let repo = if let Some(git_store_str) = sub_matches.value_of("git-store") {
let git_store_path = ui.cwd().join(git_store_str);
let repo = ReadonlyRepo::init_external_git(ui.settings(), wc_path, git_store_path);
let repo = ReadonlyRepo::init_external_git(ui.settings(), wc_path, git_store_path)?;
let git_repo = repo.store().git_repo().unwrap();
let mut tx = repo.start_transaction("import git refs");
git::import_refs(tx.mut_repo(), &git_repo).unwrap();
@ -793,9 +799,9 @@ fn cmd_init(
// number.
tx.commit()
} else if sub_matches.is_present("git") {
ReadonlyRepo::init_internal_git(ui.settings(), wc_path)
ReadonlyRepo::init_internal_git(ui.settings(), wc_path)?
} else {
ReadonlyRepo::init_local(ui.settings(), wc_path)
ReadonlyRepo::init_local(ui.settings(), wc_path)?
};
writeln!(
ui,
@ -2293,7 +2299,7 @@ fn cmd_git_clone(
fs::create_dir(&wc_path).unwrap();
}
let repo = ReadonlyRepo::init_internal_git(ui.settings(), wc_path);
let repo = ReadonlyRepo::init_internal_git(ui.settings(), wc_path)?;
let git_repo = get_git_repo(repo.store())?;
writeln!(
ui,