Skip to content

Latest commit

 

History

History
122 lines (86 loc) · 7.6 KB

composer-source-reference-plugin.md

File metadata and controls

122 lines (86 loc) · 7.6 KB

English | 中文文档

SuperKernel Composer Source Reference Plugin

Package: super-kernel/composer-source-reference-plugin · Packagist · Documentation index

Purpose

Composer gives a package installed from a local path repository a reference that does not follow the package's source, so composer.lock can stay the same while the code behind it changes. super-kernel/composer-source-reference-plugin replaces that reference, for super-kernel/* path packages, with one computed from the package's production source. A change to that source then changes composer.lock, and everything that trusts the lock, such as the build metadata of skernel build, sees it.

The plugin works only inside Composer, during composer update. Packages installed from Packagist, the root package, and packages of other vendors are left alone, and nothing scans source when the application starts.

Capabilities

Use local packages from path repositories

Require the plugin in the project that installs the path packages and permit it in config.allow-plugins. A path package takes its version from its directory, such as dev-main for a checkout of the main branch, so require it with a constraint that accepts that version, such as *.

The project's manifest, saved as composer.json, with a copy of super-kernel/filesystem in ../packages/filesystem:

{
    "name": "acme/billing",
    "type": "project",
    "repositories": [
        {
            "type": "path",
            "url": "../packages/filesystem"
        }
    ],
    "require": {
        "super-kernel/composer-source-reference-plugin": "^1.0.0-alpha.2",
        "super-kernel/filesystem": "*"
    },
    "minimum-stability": "dev",
    "prefer-stable": true,
    "config": {
        "allow-plugins": {
            "super-kernel/composer-source-reference-plugin": true
        }
    }
}

Composer loads a plugin only after it is installed, and the plugin must be loaded before Composer builds its dependency pool. Introducing the plugin therefore takes two updates: the first installs it, the second computes the references. From then on, every composer update does both.

composer update
composer update

composer.lock then records the path package with a dist.reference of sk-source-v1- followed by 64 hexadecimal digits, such as:

sk-source-v1-7681e1c9d13c586b0e646fead9ad081cdfe5440425fde9f384062aa9c4ec63f5

Know which packages count

During each update, the plugin processes a package only when all of these hold:

  • its name starts with super-kernel/;
  • it comes from a path repository, with a non-empty URL and an original reference;
  • the update resolves it: a package kept locked or fixed by the update, such as one not named in composer update <package>, and an alias keep their current reference.

Know which files count

The reference is a hash of:

  • the package name;
  • the reference that Composer computed for the path repository, so changes to the package's composer.json or to the repository's options still change the result;
  • every file that the package's production autoload rules reach, through psr-0, psr-4, classmap, and files, as its package-relative path and its bytes, sorted by path.

Files that exclude-from-classmap matches are left out of psr-0, psr-4, and classmap. The package's autoload-dev, its tests, its documentation, and any file no production rule reaches do not count. The absolute location of the checkout, file times, inode data, and the order in which the filesystem lists directories never affect the result, so the same source gives the same reference on every machine. A reference that the plugin already generated is recognized and not hashed again, so repeated updates are stable.

See a source change in the lock

After a change to a production source file of the path package, an update of that package writes a new reference. Restoring the file restores the previous reference; changing a file outside the production rules, such as a document, changes nothing.

composer update super-kernel/filesystem

Rebuild after the update

The metadata that skernel build generates records a hash of composer.lock. A new reference changes the lock, so the next start raises SuperKernel\Metadata\Exception\BuildRequiredException with the message The metadata generated by SKERNEL <version> does not match the current composer.lock. Run `skernel build` to generate the project metadata. Run skernel build after the update, or start with skernel run, which builds first. This is how a change in a local package reaches the application without any scan at start.

Bypass the plugin

composer update --no-plugins does not load the plugin, so Composer writes its own path references again, and the lock no longer follows the source. composer install installs the references already in the lock.

Errors

The plugin fails the update instead of writing a reference from a partial scan. Every error is a RuntimeException that Composer reports and that stops the update.

Situation Message
An autoload path with a null byte Autoload paths must not contain null bytes.
An absolute autoload path Autoload path "<path>" must be package-relative.
An autoload path with .. Autoload paths must not contain ".." segments.
A wildcard other than *, or a wildcard outside classmap Classmap paths support only the "*" wildcard. or Only classmap paths may contain the "*" wildcard.
An autoload path that resolves outside the package, such as through a symbolic link Autoload path "<path>" resolves outside package root "<root>".
A files entry that is not a regular file Autoload file "<path>" is not a regular file.
An autoload field that is not an array, or a list with non-string entries autoload.<field> must be an array. or <context> must contain only strings.
An invalid exclude-from-classmap pattern Invalid classmap exclusion pattern "<pattern>"., Classmap exclusion patterns must not contain null bytes., or Classmap exclusion patterns must not contain ".." segments.
A classmap pattern or source directory that cannot be read Unable to expand classmap pattern "<path>". or Unable to scan source directory "<path>".
A source file that cannot be read Unable to hash source file "<path>".
The path package's directory is missing Path package directory "<url>" is unavailable.

A missing optional inclusion, such as a psr-4 directory that does not exist, contributes no files and is not an error.

Relation to other packages

  • super-kernel/metadata compares the hash of composer.lock recorded by skernel build with the current lock and raises BuildRequiredException when they differ.
  • skernel build regenerates the metadata from the updated lock; skernel run builds before it starts the application.
  • The plugin depends on no other SuperKernel package, and no SuperKernel package requires it; it serves projects that install SuperKernel packages from local paths.

What not to do

Do not update the lock with --no-plugins in a project that relies on these references. Composer then writes its own path references, and later source changes no longer change composer.lock, so skernel build is not required and the application keeps metadata for the old source. Run composer update with plugins enabled.