UPack Documentation

Universal Package Registry Specifications

  • Last Modified: 2019-02-14

A Universal Package Registry has two components: a registry file and ephemeral lock file. A package cache can also be added but it's optional. Its layout on disk is as follows:

‹registry-root›\ .lock installedPackages.json packageCache\ ‹group$packageName›\ ‹packageName.version›.upack

Like with universal packages, you can add any number of files or directories outside of these minimal requirements. However, we strongly recommend that you prefix these files and folders with an underscore (_) as not to clash with files or folders that are added in a future version of the specification.

Interacting with a Universal Package Registry and the Lock File

The lack of a registry root directory or installedPackages.json file is not an error condition, but implies that no packages are registered (i.e. have been installed). An invalid installedPackages.json file (i.e. not readable as JSON or invalid data) is an error condition and should not be automatically remediated.

The .lock file is used to indicate that another process is currently interacting with the registry. It should only be used when atomic reading/writing of the metadata file; modifying the package cache should not cause the repository to be locked.

When a .lock file exists, its modification date should be checked against the current system time. If the difference is greater than ten seconds, the other process is assumed to have crashed and the lock file should be deleted. Otherwise, the file should be rechecked in this manner until the lock is freed.

When no .lock file exists, a process should create a lock file with two lines (\r or \r\n): a human-readable description of the lock (generally the process name), and a lock token (generally a GUID). If, at the completion of the operation, the lock token matches, then file should be deleted.

No operation should take more than a second (let alone ten), and the user should be notified of all exceptions (locked registry, mismatched token).

Universal Package Registry Files

The registry file (installedPackages.json) is a JSON-based array of objects with the following properties.

Property Format
group see package metadata specs
nameR see package metadata specs
versionR see package metadata specs
path A string of the absolute path on disk where the package was installed to
feedUrl A string of an absolute url of the universal feed where the package was installed from
installationDate A string representing the UTC date when the package was installed, in ISO 8601 format (yyyy-MM-ddThh:mm:ss)
installationReason A string describing the reason or purpose of the installation

For example, BuildMaster uses {Application Name} v{Release Number} #{Package Number} (ID{Execution-Number})
installationUsing A string describing the mechanism the package was installed with; there are no format restrictions, but we recommend treating it like a User Agent string and including the tool name and version

For example, BuildMaster uses BuildMaster/5.6.11
installationBy A string describing the person or service that performed the installation

For example, BuildMaster uses the user who triggered the deployment or SYSTEM if it was a triggered/scheduled deployment

An R denotes a required property, and the object may contain additional properties as needed.

We strongly recommended that you prefix these properties with an underscore (_) as to not clash with property names that may be added to the specification later.

Package Uniqueness and Data Constraints

Only one version of a package may be registered at a time. Uniqueness is determined by a combination of the group (or lack of a group) and package name. A future version of this specification may allow for multiple versions of a package, but that will be an “opt-in” setting likely defined in a (to be specified) registry configuration file.

Package Cache

The package cache is simply a directory containing package files that may currently be installed. It must be named packageCache, and contain package files (packageName.version.upack) stored in subdirectories comprised of the group name (with $ replacing the /), a $, and the package name. For example:

‹registry-root›\ packageCache\ $hdars\ hdars.1.2.3.upack hdars.1.2.4.upack hdars.2.0.0.upack accounting$apps$accounts\ accounts.1.0.2-beta.upack

We strongly recommend that cache usage be explicitly opt-in (both when downloading and installing packages). Default package caching generally causes more problems than it helps, and can occupy a lot of disk space if not monitored.

Is this documentation incorrect or incomplete? Help us by contributing!

This documentation is licensed under CC-BY-SA-4.0 and stored in GitHub.