Skip to content

Support non-colocated Jujutsu repositories - #1847

Open
lainon1 wants to merge 3 commits into
o2sh:mainfrom
lainon1:fix/1846-jujutsu-support
Open

Support non-colocated Jujutsu repositories#1847
lainon1 wants to merge 3 commits into
o2sh:mainfrom
lainon1:fix/1846-jujutsu-support

Conversation

@lainon1

@lainon1 lainon1 commented Aug 24, 2026

Copy link
Copy Markdown

Closes #1846.

Native Jujutsu repositories keep their Git store inside .jj, so normal Git discovery cannot find them.

This change:

  • detects non-colocated JJ workspaces;
  • uses jj git root to locate the backing Git store;
  • obtains the current JJ working-copy commit;
  • reuses the existing Git history and statistics implementation;
  • uses the JJ workspace root for language, manifest, and license detection;
  • avoids snapshotting or modifying the JJ working copy.

The transient JJ working-copy commit is displayed as HEAD but excluded from commit statistics. Its ancestors, including multiple merge parents, are still traversed.

Pending and Size are omitted because the hidden backing repository has no Git worktree or index.

Testing:

  • cargo test -p onefetch — 133 passed
  • crate-level Clippy — clean
  • manually tested with jj git clone --no-colocate

@spenserblack spenserblack left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks very good, thanks! Just have some nitpicks and comments.

Comment thread src/info/mod.rs
fn pending(mut self, repo: &Repository) -> Result<Self> {
if !self.disabled_fields.contains(&InfoType::Pending) {
fn pending(mut self, repo: &Repository, is_jujutsu: bool) -> Result<Self> {
if !is_jujutsu && !self.disabled_fields.contains(&InfoType::Pending) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's pretty obvious, but, just to be clear: we're going to skip the pending changes info for Jujutsu, and this is because Jujutsu's concept of "pending changes" is different from Git's, right? IIRC Jujutsu always tracks changes?

If so, maybe add a comment explaining why we're skipping the pending field for Jujutsu.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Jujutsu snapshots working-copy changes into the @ commit, while the existing pending field reads Git index/worktree status. A native Jujutsu repository has a bare backing Git store, so that calculation is not meaningful. I added a comment explaining why the field is skipped in 8751184.

Comment thread src/info/mod.rs
number_separator: NumberSeparator,
is_jujutsu: bool,
) -> Self {
if !is_jujutsu && !self.disabled_fields.contains(&InfoType::Size) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 I'm a bit concerned that some Jujutsu users might be confused if they don't get the size field. I wonder if it would be enough to just simply eprintln!("Jujutsu support is experimental: some fields are not yet supported") or something like that.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I added a stderr notice in 8751184 stating that Jujutsu support is experimental and that pending changes and size are not yet supported. Keeping it on stderr leaves normal and serialized stdout intact.

Comment thread src/info/repository.rs Outdated
Comment on lines +59 to +66
match self.jujutsu_head {
Some(head_id) => Ok(head_id),
None => Ok(self
.git
.head_id()
.context("Failed to retrieve HEAD ID")?
.detach()),
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stylistic nitpick: instead of using match to convert an Option to a Result, I think we can use some of the Option methods like ok_or_else.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. I simplified this with Option::map_or_else in 8751184.

Comment thread src/info/repository.rs Outdated
Comment on lines +85 to +87
input
.parent()
.context("The repository path has no parent directory")?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we allow inputs to be file paths? Should we just always fail here, instead, as the user has failed to provide a path to a directory?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. INPUT is documented as a directory path, so accepting files only through Jujutsu discovery would be inconsistent. find_jujutsu_root now rejects file inputs with a clear error, and the behavior is covered by the unit test in 8751184.

@spenserblack spenserblack left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@lainon1

lainon1 commented Aug 31, 2026

Copy link
Copy Markdown
Author

@o2sh

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Jujutsu Support

2 participants