Tour of the demo¶
A superproject with fourteen submodules, built offline, that shows every tracking mode and every state.
The repository contains scripts/demo.sh. It builds a firmware
superproject from local repositories and walks through LazySubmodules on
it in twelve short chapters. It is also an end-to-end test: every command
must exit with the status the story expects, or the demo fails.
Run the demo¶
The demo needs Bash, Git 2.39 or later and a lazysubmodules binary.
For the signed tag in chapter 10 it also needs ssh-keygen.
git clone https://github.com/FPGArtktic/lazysubmodules.git
cd lazysubmodules
scripts/build-in-container.sh build # binary in bin/lazysubmodules
scripts/demo.sh # press Enter between the chapters
With a host Go toolchain, go build -o bin/lazysubmodules ./cmd/lazysubmodules
builds the binary instead. By default the demo runs bin/lazysubmodules,
or else lazysubmodules from PATH.
Option |
Effect |
|---|---|
|
Build the demo in |
|
Build and describe the superproject, then stop; needs |
|
Do not wait for Enter between the chapters |
|
Also write the output to |
|
The |
What the demo isolates¶
Your configuration: Git runs without your user and system configuration, and
HOMEandTMPDIRpoint into the demo directory.The network: Git may use only the file transport. Every submodule URL starts with
https://git.example.invalid/, a host that does not exist, andurl.<base>.insteadOfrewrites it to bare repositories inDIR/mirror, the way a company mirror is set up.Randomness: identities and dates are fixed, so the commit IDs and the output are the same in every run.
Without --keep, everything happens in a temporary directory that is
removed at the end.
The superproject¶
Submodule |
Path |
Tracks |
Situation at the start |
|---|---|---|---|
|
|
tag pattern |
Locked at |
|
|
branch |
|
|
|
tag |
Name with a dot; the demo moves the tag upstream |
|
|
a commit |
Name and path with a space |
|
|
nothing |
Unmanaged |
|
|
branch |
Its nested submodule is at another commit |
|
|
tag |
Deinitialized; its repository in |
|
|
tag pattern |
Never cloned |
|
|
tag |
Uncommitted change |
|
|
tag pattern |
Locked at the release candidate |
|
|
branch |
A branch other than |
|
|
tag |
The tag does not exist |
|
|
tag |
The tag is SSH-signed |
|
|
tag |
|
Explore it yourself¶
Keep the demo and stop before the story changes anything. env.sh sets
HOME and the Git environment of the demo, so source it in a separate
shell:
scripts/demo.sh --keep /tmp/lsm-demo --setup-only
. /tmp/lsm-demo/env.sh
cd /tmp/lsm-demo/firmware
DIR/firmware is the superproject, DIR/mirror holds the upstream
repositories (bare), and DIR/work is where their history was written.
Every command on this site that uses the demo names runs in such a
shell.
lazysubmodules status shows every state at once. It reads local refs
only, so it works offline:
$ lazysubmodules status
NAME PATH MODE REF LOCK HEAD STATE
kernel kernel tag-pattern v6.6.* 8106f61 (v6.6.9) 8106f61 behind
u-boot bootloader/u-boot branch main 29b295c 29b295c behind
fpga.core ip/fpga-core tag v2.3.1 556baa1 556baa1 ok
crypto lib libs/crypto lib commit 5da6927 5da6927 5da6927 ok
legacy vendor/legacy - - - 2f54e11 unmanaged
tools tools/nested branch develop 3e8e307 3e8e307 ok
theme docs/theme tag v1.0.0 05f49f3 - uninitialized
fresh third_party/fresh tag-pattern v1.* f2de3e1 (v1.1.0) - uninitialized
app apps/app tag v1.2.0 cfa9d86 cfa9d86 dirty
sdk sdk tag-pattern v* 6308203 (v3.0.0-rc.2) 6308203 ok
mirror-lib libs/mirror branch stable 71eb52c 71eb52c ok
broken libs/broken tag v9.9.9 52c4bdb (v1.0.0) 52c4bdb missing-ref
signed libs/signed tag v1.0.0 5d1133e 5d1133e ok
quirky libs/quirky tag v1.0.0 64eca61 64eca61 ok
[exit status 0: success]
The [exit status N: …] lines come from the demo, not from
LazySubmodules. The states mean:
behind:
kernelhas a newerv6.6.xtag, andorigin/mainofu-boothas moved on.uninitialized:
themewas deinitialized,freshwas never cloned.dirty:
apphas an uncommitted change.missing-ref:
brokentracks tagv9.9.9, which does not exist.unmanaged:
legacyhas nolsm-modekey.ok:
sdkstays at its release candidate becausev3.0.0-rc.2is still the highest tag matching its pattern, and the tag the lock file records is never skipped for being a pre-release; see Never downgrade.toolsisokalthough its nested submodule is at another commit, andquirkyalthough.gitmodulessaysupdate = noneandignore = all.
The seventh state, drift, needs a submodule that moved away from its lock entry; the demo produces it in chapter 8, when a tag moves upstream.
States defines every state and the order in which they are checked. The machine-readable form of the same table is described in Porcelain format v1.
Try the terminal interface¶
In the same shell, start the terminal interface:
lazysubmodules tui
Move to u-boot with j, press u, and confirm with y
once the planned update is shown. Use the terminal interface
explains the rest.
The chapters¶
Each chapter corresponds to a guide on this site:
The superproject: history,
.gitmodulesand.lsm.lock(Files: .gitmodules and .lsm.lock).status: every state at once (States).status --porcelain=v1and a script that uses it (Scripts and CI).set: an unmanaged submodule is refused, then put under control (Change what a submodule tracks).update --dry-run, with and without--include-prerelease(Update submodules).A refused
update(exit status 3), and how to fix each problem (Update submodules).update --commitfor a selection, and the generated commit message (Commit updates).A tag moved upstream:
fetch,driftandverify(exit status 4) (Detect moved tags).update --fetchclones a submodule through the mirror (Mirrors, credentials and offline work).verify --signatures(Verify signatures).foreach, including a failing command (Run a command in every submodule).The final state: every submodule is
ok.
The complete output is in
examples/transcript.txt,
and the .gitmodules and .lsm.lock the demo ends with are in
examples/.
To run the whole story without stopping and keep the result:
scripts/demo.sh --keep /tmp/lsm-demo-full --no-pause