radicle: Detect current repository using `jj`
When using Jujutsu and a non-colocated Git repository, the detection using `git2` directly fails (just as `git` in a shell would fail) because there is no `.git` directory found by traversing up the filesystem hierarchy. Add an invocation of `jj git root` as a fallback.
This commit is contained in:
parent
abc963f2f2
commit
9e1d6b1feb
|
|
@ -0,0 +1,19 @@
|
||||||
|
We initialize Jujutusu for our repository for use with a bare Git repo.
|
||||||
|
|
||||||
|
```(stderr)
|
||||||
|
$ jj git init --git-repo heartwood heartwood.jj
|
||||||
|
Done importing changes from the underlying Git repo.
|
||||||
|
Working copy (@) now at: lvxkkpmk 9ec513df (empty) (no description set)
|
||||||
|
Parent commit (@-) : xpnzuzwn f2de534b master | Second commit
|
||||||
|
Added 1 files, modified 0 files, removed 0 files
|
||||||
|
Initialized repo in "heartwood.jj"
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
$ cd heartwood.jj
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
$ rad .
|
||||||
|
rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
|
||||||
|
```
|
||||||
|
|
@ -858,6 +858,37 @@ fn rad_patch() {
|
||||||
Environment::alice(["rad-init", "rad-patch"]);
|
Environment::alice(["rad-init", "rad-patch"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rad_jj_bare() {
|
||||||
|
// We test whether `jj` is installed, and have this test succeed if it is not.
|
||||||
|
// Programmatic skipping of tests is not supported as of 2024-08.
|
||||||
|
if !program_reports_version("jj") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut environment = Environment::new();
|
||||||
|
let mut profile = environment.node("alice");
|
||||||
|
let rid = profile.project("heartwood", "Radicle Heartwood Protocol & Stack");
|
||||||
|
|
||||||
|
test(
|
||||||
|
"examples/rad-init-existing-bare.md",
|
||||||
|
environment.work(&profile),
|
||||||
|
Some(&profile.home),
|
||||||
|
[(
|
||||||
|
"URL",
|
||||||
|
git::url::File::new(profile.storage.path())
|
||||||
|
.rid(rid)
|
||||||
|
.to_string()
|
||||||
|
.as_str(),
|
||||||
|
)],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
environment
|
||||||
|
.tests(["jj-config", "jj-init-bare"], &profile)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rad_jj_colocated_patch() {
|
fn rad_jj_colocated_patch() {
|
||||||
// We test whether `jj` is installed, and have this test succeed if it is not.
|
// We test whether `jj` is installed, and have this test succeed if it is not.
|
||||||
|
|
|
||||||
|
|
@ -372,6 +372,18 @@ pub fn remove_remote(repo: &git2::Repository) -> Result<(), RemoteError> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
pub enum CwdError {
|
||||||
|
#[error(transparent)]
|
||||||
|
Remote(#[from] RemoteError),
|
||||||
|
|
||||||
|
#[error("Detection failed (git: '{git}', jj: '{jj}')")]
|
||||||
|
Detection {
|
||||||
|
git: git2::Error,
|
||||||
|
jj: JujutsuGitRootError,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the RID of the repository in current working directory
|
/// Get the RID of the repository in current working directory
|
||||||
///
|
///
|
||||||
/// It will atempt to search parent directories if `path` did not find
|
/// It will atempt to search parent directories if `path` did not find
|
||||||
|
|
@ -382,10 +394,11 @@ pub fn remove_remote(repo: &git2::Repository) -> Result<(), RemoteError> {
|
||||||
/// This function should only perform read operations since we do not
|
/// This function should only perform read operations since we do not
|
||||||
/// want to modify the wrong repository in the case that it found a
|
/// want to modify the wrong repository in the case that it found a
|
||||||
/// Git repository that is not a Radicle repository.
|
/// Git repository that is not a Radicle repository.
|
||||||
pub fn cwd() -> Result<(git2::Repository, RepoId), RemoteError> {
|
pub fn cwd() -> Result<(git2::Repository, RepoId), CwdError> {
|
||||||
let repo = repo()?;
|
let repo =
|
||||||
let (_, id) = remote(&repo)?;
|
repo().or_else(|git| repo_jj_git_root().map_err(|jj| CwdError::Detection { git, jj }))?;
|
||||||
|
|
||||||
|
let (_, id) = remote(&repo)?;
|
||||||
Ok((repo, id))
|
Ok((repo, id))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -411,6 +424,34 @@ pub fn repo() -> Result<git2::Repository, git2::Error> {
|
||||||
Ok(repo)
|
Ok(repo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
pub enum JujutsuGitRootError {
|
||||||
|
#[error("git: {0}")]
|
||||||
|
Git(#[from] git2::Error),
|
||||||
|
|
||||||
|
#[error("i/o: {0}")]
|
||||||
|
Io(#[from] io::Error),
|
||||||
|
|
||||||
|
#[error("exited with status {status}")]
|
||||||
|
CommandFailure { status: std::process::ExitStatus },
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the Git repo underlying the current Jujutsu repository.
|
||||||
|
pub fn repo_jj_git_root() -> Result<git2::Repository, JujutsuGitRootError> {
|
||||||
|
let output = std::process::Command::new("jj")
|
||||||
|
.args(["git", "root"])
|
||||||
|
.output()?;
|
||||||
|
|
||||||
|
if !output.status.success() {
|
||||||
|
return Err(JujutsuGitRootError::CommandFailure {
|
||||||
|
status: output.status,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let path = std::path::PathBuf::from(String::from_utf8_lossy(&output.stdout).to_string().trim());
|
||||||
|
Ok(git2::Repository::open(path)?)
|
||||||
|
}
|
||||||
|
|
||||||
/// Setup patch upstream branch such that `git push` updates the patch.
|
/// Setup patch upstream branch such that `git push` updates the patch.
|
||||||
pub fn setup_patch_upstream<'a>(
|
pub fn setup_patch_upstream<'a>(
|
||||||
patch: &ObjectId,
|
patch: &ObjectId,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue