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"]);
|
||||
}
|
||||
|
||||
#[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]
|
||||
fn rad_jj_colocated_patch() {
|
||||
// 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(())
|
||||
}
|
||||
|
||||
#[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
|
||||
///
|
||||
/// 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
|
||||
/// want to modify the wrong repository in the case that it found a
|
||||
/// Git repository that is not a Radicle repository.
|
||||
pub fn cwd() -> Result<(git2::Repository, RepoId), RemoteError> {
|
||||
let repo = repo()?;
|
||||
let (_, id) = remote(&repo)?;
|
||||
pub fn cwd() -> Result<(git2::Repository, RepoId), CwdError> {
|
||||
let repo =
|
||||
repo().or_else(|git| repo_jj_git_root().map_err(|jj| CwdError::Detection { git, jj }))?;
|
||||
|
||||
let (_, id) = remote(&repo)?;
|
||||
Ok((repo, id))
|
||||
}
|
||||
|
||||
|
|
@ -411,6 +424,34 @@ pub fn repo() -> Result<git2::Repository, git2::Error> {
|
|||
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.
|
||||
pub fn setup_patch_upstream<'a>(
|
||||
patch: &ObjectId,
|
||||
|
|
|
|||
Loading…
Reference in New Issue