Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support jujutsu (jj) VCS #1070

Open
dbarnett opened this issue Aug 28, 2024 · 13 comments
Open

Support jujutsu (jj) VCS #1070

dbarnett opened this issue Aug 28, 2024 · 13 comments

Comments

@dbarnett
Copy link

Would it be possible to support https://github.com/martinvonz/jj so that if I clone a repo of a python project using that, I'm still able to build its python package contents normally?

At least in the case of their git backend that could be as simple as detecting if the repo dir contains a .jj/repo/store/git/ and running the existing git detection against that $GIT_DIR (example: https://martinvonz.github.io/jj/latest/github/#using-github-cli).

@RonnyPfannschmidt
Copy link
Contributor

That needs some research, at first glance its probably possible

But there's a need to verify all plumbing command's are available and we need automated tests for it

It's not something I can currently send time on

@RonnyPfannschmidt
Copy link
Contributor

A colocated repo may be the easiest start

Anything more needs research

@dbarnett
Copy link
Author

Yeah, actually colocated repos already work (they're just a normal git repo with an extra .jj/ subdir). The others should be as trivial as adding an alternate gitdir path to check.

@RonnyPfannschmidt
Copy link
Contributor

as far as im aware, jj will know the correct metadata, so id strongly prefer using jj commands over pretending a jj repo is a drunk git repo

@dbarnett
Copy link
Author

Fair 😄

I'm involved with the jj project, so LMK if I can help here too with the research / coding.

@RonnyPfannschmidt
Copy link
Contributor

the key part is whether there are commands to give us some extra details on the worktree

  • last tag
  • distance in commits
  • commit date fo the current commit
  • dirty/clean state of the worktree (as far as i confusedly guessed jj always pushes things into the "index" and a "hidden commit")

a backend should be fairly straightforward, but a key part wil lbe testign how we get what version when in the testsuite

@RonnyPfannschmidt
Copy link
Contributor

so if jj had a way to get the metadata for "infer development version from scm metadata" in a easy way, it might be as simple as a single command

@dbarnett
Copy link
Author

Some relevant jj commands for reference...

  • Get most recent tag that's an ancestor of the working copy commit:
    jj log --no-graph -r 'latest(ancestors(@) & tags())' -T tags
  • Get commit ID for current working copy vs. latest tagged:
    jj log --no-graph -r @ -T commit_id; jj log --no-graph -r 'latest(ancestors(@) & tags())' -T commit_id

One gotcha: the @ part should probably be something like git_head(), but ideally not git-specific... I'll do some more digging on that part...

@RonnyPfannschmidt
Copy link
Contributor

lovely starting point

@dbarnett
Copy link
Author

K, this one-liner should spit out one or two lines of input to determine the necessary tag/commit metadata:

$ jj log --no-graph \
    -r 'latest(::@ ~ (empty() ~ tags()))' \
    -r 'latest(::@ & tags())' \
    --template 'tags++" "++change_id++"\n"'
 rqpqstnkkssmnpxtrotnoomxnrvnuvwo
v0.14.0 vktsrykqlynwupyvuupoxqsqnqswzkqo

If there's no tagged ancestor it'll be missing the 2nd line of output (triggering the fallback_version or error case):

 rqpqstnkkssmnpxtrotnoomxnrvnuvwo

If the "current commit" IS the last tagged commit it'll resolve both revisions as the same and spit out a single line with a tagged commit (meaning it's a clean tagged version and doesn't need a hash suffix):

v0.14.0 vktsrykqlynwupyvuupoxqsqnqswzkqo

Details on the revset mini-language at https://martinvonz.github.io/jj/latest/revsets/. For a quick explanation of the mechanics here, the latest(::@ ~ (empty() ~ tags())) means "last commit that's part of the current working copy that's not empty OR is tagged". The latest(::@ & tags()) means "last commit that's part of the current working copy that's tagged".

Filtering out empty commits is important because jj paradigms usually have an empty commit on top of the "real" commit (akin to git's staging area).

@RonnyPfannschmidt
Copy link
Contributor

so how to add the distanceto the listing

we need current commit id, last reachable tag, distance in commits to the tag to match what we do with the others

@dbarnett
Copy link
Author

dbarnett commented Aug 29, 2024

One way would be to run 2 separate commands, one to figure out the tag and another to find all newer commits:

  1. jj log -r 'latest(heads(::@ & tags()))' --no-graph -T 'tags++" "++change_id++"\n"' -> v0.14.0 vktsrykqlynwupyvuupoxqsqnqswzkqo
  2. jj log -r 'v0.14.0::@ ~ empty()' --no-graph -T 'change_id++"\n"' -> (D lines of commit IDs for distance D>=0)

That might act funny when there are branched/merged commits, depending on what you mean by "distance", but in the case of multiple commit paths from tag to head I'm not sure there's a simple way to flatten to "longest distance" or "shortest distance" using the revset language, without separate processing.

@dbarnett
Copy link
Author

dbarnett commented Sep 2, 2024

That might act funny when there are branched/merged commits, depending on what you mean by "distance"...

Nice, I verified those commands seem correct and it gets the same count git describe does in the case of merge commits (just the total unioned count of all commits between between TAG and HEAD).

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

No branches or pull requests

2 participants