Skip to content

cli/manifest/deps: report dev dependency moves - #1360

Open
bigbes wants to merge 5 commits into
bigbes/tntp-9958-package-deps-clifrom
bigbes/tntp-9989-dev-dependencies
Open

cli/manifest/deps: report dev dependency moves#1360
bigbes wants to merge 5 commits into
bigbes/tntp-9958-package-deps-clifrom
bigbes/tntp-9989-dev-dependencies

Conversation

@bigbes

@bigbes bigbes commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

[dev_dependencies] was parsed and validated and reached neither the lock nor .rocks/: the identifier appeared in exactly two places, the struct field and a validation call, and resolve.effectiveDeps never looked at the table. RFC-0010 asks for the opposite in two places — §4.5 ("резолвятся и устанавливаются в .rocks/ только в dev-режиме") and step 6 of the build cycle ("ставятся туда же, но не попадают в архив"). In practice tt package add luatest --dev wrote a line into a section nobody ever read.

  • cli/manifest/lock: record the dev closure — Lock.DevDependencies, on disk [[lock.dev_dependencies]] beside [lock.products.<name>]. One global closure, because the manifest section is global too; omitempty keeps existing golden locks unchanged.
  • cli/manifest/resolve: resolve dev dependencies — products resolve first, then the dev closure with their picks layered over the caller's pins, so a rock needed by both lands in the tree once at one version. The pin-conflict retry is local rather than ResolvePinned's, because those pins are derived from the pass's own output. IsStale gains a third case: a lock with no dev closure against a manifest that declares dev dependencies, which the manifest hash alone cannot catch.
  • cli/manifest/build: install dev dependencies — build and fetch materialize the dev closure, deduplicated by name+version.
  • cli/manifest/pack: keep dev rocks out — dev-only rocks are excluded by their own rock_manifest footprint rather than by a directory named after the rock, because luatest installs share/tarantool/luatest.lua and bin/luatest outside any such directory.
  • cli/manifest/deps: report dev dependency moves — the version report the three dependency commands print now covers the dev closure, so the one command able to move a dev dependency no longer stays silent about having done so.

Stacked on #1359 — review that one first; this PR's diff is against it.

Closes TNTP-9989

Lock gains DevDependencies, serialized under the existing [lock] table
as [[lock.dev_dependencies]] beside [lock.products.<name>]. It is one
global list rather than one per product, because [dev_dependencies] is
a single top-level table with nothing to key it by.

The key is omitted entirely when the closure is empty, so every lock
written before this still marshals byte-for-byte as it did.

Part of TNTP-9989
[dev_dependencies] was parsed and validated and then ignored by the
whole pipeline, so it never reached the lock or .rocks/. The engine now
resolves it into Lock.DevDependencies.

The dev closure is global, matching the table it comes from, and is
resolved after the products with every product pick applied as a pin:
both closures land in one .rocks/ tree, which cannot hold two versions
of a rock. A dev constraint the runtime pick cannot satisfy drops that
pin and warns, the ordinary pin semantics. Its retry loop is local
rather than ResolvePinned's, since these pins are derived from the
pass's own output and dropping one upstream would not remove it.

PinsFromLock absorbs the dev closure too, or a tt package add would
drag every dev dependency forward to its newest version.

IsStale gains a third case: a manifest declaring dev dependencies over
a lock with no closure. A lock written before this carries none and its
manifest_hash still matches, so nothing else could notice.

Part of TNTP-9989
tt package build and tt package fetch now materialize the lock's dev
closure into the same .rocks/ tree as the product's, after it, so a
rock in both is already present at the product's version when the dev
list reaches it and is skipped rather than reinstalled.

Both commands operate on a developer's project, which is what
[dev_dependencies] is for. Keeping them out of a package archive is
cli/manifest/pack's job: .rocks/ is a standing tree and holds whatever
the last build put there.

Part of TNTP-9989
The .tt archive must not carry [dev_dependencies]. Not installing them
during a pack-driven build would not achieve that: .rocks/ is the
developer's standing tree, so an earlier tt package build has already
put them there. The exclusion belongs where the archive content is
selected, so stageRocks skips them in both packing modes.

A rock's footprint comes from its own rock_manifest, which catches a
flat share/tarantool/<name>.lua and a console script in bin/ that the
name-keyed directories miss. A rock with no readable rock_manifest
falls back to those directories, under-excluding rather than losing a
file the archive needs.

Dev-only is judged against every product, not just the packed one: a
rock another product's closure holds is not the dev closure's to strip.

Part of TNTP-9989
The version report tt package add/remove/update prints is built by
flattening the lock, which until now meant the product closures only. A
dev dependency that moved was resolved, written and installed without a
word, so the one command able to move it said nothing about having done
so.

Fold the dev closure into the same flattening, under the rule the
products already follow: first occurrence wins, so a rock held by both
is reported once.

Closes TNTP-9989
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.

1 participant