Commit 1a8608b
Match Composer patch versions like Composer does (#270)
* Match composer patch versions by release identity
A composer patch's base purl can carry the padded version Socket's
SBOM ingestion stores (pkg:composer/psr/log@3.0.2.0), while the
project's installed.json and composer.lock say 3.0.2 or v3.0.2. The
CLI compared those as strings after stripping a leading v, so such a
patch was "not found" by apply and vendor, refused by the hosted
redirect as a version mismatch, rejected by VEX discovery, and deleted
by scan --prune.
Compare composer versions the way Composer does. The new
utils::composer_version ports composer/semver 3.4.4
VersionParser::normalize (padding, v tags, stability spellings such as
-rc.1 and RC1, +build, x-dev branches); a spelling Composer rejects
only matches itself. purl_eq, the crawler, the vendor lock lookup, the
hosted lock rewriter, the redirect ledger, VEX discovery and sources,
scan discovery and the prune step now use it for composer purls.
Stored spellings (manifest keys, vendored leaf dirs, ledger keys) are
unchanged.
The shared vector file tests/fixtures/composer-version-vectors.json is
generated from real Composer 2.10.3 and is byte-identical to depscan's
copy, so the CLI and the server agree on every case; the port also
matches Composer on 12,129 fuzzed inputs. New tests cover the crawler,
lock lookup, ledger, VEX leaf, prune, a padded-version redirect golden,
and apply, vendor (with VEX) and hosted runs against a mock API that
serves only the padded spelling.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Test exact Composer releases on every OS
Composer patching was only proven on Ubuntu against three floating
releases, so a regression on macOS, Windows, or a specific 2.x line
(2.9 still falls back to the git source; 2.10 does not) went unseen.
composer-compatibility.yml runs the real vendored and hosted capstones
plus the composer VEX cells against checksum-pinned 1.10.28, 2.0.14,
2.1.14, 2.2.30, 2.5.8, 2.8.12, 2.9.8 and 2.10.3 phars on Ubuntu, and
the 1.10/2.2/2.9/2.10 lines on Windows and macOS. A Docker job runs the
vendored Docker capstone on exact 2.2.30 and 2.10.3 images.
The capstones can now run a given composer.phar through php, which is
also what makes them work on Windows. Dockerfile.composer installs an
exact, checksum-verified Composer instead of the latest one, and the
ci.yml comment on the git-source fallback is corrected.
Assisted-by: Claude Code:claude-opus-5-5
* Keep Composer patches installed on every version
Hosted redirects now remove a patched package's source wherever it
sits in its composer.lock entry, and strip dist mirrors. Before, a
failed or skipped hosted download let Composer 1 through 2.9 quietly
install the unpatched upstream code from git. Locks that an older
CLI or the GitHub app already redirected are healed on the next run.
Vendored copies no longer lose files when installed. Composer's path
mirror skipped anything matched by the copy's .gitignore (Composer 1
to 2.1), .hgignore (Composer 1) or .gitattributes export-ignore rules
(every version), so a patched file could silently go missing. Those
rules are now neutralized in the copy, and re-runs heal copies
vendored earlier. A patch that edits one of those files is refused.
vendor, scan and get now tell users to run composer install, and to
remove the package directory first on Composer 1, which does not
reinstall a changed package. Real-Composer tests cover the new cases
on 1.10 through 2.10, and docs/testing/composer-compatibility.md
records what each version does.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Keep CRLF composer.lock line endings when vendoring
Vendoring a Composer patch (vendor, scan --mode vendored, get --mode
vendored) rewrote a CRLF composer.lock, as a Windows or core.autocrlf
checkout has, with LF line endings. The commit diff covered every
line instead of the patched entry, and vendor --revert also wrote LF,
so it did not restore the original bytes.
Both writes now keep the line endings of the lock they replace, as the
hosted mode already did. A CRLF lock now round-trips byte for byte
through vendor and vendor --revert. Unit tests and a binary e2e cover
vendor, scan --vendor and get --mode vendored on a CRLF lock.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Match SBOM-padded Composer date versions
Socket's SBOM pads every numeric Composer version to four parts, so a
date release locked as 20231001 reaches the CLI as 20231001.0.0.0.
Composer rejects that spelling (a 6+ digit major is only valid as a
date), so the version key fell back to the raw text and never matched
the lock: apply, vendor, hosted redirect and VEX reported the patch as
not found for its own package.
A 2-4 part numeric spelling Composer rejects is now normalized with
its trailing .0 parts dropped. The shared vector file, copied from
depscan, gains the padded date cases checked against Composer 2.10.3.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Strip Composer dist mirrors before redirecting
A dist that lists mirrors before its url had the mirrors' url
rewritten instead of the dist's own, and a dist whose only url is a
mirror is now refused with redirect_composer_no_dist_url. Also drop
the dead composer_source_before_dist helper.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Edit only the vendored entry in composer.lock
Vendoring rewrote the whole composer.lock through serde_json, so a
lock with \/ escapes, \uXXXX escapes or mixed line endings did not
revert byte for byte. Splice only the patched entry's text, keeping
the lock's indentation, line endings and escaping.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Match vendored Composer ownership by release
Vendored ownership checks compared composer purls as exact strings,
so a ledger keyed pkg:composer/psr/log@3.0.2.0 never covered the lock's
@3.0.2 and apply, rollback, gc and scan treated a live vendored patch
as foreign or dead. Match composer purls by release identity. The
vendor hint now reads composer.lock only when this run wired
composer, and never blocks on a special file.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Do not report source-installed Composer as fixed
Composer installs from source first when preferred-install resolves
to source for the package, or when it is auto with a dev version on a
Composer 1 or 2.0 lock. A leftover source entry then means pristine
bytes, so VEX no longer reports those entries as fixed.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Name the vendor dir in Composer reinstall hints
After a hosted redirect that removed no source entry, Composer 2
keeps an existing vendor/ copy, so the hint now names the vendor
directory to remove on every Composer version.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Run Composer compatibility on every related change
The composer compatibility workflow now also runs for vendor, patch,
manifest, lockfile and command changes. Docker composer tests fail
instead of skipping when SOCKET_PATCH_DOCKER_E2E_REQUIRED=1, and the
source-fallback test disables autocrlf so Windows compares LF bytes.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Satisfy clippy in the Composer lock splice
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Read composer.json through the VEX discovery context
The source-install veto read composer.json directly, which the VEX
discovery rules forbid: every extractor reads through DiscoverCtx so
unreadable files are diagnosed and Socket identities are recognized.
Also add the golden entries for the dist-mirrors-before-url fixture.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Check Composer source and mirror layouts against the redirect oracle
The in-place composer.lock rewrite oracle now also generates locks
with dist mirrors listed before the url or as the only url, a source
member placed before name, and patched versions spelled padded or
v-prefixed. Every randomized lock is also checked to revert byte for
byte when each recorded fragment is undone, newest first, the way the
ledger reverts it.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Run Composer compatibility when the crawler oracle or group commit changes
The Composer crawler is now a directory module with its equivalence
oracle, and vendored Composer lock writes go through the per-run group
commit and the durable writer, so changes to any of them run the exact
release matrix too.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Treat a Composer date release's trailing .0 parts as padding
Adopt depscan's final shared vectors (4ecd8543d3) byte for byte. A date
release (6+ digit major) now drops its trailing .0 parts from its
identity, since SBOM padding erases whether the lock said X, X.0 or
X.0.0. Versions Composer rejects key into their own space, matching
depscan's composerVersionIdentityKey, so purl identity keys cannot
collide with a normalized one.
Also point the drop_superseded_purl composer test at the real
redirect_composer_dist edit kind: main's unknown-kind guard (#269)
correctly refuses the made-up kind it used.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Match package/-prefixed patch keys and guard reads in mirror filters
The conflict check compared patch file keys to `.gitignore` /
`.hgignore` / `.gitattributes` verbatim, but API records key files as
`package/<path>`, so a patch rewriting a filter file slipped past it and
neutralization broke the patched file's afterHash. Normalize the key
first.
Read the copy's filter files through the FIFO-safe
`read_regular_to_bytes` instead of a bare `tokio::fs::read`, so a FIFO
at the path is skipped instead of wedging the vendor run.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>1 parent 5e1ebac commit 1a8608b
129 files changed
Lines changed: 8537 additions & 313 deletions
File tree
- .github/workflows
- crates
- socket-patch-cli
- src/commands
- scan
- tests
- composer_e2e_common
- docker_vendor_common
- socket-patch-core
- src
- crawlers
- composer_crawler
- patch/redirect
- utils
- vendor
- composer_lock
- lock_inventory
- vex/discover
- testing
- tests/fixtures
- composer-vendored
- basic
- .socket/vendor/composer/5f3c8a2e-7b41-4d6a-9e0c-1a2b3c4d5e6f
- psr/log@3.0.2
- src
- dev
- .socket/vendor/composer/8c9d0e1f-2a3b-4c5d-8e6f-7a8b9c0d1e2f
- acme/tooling@dev-main
- src
- outside-anchor
- .socket/vendor/composer/5f3c8a2e-7b41-4d6a-9e0c-1a2b3c4d5e6f
- psr/log@3.0.2
- src
- reference-mismatch
- .socket/vendor/composer/5f3c8a2e-7b41-4d6a-9e0c-1a2b3c4d5e6f
- psr/log@3.0.2
- src
- source-leftover
- .socket/vendor/composer/5f3c8a2e-7b41-4d6a-9e0c-1a2b3c4d5e6f
- psr/log@3.0.2
- src
- v-tagged
- .socket/vendor/composer/5f3c8a2e-7b41-4d6a-9e0c-1a2b3c4d5e6f
- symfony/deprecation-contracts@3.5.1
- src
- redirect/composer/composer-lock
- already-redirected-source-kept
- expected
- input
- dist-before-name
- input
- dist-mirrors-before-url
- expected
- input
- dist-mirrors
- expected
- input
- no-lockfile
- input
- padded-version
- expected
- input
- source-after-dist
- expected
- input
- source-before-name
- expected
- input
- source-in-extra-untouched
- expected
- input
- source-last-key
- expected
- input
- source-not-adjacent
- expected
- input
- vex-discover-golden
- docs
- testing
- tests/docker
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
724 | 724 | | |
725 | 725 | | |
726 | 726 | | |
727 | | - | |
728 | | - | |
729 | | - | |
| 727 | + | |
| 728 | + | |
| 729 | + | |
| 730 | + | |
| 731 | + | |
| 732 | + | |
730 | 733 | | |
731 | 734 | | |
732 | 735 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
718 | 718 | | |
719 | 719 | | |
720 | 720 | | |
721 | | - | |
| 721 | + | |
722 | 722 | | |
723 | 723 | | |
724 | 724 | | |
| |||
0 commit comments