ADR 008 Finding a version in the repository - nekrozis/qtogo GitHub Wiki

ADR-008: Finding a version in the repository

Status: Accepted (2026-10-09).

Context

  • Listing what a repository holds, and later planning an install, both begin by walking the same path: a host and a target name a directory, its children name versions, and one of those leads to an Updates.xml. This is discovery, and it is the prerequisite both list-qt (P1) and the planner (P2) share. ADR-004 left the path template open on purpose โ€” "the candidate paths are an ordered probe list in the discovery layer" โ€” and this is that record.

  • The layout is not one shape. Measured against download.qt.io, a version's directory takes one of three observed shapes:

    shape what the version directory holds captured sample
    flat the aggregate Updates.xml and the package directories itself โ€ฆ/windows_x86/desktop/qt5_5152/
    nested one same-named child, qt6_680/qt6_680/, which holds them โ€ฆ/windows_x86/desktop/qt6_680/
    arch-split children <ver>_<ext>/, one per architecture โ€ฆ/windows_x86/desktop/qt6_6110/

    (A fourth arrangement, <ver>_<ext> directly under the target, is seen for the pre-6.8 cross targets and for all_os/qt; it is the same probe entered one level up, and it gets its own fixture when those targets are listed.)

  • Which shape a version uses is not a function of the version number. windows_x86/ desktop became arch-split at 6.11.0, all_os/android and all_os/wasm at 6.8.0, and linux_x64, linux_arm64, mac_x64 and windows_arm64 desktops are still nested at 6.11.0 and 6.12.0. The same version is nested on one host and split on another, so no single number can express the boundary.

  • The reference tool encodes it as version checks and hardcoded architecture sets (EXTENSIONS_WIN_X64_QT6_11 and the like) and has paid for it with a maintenance burden measured in dozens of issues (D4 research ยง24). The captured listings under dev/qtogo/qt-repo-layout/html/ are the evidence, and the three fixtures named above are the same shapes.

Decision

  1. Discovery probes an ordered list of the observed shapes; it never branches on a version. A version directory is listed once, and the shapes are checked against that listing in a fixed order โ€” an Updates.xml of its own (flat), else a same-named child (nested), else <ver>_<ext> children (arch-split) โ€” and the first that matches decides. The three captured fixtures are exactly those three listings, which is what makes the probe a table-driven test rather than a hope. A new shape is added to the list with a captured sample. A rule of the form if version >= 6.8 may not appear in this layer, because the table above shows the boundary is per host and target.

  2. Updates.xml is authoritative; a directory name is a candidate. A token decoded by ADR-004 says a version may exist. The metadata inside the leaf says what it holds โ€” packages, versions, dependencies. Nothing is listed, installed or planned from a directory name alone.

  3. Architectures are read from the listing, not from a table. The <ver>_<ext> children name the architectures a target offers, and ext is everything after <ver>_: the split is at the first two underscores, so qt6_6110_msvc2022_arm64_cross_compiled keeps msvc2022_arm64_cross_compiled whole. A hardcoded set of architectures is the reference tool's mistake and is not repeated.

  4. A page is a listing only if it says so. A listing must carry Index of <path> matching the request; a 404 page is a failure, never an empty directory. The check is on the marker, not the size โ€” a one-child listing is a legitimate page, and the size test once misread one as a placeholder.

  5. The walk starts from an observed segment, and the segment is probed too. A host and target are addressed by a directory segment (windows_x86, linux_x64, all_os, โ€ฆ). There is no rule that a cross target sits under all_os: ios lives under mac_x64, while android and wasm are under all_os. The segment for a (host, target) comes from an observed table, by the same discipline as the layout โ€” not derived from a version, and not derived from which kind of target it is. Where a target has lived under more than one segment, the candidates are tried in a fixed order. The table is a whitelist, and the walk never takes a directory child for a segment merely because it is one: the root holds default_install, and all_os holds qtcreator, license_agreements and the like. The table lives with the code and grows from evidence, like the shape list.

Consequences

  • The probe is where the repository's shape changes are absorbed: a new layout is a new entry in a list and a fixture, not a branch in the planner or the CLI.
  • The same code lists a 5.12 flat target and a 6.11 split one; the D4 research's four-shape model needs no version table to be encoded.
  • A shape this project has not seen is reported as "not a recognised layout" rather than guessed at, so an upstream change surfaces as a failure to notice rather than as a wrong listing.
  • Discovery costs one listing per level walked โ€” the segment and the version directory โ€” plus a request for the leaf's Updates.xml; the cache absorbs them later and the levels are few.

Explicitly not covered

The exhaustive host/target-to-segment table and which targets are listable; caching a listing; all_os/qt (source, documentation and examples) and the extensions repository (โ€ฆ/extensions/<module>/โ€ฆ), which have their own shapes and arrive with them; and everything about downloading or installing.

Alternatives considered

  • Branch on the version (>= 6.8 nested, >= 6.11 split). Rejected: the boundary differs per target, so the rule is wrong for linux_x64 and for all_os.
  • Trust the directory name and skip the metadata. Rejected: the token is ambiguous (ADR-004) and says nothing about packages or architectures; the metadata is the truth.
  • Hardcode the architecture suffixes, as the reference tool does. Rejected: it is the maintenance burden the D4 research measured, and the listing already states them.
  • Treat any page that returns 200 as a listing. Rejected: MirrorBrain answers a missing path with a small "Not Found" page, which without the Index of check would read as an empty version directory.
โš ๏ธ **GitHub.com Fallback** โš ๏ธ