refactor: split into idx-core library and idx-cli binary workspace

Phase 2 of docs/DESIGN.md, no behavior change:

- crates/idx-core (library): api, analysis, cache, config file handling
  and provider selection, curl_impersonate, error, ownership, runtime,
  plus the shared test fixtures. clap derives are behind an optional
  `clap` feature so the library does not require clap.
- crates/idx-cli (binary `idx`): cli/, output/, and IdxConfig (output
  format and color resolution). Package and binary names are unchanged.
- config.rs is split: file read/write and validation move to core; a
  CLI test keeps core's OUTPUT_VALUES in sync with OutputSetting.
- ownership::db::open_db/db_path drop their unused IdxConfig argument.
- One workspace version; shared dependency versions; no third-party
  version changes in Cargo.lock. LICENSE is symlinked into each crate.
- flake: workspace version, new source paths, and a per-crate package
  check (idx-cli is built from its tarball against packaged idx-core,
  since idx-core is not on crates.io yet). CI cache key, release path
  filter, and the golden whitespace-hook exclusion follow the new layout.

Parity: all 143 golden outputs match byte for byte without
regeneration; 157 core + 17 CLI unit tests (173 before plus the new
OUTPUT_VALUES sync test), 62 CLI tests pass. Live A/B against main:
16/16 stocks cases identical; ownership discover got IDX 403 on both
(exit 4 vs 1 is the phase 1 exit-code change).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
hermes 2026-10-14 09:13:46 +00:00
commit 15947de51a
238 changed files with 544 additions and 375 deletions

View file

@ -18,6 +18,7 @@
pkgs = import nixpkgs { inherit system overlays; };
lib = pkgs.lib;
cargoManifest = builtins.fromTOML (builtins.readFile ./Cargo.toml);
version = cargoManifest.workspace.package.version;
rustToolchain = pkgs.rust-bin.stable.latest.default.override {
extensions = [ "rust-src" "rust-analyzer" ];
};
@ -31,12 +32,15 @@
rustFiles = [
./Cargo.toml
./Cargo.lock
./src
./tests/fixtures
./crates/idx-core/Cargo.toml
./crates/idx-core/src
./crates/idx-core/tests/fixtures
./crates/idx-cli/Cargo.toml
./crates/idx-cli/src
];
testSrc = lib.fileset.toSource {
root = ./.;
fileset = lib.fileset.unions (rustFiles ++ [ ./tests ]);
fileset = lib.fileset.unions (rustFiles ++ [ ./crates/idx-cli/tests ]);
};
src = lib.fileset.toSource {
root = ./.;
@ -44,8 +48,8 @@
};
commonArgs = {
inherit src;
pname = cargoManifest.package.name;
version = cargoManifest.package.version;
pname = "idx-cli";
inherit version;
CARGO_PROFILE = "dev";
strictDeps = true;
nativeBuildInputs = with pkgs; [ pkg-config ];
@ -90,7 +94,7 @@
];
ownershipPublisher = pkgs.stdenvNoCC.mkDerivation {
pname = "idx-ownership-publisher";
version = cargoManifest.package.version;
inherit version;
src = lib.fileset.toSource {
root = ./.;
fileset = lib.fileset.unions publisherScripts;
@ -155,7 +159,7 @@
${ownershipPublisher}/bin/idx-ownership-publish --help
touch "$out"
'';
fmt = craneLib.cargoFmt { src = testSrc; };
fmt = craneLib.cargoFmt { src = testSrc; pname = "idx-cli"; inherit version; };
clippy = craneLib.cargoClippy (commonArgs // {
inherit cargoArtifacts;
src = testSrc;
@ -172,20 +176,39 @@
# `curl` against a local fixture server.
nativeCheckInputs = [ pkgs.curl ];
});
# `cargo package` verification: the published crate (per the
# `include` list in Cargo.toml) must build on its own.
# `cargo package` verification: each published crate (per the
# `include` lists in crates/*/Cargo.toml) must build on its own.
package = craneLib.mkCargoDerivation (commonArgs // {
inherit cargoArtifacts;
pnameSuffix = "-package";
src = lib.fileset.toSource {
root = ./.;
fileset = lib.fileset.unions (rustFiles ++ [
./tests
./crates/idx-cli/tests
./crates/idx-core/LICENSE
./crates/idx-cli/LICENSE
./LICENSE
./README.md
]);
};
buildPhaseCargoCommand = "cargo package --locked --offline --allow-dirty";
buildPhaseCargoCommand = ''
# idx-core: full `cargo package` verification.
cargo package -p idx-core --registry crates-io --locked --offline --allow-dirty
# idx-cli depends on idx-core, which is not on crates.io yet, so
# cargo cannot resolve it from the vendored registry. Package
# idx-cli without lockfile or verification, then build the
# extracted tarball against the packaged idx-core. Real releases
# publish idx-core first and package idx-cli normally.
cargo package -p idx-cli --registry crates-io --no-verify --exclude-lockfile --offline --allow-dirty
verify="$TMPDIR/package-verify"
mkdir -p "$verify"
tar -xzf target/package/idx-core-${version}.crate -C "$verify"
tar -xzf target/package/idx-cli-${version}.crate -C "$verify"
cp Cargo.lock "$verify/idx-cli-${version}/"
(cd "$verify/idx-cli-${version}" && cargo build --offline \
--config 'patch.crates-io.idx-core.path="../idx-core-${version}"' \
--target-dir "$verify/target")
'';
doInstallCargoArtifacts = false;
installPhaseCommand = "touch $out";
});
@ -196,7 +219,7 @@
''
# The mock provider reads fixtures relative to the working dir.
mkdir -p tests
cp -r ${./tests/fixtures} tests/fixtures
cp -r ${./crates/idx-core/tests/fixtures} tests/fixtures
export HOME="$TMPDIR"
${idxPackage}/bin/idx -o json version | jq -e '.version | type == "string"'
${idxPackage}/bin/idx completions bash | bash -n