Skip to content

FR: Using jj as library in third party projects #3034

Description

@poliorcetics

Is your feature request related to a problem? Please describe.

I would like to implement the DiffProvider trait in helix for Jujutsu, like it is for Git

Describe the solution you'd like

Overall I would like to be able to use jj-lib to

  • Easily open a repo (readable OR mutable, that can be two differents types or a config, it's not important) when given a path anywhere inside that repo
  • Easily access convenience methods on repos like
    • files at a particular revision (allows computing the diff on our side in helix using imara-diff
    • commit message at a given revision
    • current commit id
    • current commit branch (if any)
    • navigate the tree with things like repo.view_at_commit(...).parents() or .children() or equivalents in some way

I'm sure there are dozens of other "common" things that will be asked over time so it could be done in a new library on top of jj-lib that is intended for use by third parties without interfering with the core algorithms and data structures in jj-lib. Lots of helpers only available in jj-cli could be moved in that hypothetical lib for example.

Describe alternatives you've considered

  1. I've tried to do it and just opening a workspace (not even a repo) is very hard:
        // No method for auto discovery of the .jj, must be done by each consumer
        let ws_loader = WorkspaceLoader::init(workspace_dir).unwrap();

        // Defaults and empty things everywhere because how do I fill those things ? They're only instantiated in jj-cli, using private elements
        let ws = ws_loader.load(
            &UserSettings::from_config(Default::default()),
            &StoreFactories::empty(),
            &Default::default(),
        ).unwrap();

        // it just gets worse
  1. Documentation doesn't exist much but honestly that wasn't such a bother, rustdoc makes it easy to navigate code and the types are named mostly logically so it would make things easier but I'm not gonna blame Jujutsu for not having very expansive docs in a 0.x version :)

  2. I tried to look into using jj-cli to use all the helpers and things available there but it wasn't much better: the entry point of CliRunner::init() only accepts moving forward through .run(), returning an ExitCode, which makes it hard to do anything with it. I could use a channel for example, but for a diff in a single code file (so often very very small), that's overkill both in code and ergonomics.

  3. I could invoke jj as a subprogram, overriding the config to define some custom diff handler and go from there, but again, that's way more layers of abstractions and possible failures that needed. It would also mean helix needs to invoke jj as binary, trusting it's not malicious and actually jj and not some third party command that happens to have the same name but doesn't at all does the correct thing.
    It would also be sad because both jj and `helix are developed in Rust, so it's not like I'm trying to interface two incompatibles languages here 😅

Additional context


If you have any questions or channels on which rapid discussions is possible I can join them to help with that, if you have guidance to give I can try and help implement/document all that 😄

Metadata

Metadata

Assignees

No one assigned

    Labels

    libificationEverything concerning jj-lib API's for thirdparty developers

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions