From f425864692614cb6385a9fd23fc23818c81b8151 Mon Sep 17 00:00:00 2001 From: Philip Metzger Date: Fri, 1 May 2026 16:54:33 +0200 Subject: [PATCH 1/5] crates: Add the `jj-core` crate This will be common base for building upon `jj` if you only want the internals which make the other systems work, like the `Backend` or `WorkingCopy` trait. It should be of utmost importance to make the crate as low dependency as possible so it'ss not in the critical path during compilation. Part of #6284 --- Cargo.lock | 4 ++++ Cargo.toml | 9 ++++++++- core/Cargo.toml | 17 +++++++++++++++++ core/src/lib.rs | 20 ++++++++++++++++++++ 4 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 core/Cargo.toml create mode 100644 core/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 1b4a6f10fc5..13e38360b94 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2635,6 +2635,10 @@ dependencies = [ "whoami", ] +[[package]] +name = "jj-core" +version = "0.44.0" + [[package]] name = "jj-lib" version = "0.44.0" diff --git a/Cargo.toml b/Cargo.toml index ad90a9fba29..bfeb2bc2124 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,14 @@ cargo-features = [] [workspace] resolver = "3" -members = ["cli", "lib", "lib/gen-protos", "lib/proc-macros", "lib/testutils"] +members = [ + "cli", + "core", + "lib", + "lib/gen-protos", + "lib/proc-macros", + "lib/testutils", +] [workspace.package] version = "0.44.0" diff --git a/core/Cargo.toml b/core/Cargo.toml new file mode 100644 index 00000000000..ff3a82422fe --- /dev/null +++ b/core/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "jj-core" +version.workspace = true +license.workspace = true +rust-version.workspace = true +edition.workspace = true +readme.workspace = true +homepage.workspace = true +repository.workspace = true +documentation.workspace = true +categories.workspace = true +keywords.workspace = true + +[dependencies] + +[lints] +workspace = true diff --git a/core/src/lib.rs b/core/src/lib.rs new file mode 100644 index 00000000000..02eb60d1a21 --- /dev/null +++ b/core/src/lib.rs @@ -0,0 +1,20 @@ +// Copyright 2026 The Jujutsu Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! The core library powering the Jujutsu Version Control System. It contains +//! all "base" types such as `Commit` and the `Backend` trait. + +#![warn(missing_docs)] +#![forbid(unsafe_code)] +#![deny(unused_must_use)] From 3baace65c9b43fde074e8b471a687eac70b0f1cf Mon Sep 17 00:00:00 2001 From: Martin von Zweigbergk Date: Thu, 6 Aug 2026 13:07:56 -0700 Subject: [PATCH 2/5] core: move `dag_walk` and `dag_walk_async` from `jj-lib` These modules are general-purpose algorithms with no dependencies on the rest of `jj-lib`, so they can move to the new low-dependency `jj-core` crate. `jj-lib` re-exports them, so its API is unchanged. Part of #6284 --- Cargo.lock | 10 ++++++++++ Cargo.toml | 1 + core/Cargo.toml | 9 +++++++++ {lib => core}/src/dag_walk.rs | 0 {lib => core}/src/dag_walk_async.rs | 0 core/src/lib.rs | 3 +++ lib/Cargo.toml | 1 + lib/src/lib.rs | 4 ++-- 8 files changed, 26 insertions(+), 2 deletions(-) rename {lib => core}/src/dag_walk.rs (100%) rename {lib => core}/src/dag_walk_async.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index 13e38360b94..1c16e3931fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2638,6 +2638,15 @@ dependencies = [ [[package]] name = "jj-core" version = "0.44.0" +dependencies = [ + "assert_matches", + "futures 0.3.33", + "indexmap", + "itertools 0.15.0", + "maplit", + "pollster", + "smallvec", +] [[package]] name = "jj-lib" @@ -2665,6 +2674,7 @@ dependencies = [ "insta", "interim", "itertools 0.15.0", + "jj-core", "jj-lib-proc-macros", "maplit", "memchr", diff --git a/Cargo.toml b/Cargo.toml index bfeb2bc2124..1641b3e79dc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -146,6 +146,7 @@ winreg = "0.56" # put all inter-workspace libraries, i.e. those that use 'path = ...' here in # their own (alphabetically sorted) block +jj-core = { path = "core", version = "0.44.0" } jj-lib = { path = "lib", version = "0.44.0", default-features = false } jj-lib-proc-macros = { path = "lib/proc-macros", version = "0.44.0" } testutils = { path = "lib/testutils" } diff --git a/core/Cargo.toml b/core/Cargo.toml index ff3a82422fe..5eeb360c02a 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -12,6 +12,15 @@ categories.workspace = true keywords.workspace = true [dependencies] +futures = { workspace = true } +indexmap = { workspace = true } +itertools = { workspace = true } +smallvec = { workspace = true } + +[dev-dependencies] +assert_matches = { workspace = true } +maplit = { workspace = true } +pollster = { workspace = true } [lints] workspace = true diff --git a/lib/src/dag_walk.rs b/core/src/dag_walk.rs similarity index 100% rename from lib/src/dag_walk.rs rename to core/src/dag_walk.rs diff --git a/lib/src/dag_walk_async.rs b/core/src/dag_walk_async.rs similarity index 100% rename from lib/src/dag_walk_async.rs rename to core/src/dag_walk_async.rs diff --git a/core/src/lib.rs b/core/src/lib.rs index 02eb60d1a21..44125be0ecd 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -18,3 +18,6 @@ #![warn(missing_docs)] #![forbid(unsafe_code)] #![deny(unused_must_use)] + +pub mod dag_walk; +pub mod dag_walk_async; diff --git a/lib/Cargo.toml b/lib/Cargo.toml index 152fc1700c5..457a4bb2c4c 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -47,6 +47,7 @@ hashbrown = { workspace = true } indexmap = { workspace = true } interim = { workspace = true } itertools = { workspace = true } +jj-core = { workspace = true } jj-lib-proc-macros = { workspace = true } maplit = { workspace = true } memchr = { workspace = true } diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 5ed1381c8f0..0f2f5dbc860 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -40,8 +40,8 @@ pub mod conflict_labels; pub mod conflicts; pub mod converge; pub mod copies; -pub mod dag_walk; -pub mod dag_walk_async; +pub use jj_core::dag_walk; +pub use jj_core::dag_walk_async; pub mod default_backend_factories; pub mod default_index; pub mod default_submodule_store; From a16db415aac48ff540ac261ef3de171bfe75e06a Mon Sep 17 00:00:00 2001 From: Martin von Zweigbergk Date: Thu, 6 Aug 2026 13:17:37 -0700 Subject: [PATCH 3/5] core: move `diff` module from `jj-lib` `jj-lib` re-exports it, so its API is unchanged. The `hashbrown` dependency moves along with it since `diff` was its only user in `jj-lib`. Part of #6284 --- Cargo.lock | 5 +++-- core/Cargo.toml | 7 +++++++ {lib => core}/benches/diff_bench.rs | 2 +- {lib => core}/src/diff.rs | 0 core/src/lib.rs | 1 + lib/Cargo.toml | 7 ------- lib/src/lib.rs | 2 +- 7 files changed, 13 insertions(+), 11 deletions(-) rename {lib => core}/benches/diff_bench.rs (99%) rename {lib => core}/src/diff.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index 1c16e3931fc..e43d289f6fa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2640,7 +2640,10 @@ name = "jj-core" version = "0.44.0" dependencies = [ "assert_matches", + "bstr", + "criterion", "futures 0.3.33", + "hashbrown 0.17.1", "indexmap", "itertools 0.15.0", "maplit", @@ -2658,7 +2661,6 @@ dependencies = [ "bstr", "chrono", "clru", - "criterion", "digest 0.10.7", "dunce", "either", @@ -2668,7 +2670,6 @@ dependencies = [ "gix", "gix-ignore", "globset", - "hashbrown 0.17.1", "indexmap", "indoc", "insta", diff --git a/core/Cargo.toml b/core/Cargo.toml index 5eeb360c02a..29fa2ace826 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -11,14 +11,21 @@ documentation.workspace = true categories.workspace = true keywords.workspace = true +[[bench]] +name = "diff_bench" +harness = false + [dependencies] +bstr = { workspace = true } futures = { workspace = true } +hashbrown = { workspace = true } indexmap = { workspace = true } itertools = { workspace = true } smallvec = { workspace = true } [dev-dependencies] assert_matches = { workspace = true } +criterion = { workspace = true } maplit = { workspace = true } pollster = { workspace = true } diff --git a/lib/benches/diff_bench.rs b/core/benches/diff_bench.rs similarity index 99% rename from lib/benches/diff_bench.rs rename to core/benches/diff_bench.rs index c1c8bf4b4ed..0a104331cc1 100644 --- a/lib/benches/diff_bench.rs +++ b/core/benches/diff_bench.rs @@ -2,7 +2,7 @@ use criterion::BenchmarkId; use criterion::Criterion; use criterion::criterion_group; use criterion::criterion_main; -use jj_lib::diff; +use jj_core::diff; fn unchanged_lines(count: usize) -> (String, String) { let mut lines = vec![]; diff --git a/lib/src/diff.rs b/core/src/diff.rs similarity index 100% rename from lib/src/diff.rs rename to core/src/diff.rs diff --git a/core/src/lib.rs b/core/src/lib.rs index 44125be0ecd..42ad60497ed 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -21,3 +21,4 @@ pub mod dag_walk; pub mod dag_walk_async; +pub mod diff; diff --git a/lib/Cargo.toml b/lib/Cargo.toml index 457a4bb2c4c..ed2b49765f1 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -14,7 +14,6 @@ readme = { workspace = true } include = [ "/LICENSE", - "/benches/", "/src/", "/tests/", "!*.pending-snap", @@ -25,10 +24,6 @@ include = [ [[test]] name = "runner" -[[bench]] -name = "diff_bench" -harness = false - [dependencies] async-trait = { workspace = true } blake2 = { workspace = true } @@ -43,7 +38,6 @@ futures = { workspace = true } gix = { workspace = true, optional = true } gix-ignore = { workspace = true } globset = { workspace = true } -hashbrown = { workspace = true } indexmap = { workspace = true } interim = { workspace = true } itertools = { workspace = true } @@ -80,7 +74,6 @@ winreg = { workspace = true } [dev-dependencies] assert_matches = { workspace = true } -criterion = { workspace = true } eyre = { workspace = true } indoc = { workspace = true } insta = { workspace = true } diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 0f2f5dbc860..30e611ef95b 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -45,7 +45,7 @@ pub use jj_core::dag_walk_async; pub mod default_backend_factories; pub mod default_index; pub mod default_submodule_store; -pub mod diff; +pub use jj_core::diff; pub mod diff_presentation; pub mod dsl_util; pub(crate) mod eol; From aaf5cc8c31b844280d171a3be5453c2d8336e08a Mon Sep 17 00:00:00 2001 From: Martin von Zweigbergk Date: Thu, 6 Aug 2026 13:18:04 -0700 Subject: [PATCH 4/5] core: move `hex_util` module from `jj-lib` `jj-lib` re-exports it, so its API is unchanged. Part of #6284 --- {lib => core}/src/hex_util.rs | 0 core/src/lib.rs | 1 + lib/src/lib.rs | 2 +- 3 files changed, 2 insertions(+), 1 deletion(-) rename {lib => core}/src/hex_util.rs (100%) diff --git a/lib/src/hex_util.rs b/core/src/hex_util.rs similarity index 100% rename from lib/src/hex_util.rs rename to core/src/hex_util.rs diff --git a/core/src/lib.rs b/core/src/lib.rs index 42ad60497ed..b840b4fc8f1 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -22,3 +22,4 @@ pub mod dag_walk; pub mod dag_walk_async; pub mod diff; +pub mod hex_util; diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 30e611ef95b..7c8297095ce 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -68,7 +68,7 @@ pub mod gitignore; pub mod gpg_signing; pub mod graph; pub mod graph_dominators; -pub mod hex_util; +pub use jj_core::hex_util; pub mod id_prefix; pub mod index; pub mod iter_util; From ceab14c61f6658a5b03903c8956a460e8a347df7 Mon Sep 17 00:00:00 2001 From: Martin von Zweigbergk Date: Thu, 6 Aug 2026 13:22:30 -0700 Subject: [PATCH 5/5] core: move `str_util` module from `jj-lib` `jj-lib` re-exports it, so its API is unchanged. The tests need the `TestResult` alias that `jj-lib` has in its crate-level `tests` module, so `jj-core` gets a copy of that module. Part of #6284 --- Cargo.lock | 6 ++++++ core/Cargo.toml | 6 ++++++ core/src/lib.rs | 7 +++++++ {lib => core}/src/str_util.rs | 0 lib/src/lib.rs | 2 +- 5 files changed, 20 insertions(+), 1 deletion(-) rename {lib => core}/src/str_util.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index e43d289f6fa..95ca7dc8c42 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2642,13 +2642,19 @@ dependencies = [ "assert_matches", "bstr", "criterion", + "either", + "eyre", "futures 0.3.33", + "globset", "hashbrown 0.17.1", "indexmap", + "insta", "itertools 0.15.0", "maplit", "pollster", + "regex", "smallvec", + "thiserror 2.0.19", ] [[package]] diff --git a/core/Cargo.toml b/core/Cargo.toml index 29fa2ace826..c70da7b8c97 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -17,15 +17,21 @@ harness = false [dependencies] bstr = { workspace = true } +either = { workspace = true } futures = { workspace = true } +globset = { workspace = true } hashbrown = { workspace = true } indexmap = { workspace = true } itertools = { workspace = true } +regex = { workspace = true } smallvec = { workspace = true } +thiserror = { workspace = true } [dev-dependencies] assert_matches = { workspace = true } criterion = { workspace = true } +eyre = { workspace = true } +insta = { workspace = true } maplit = { workspace = true } pollster = { workspace = true } diff --git a/core/src/lib.rs b/core/src/lib.rs index b840b4fc8f1..ade500f8555 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -23,3 +23,10 @@ pub mod dag_walk; pub mod dag_walk_async; pub mod diff; pub mod hex_util; +pub mod str_util; + +#[cfg(test)] +mod tests { + // Copied from `testutils::TestResult` to remove dependency cycle. + pub type TestResult = eyre::Result; +} diff --git a/lib/src/str_util.rs b/core/src/str_util.rs similarity index 100% rename from lib/src/str_util.rs rename to core/src/str_util.rs diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 7c8297095ce..34fd1479501 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -107,7 +107,7 @@ pub mod simple_op_store; pub mod ssh_signing; pub mod stacked_table; pub mod store; -pub mod str_util; +pub use jj_core::str_util; pub mod submodule_store; #[cfg(feature = "testing")] pub mod test_signing_backend;