forked from mirrors/jj
cli: on init, give a proper error message instead crashing when repo exists
This commit is contained in:
parent
f0cec5ddc8
commit
1fe8f6ac27
5 changed files with 52 additions and 27 deletions
|
@ -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(
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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"));
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue