Package: romt
Romt (Rust Offline Mirror Tool) aids in using the Rust programming language in
an offline context.  Instructions and tooling are provided for:Mirroring of Rust ecosystem artifacts:Toolchains (Rustc, Cargo, libraries, etc.)Rustup (toolchain multiplexer)Crates.io (community-supplied Crates)Incremental artifact downloading (with a configurable number of simultaneous
download jobs).Incremental artifact transfer to offline network.Artifact serving in offline context (offline computer, disconnected network).ScenariosRomt support two main mirroring scenarios:Development laptop scenario:  Download Rust artifacts to the laptop when
connected to the Internet, then serve the artifacts from the laptop when
offline.Disconnected network scenario:  Download Rust artifacts on an
Internet-connected “Export” machine, transfer them to an offline network, then
serve the artifacts from an offline “Import” machine.Instructions are provided for serving the artifacts using Romt itself via
unencrypted HTTP or via the nginx web server.Alternative ToolingPanamax is an alternative to Romt, written in Rust:https://github.com/panamax-rs/panamaxRequirementsPython 3.6+ for runningromt(requires some packages from pypi.org).Git is required for manipulating the crates.io-index repository.Internet-connected computer for initial downloading (Linux, Windows, Mac[1]).Offline computer for serving artifacts (Linux, Windows, Mac).[Optional] Gnu Privacy Guard (GPG), if installed, is used used for signature
checking.[1]Note: the author does not have access to a Mac, so support for Romt on
Mac is untested but hopefully close to working.  Pull requests for
Mac-specific fixes are welcome.Romt installationNoteTake note of the instructions for upgrading from Romt versions before 0.4.0
if you have existing crate mirrors created from older Romt versions.Install prerequisitesFirst install prerequisites for Romt:Ensure Git is installed; it is required for proper manipulation of the
crates.io-index repository.For signature checking, GNU Privacy Guard (gpg) should be installed as well.
If gpg is not available, signature files (*.asc) will still be transferred
but signature checking will be skipped.Next, choose an option for installation of Romt itself.Option 1: Install a pre-built executableThe simplest method of installation is to use a pre-built self-contained
executable from the Github release area:https://github.com/drmikehenry/romt/releasesOption 2: Install from Python Package IndexRomt is also available in the Python Package Index (PyPI).  For machines with
direct Internet access, installation is straightforward; for machines on a
disconnected network, more steps are required.First ensure that thePATHcontains the directory that holds installed
Python packages:# For Linux:
~/.local/bin

# For Windows with Python version X.Y:
%APPDATA%\Python\PythonXY\ScriptsNext, choose installation method based on access to the Internet:With direct Internet access:Install directly from PyPI:pipinstall--userromtOn a disconnected Network:Downloadromtwith dependencies (from Internet-connected machine):mkdirromtcdromtpipdownloadromtTransfer theromtdirectory to a machine on the disconnected network.Install from theromtdirectory:cdromtpipinstall--user--no-index--find-links.romtOption 3: Work with sourceIf desired, the source may be cloned from Github and installed into a virtual
environment.Clone source:gitclonehttps://github.com/drmikehenry/romtcdromtCreate and activate a virtual environment for your platform:Linux:python-mvenvenvs/linux.envs/linux/bin/activateWindows:py-3-mvenvenvs\windowsenvs\windows\Scripts\activate.batMac:python-mvenvenvs/darwin.envs/darwin/bin/activateInstall Romt in development mode:pipinstall-e".[dev]"Optionally build an executable for your platform:Linux:./make-exec-linux.shWindows:make-exec-windows.batMac:./make-exec-darwin.shFind executables at:dist/linux/romt
dist/windows/romt.exe
dist/darwin/romtRomt usage overviewRomt is a Python-based command-line tool with several commands:romt toolchain: mirror and manage Rust toolchains.romt rustup: mirror and manage Rustup.romt crate: mirror and manage crate files from crates.io.romt serve: simple HTTP server for toolchains, rustup, and crates.Seeromt--helpfor overall usage help.In particular, note thatromt--readmewill display the contents of this
README file for reference.Quick-start development-laptop serverFor the development-laptop scenario, follow these steps to get a working server
configuration with mirrored Rust content.Ensure the laptop has Internet access.Install Romt (as above).Create area for mirrored artifacts:mkdirmirrorcdmirrorDownload latest stable toolchain:# Change ``linux`` to ``windows`` or ``darwin`` as appropriate:romttoolchain-v-sstable-tlinuxdownloadDownload latest stable rustup version:# Change ``linux`` to ``windows`` or ``darwin`` as appropriate:romtrustup-v-sstable-tlinuxdownloadSetup crate mirror (one-time only):romtcrateinitDownload full crates.io mirror:romtcrate-v--keep-goingupdateNoteA few crates have been removed from crates.io and are therefore not
available, so a few download failures (403 Client Error: Forbidden)
should be expected.  The--keep-goingoption allows romt to continue
in the face of these missing crates.Currently (April 2022), versions of the following crates are missing:borkcss-modulescss-modules-macrosdeploydoccyetchglib-2-0-sysgluegobject-2-0-syspeekposeConfigure crate mirror to be served from localhost (one-time only):romtcrateconfigStart Romt as a server onhttp://localhost:8000:romtserveNoteLeave the server running in this dedicated terminal.Quick-start disconnected-network serverSetting up a server for the disconnected-network scenario is similar to that for
the development-laptop scenario above; explanations that overlap that scenario
are omitted below.On Internet-connected Export machine:Install Romt (as above).Create area for mirrored artifacts:mkdirmirrorcdmirrorDownload latest stable toolchain and createtoolchain.tar.gz:# Change ``linux`` to ``windows`` or ``darwin`` as appropriate:romttoolchain-v-sstable-tlinuxdownloadpackDownload latest stable rustup version and createrustup.tar.gz:# Change ``linux`` to ``windows`` or ``darwin`` as appropriate:romtrustup-v-sstable-tlinuxdownloadpackSetup crate mirror (one-time only):romtcrateinitDownload and createcrates.tar.gz:romtcrate-v--keep-goingexportTransfertoolchain.tar.gz, ``rustup.tar.gz, andcrates.tar.gzto
Import machine.On Disconnected network Import machine:Install Romt (as above).Create area for mirrored artifacts (one-time only):mkdirmirrorPlace exportedtoolchain.tar.gz, ``rustup.tar.gz, andcrates.tar.gzfiles into thismirror/directory, and enter the directory at a prompt:cdmirrorImport toolchain and rustup:romttoolchain-vunpackromtrustup-vunpackSetup crate mirror (one-time only):romtcrateinit-importImportcrates.tar.gz:romtcrate-v--keep-goingimportConfigure crate mirror to be served from localhost (one-time only):romtcrateconfigStart Romt as a server onhttp://localhost:8000:romtserveNoteLeave the server running in this dedicated terminal.Quick-start client setupFollow these steps to configure Rust tooling for use with a mirror server on
localhost using either Quick-start server configuration above.Setup environment variables to point to the server.  By default, this will be
athttp://localhost:8000; adjust all uses oflocalhost:8000below for
different server address:port combinations:# For Linux/Mac:exportRUSTUP_DIST_SERVER=http://localhost:8000exportRUSTUP_UPDATE_ROOT=http://localhost:8000/rustup# For Windows:setRUSTUP_DIST_SERVER=http://localhost:8000setRUSTUP_UPDATE_ROOT=http://localhost:8000/rustupNoteThese variables must be set in each terminal window before using the mirror
server.Download therustup-initinstaller for your platform from the Romt server
using the appropriate URL below, saving it into the current directory:Linux:http://localhost:8000/rustup/dist/x86_64-unknown-linux-gnu/rustup-initWindows:http://localhost:8000/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exeMac:http://localhost:8000/rustup/dist/x86_64-apple-darwin/rustup-initRun the installer, accepting the defaults:# Linux/Mac:chmod+xrustup-init./rustup-init# Windowsrustup-initEnsure environment changes take place in current shell:# For Linux/Mac:source$HOME/.cargo/env# For Windows:PATH%USERPROFILE%\.cargo\bin;%PATH%Try out some rustup commands:rustup self update
rustup component add rust-srcCreate the text file~/.cargo/config(%USERPROFILE%\.cargo\configon
Windows) with the following content:[source.crates-io]
registry = 'http://localhost:8000/git/crates.io-index'

# Disable cert revocation checking (necessary only on Windows):
[http]
check-revoke = falseCreate a sample project to demonstrate crate usage:cargonewrand_testcdrand_testAppend the following line toCargo.toml(just below the[dependencies]line):rand = ""Fetchrandand its dependencies:cargo fetchUpgrading from Romt versions before 0.4.0When upgrading Romt, it’s recommended to use the same version of Romt on both
the Internet-connected and offline hosts.Romt 0.4.0 changes how crate files are stored on-disk by default, in order to
fix problems using a mirror with case-sensitive and case-insensitive filesystems
simultaneously.  Older Romt stores crates in directories based on the prefix of
each crate’s mixed-case name (e.g.,MyCrate-0.1.0.cratewould have a prefix
ofMy/Cr/).  This works for filesystems that are either case-sensitive or
case-insensitive, but it does not allow a tree of crate files created with one
case sensitivity to be accessed using the opposite case sensitivity.  Romt 0.4.0
now defaults to making prefix directories in lowercase, allowing a crate mirror
to be used via arbitrary case sensitivity.For backward compatibility, Romt 0.4.0 supports the use of existing mirror trees
transparently.  Newly created mirror trees will use lowercase prefixes by
default (usable on all filesystems); mixed-case prefixes may be requested via
the--prefix=mixedflag (permitted only with case-sensitive filesystems).Romt 0.4.0 generates crate archives (crates.tar.gz) using mixed-case
prefixes by default for backward compatibility, but it can also use lowercase
prefixes for consistency with the preferred on-disk prefix format.  To
distinguish the prefix style, Romt 0.4.0 adds anARCHIVE_FORMATfile to the
crate archive.  Format1is compatible with old Romt except for the addition
of theARCHIVE_FORMATfile.  Old Romt will see this file as an error and
refuse to unpack the archive by default, but processing will succeed using the
invocationromt crate unpack--keep-going.  To avoid corrupting
an existing crate mirror by unpacking a new crate archive with old Romt,
new archives currently default to format1, but it’s recommended to upgrade
Romt to ensure proper processing of all crate archive formats.Converting crate mirror to lowercase prefixesTo convert an existing crate mirror (using mixed-case prefixes) to the new
format (using lowercase prefixes), the easiest method is to make a crate archive
of the old mirror, then unpack the archive using the new format.  For example:# Pack up existing crate mirror into ``crates.tar.gz``:romtcrate-v--keep-going--start0--endmasterpack# Rename the old crate tree out of the way:mvcratescrates.old# Initialize for importing with a temporary index area:romtcrate--indexindex-tmpinit-import# Unpack crates from crates.tar.gz into new crates/ tree:romtcrate-v--indexindex-tmpunpack# Verify conversion:romtcrateverify-v--start0# Cleanup:rm-rfindex-tmpcrates.oldNote that the above steps eliminate the unpredictable-case prefixes that are
created with old Romt using a case-insensitive filesystem (such as on Windows).CommonalitiesRomt has some features that are shared across two or more commands.TARGETThe TARGET specifies the platform for executables using standard tuple values
(e.g.,x86_64-unknown-linux-gnu).  Any tuples supported by Rust are valid.
Typical values are shown below; in parentheses are aliases Romt provides for
ease of typing these common targets:x86_64-unknown-linux-gnu(aliaslinux)x86_64-pc-windows-msvc(aliaswindows)x86_64-apple-darwin(aliasdarwin)TARGET values are given by the option--targetTARGET.  Multiple TARGET
options may be given, and each TARGET will be split at commas and whitespace to
produce a list of desired TARGET values, e.g.:--target linux,windows --target 'darwin i686-pc-windows-msvc'A TARGET may be a literalallthat expands to all known targets.  Forromt toolchain, this list comes from the manifest file.  Forromt rustup, it
comes from a hard-code list within Romt; this is an ever-changing list that may
be out-of-date in an old release of Romt.A TARGET may be a literal*(asterisk) that expands to all targets with at
least one on-disk file for the given SPEC.SHA256 hashesEach file named{file}.sha256contains the SHA256 hash of the
corresponding file named{file}.  Romt verifies all hashes to ensure file
integrity.Command-line option detailsThe option--num-jobscontrols how many simultaneous download jobs Romt
may use at a time.  By default,--num-jobs=4, which should be a
conservative value that won’t stress the servers heavily.The option--timeoutcontrols the timeout in seconds for downloading.
A value of zero disables the timeout functionality altogether.The option--assume-okinstructs Romt that all files already on-disk are
to be assumed OK; no hashes or signatures are checked for such files.toolchainoperationThetoolchainoperation deals with Rust toolchains.SPECEach toolchain is identified by a SPEC value which takes on one of the below
forms:{channel}
{channel}-{date}
{date}In the above SPEC forms:{channel}is typically one of the channel namesnightly,beta,stable.  It may also be a version number of the formX.Y.Zor a
literal*(asterisk) as a wildcard that expands to the setnightly,beta,stable.{date}is typically of the formYYYY-MM-DD(e.g.,2020-04-30).  It
may also be a literal*(asterisk) as a wildcard that expands to all
toolchain dates on-disk, or a literallatestthat expands to the most
recent toolchain date on-disk.Note that a SPEC value consisting of a single*represents a wildcarded{date}value, not a{channel}value.  It is equivalent to*-*(making both{channel}and{date}wild).Wildcards (*andlatest) may not be used when downloading, and the{channel}is always required.  The{date}field may be omitted to
download the most recent toolchain for the given channel.SPEC values are given by the option--selectSPEC.  Multiple SPEC options
may be given, and each SPEC will be split at commas and whitespace to produce
a list of desired SPEC values.  E.g.:--select nightly,stable --select beta-2020-01-23TARGETSee the TARGET section of Commonalities above for details.Manifest fileA manifest file provides details about a toolchain for a given SPEC, enumerating
valid combinations of toolchain components and targets.The manifest filename is of the formchannel-rust-{channel}.toml, where{channel}is one ofnightly,beta, orstable.  Forstablemanifests, the manifest is duplicated into a file of the formchannel-rust-{version}.toml, where{version}is a version number of the
formX.Y.Z.DownloadingDownloading is requested via theromt toolchain downloadcommand.A toolchain is specified by a SPEC/TARGET pair.  Both must be given.
Wildcarding (via*orlatest) is not permitted, though the{date}may be omitted from the SPEC value, and TARGET may be the literalallto
download all known targets for the SPEC.Files are downloaded fromhttps://static.rust-lang.org/distby default; this
may be changed via the option--url<URL>.Files are downloaded to the destination directorydist/by default; this
may be changed via the option--destDEST.When downloaded, the toolchain will be stored on-disk in the following layout:dist/
  YYYY-MM-DD/
    channel-rust-{channel}.toml
    channel-rust-{channel}.toml.asc
    channel-rust-{channel}.toml.sha256
    {component}-{channel}.tar.xz
    {component}-{channel}.tar.xz.asc
    {component}-{channel}.tar.xz.sha256
    {component}-{channel}-{target}.tar.xz
    {component}-{channel}-{target}.tar.xz.asc
    {component}-{channel}-{target}.tar.xz.sha256Where:YYYY-MM-DDis the toolchain date.{channel}is one ofnightly,beta, orstable.{component}represents a toolchain component (e.g.,rust,cargo,rust-src).{target}represents a target tuple (e.g.,x86_64-unknown-linux-gnu).
Components lacking a{target}are common across all targets; currently
this is limited to therust-srccomponent.Each file named{file}.asccontains the Gnu Privacy Guard (GPG) digital
signature of the corresponding file named{file}.  Checking signature
requires GPG; if it is not installed, signature files won’t be checked but
they will still be transferred.  The verification key is available athttps://static.rust-lang.org/rust-key.gpg.ascii; this key is built into Romt
itself for offline use.For example, after downloading with this command:romttoolchaindownload--specnightly-2020-04-30--targetlinuxThe tree would contain (among other files):dist/
  2020-04-30/
    channel-rust-nightly.toml
    channel-rust-nightly.toml.asc
    channel-rust-nightly.toml.sha256
    rust-src-nightly.tar.xz
    rust-src-nightly.tar.xz.asc
    rust-src-nightly.tar.xz.sha256
    rust-nightly-x86_64-unknown-linux-gnu.tar.xz
    rust-nightly-x86_64-unknown-linux-gnu.tar.xz.asc
    rust-nightly-x86_64-unknown-linux-gnu.tar.xz.sha256For convenience, the most recently released toolchain for each channel
(nightly,beta, orstable) will be copied directly into thedist/directory.  This is especially helpful forstableandbetabuilds so that the date of the most recent release need not be known in advance.
Forstablemanifests, the version-specific copy of the manifest is placed
intodist/as well.For example, as of 2020-05-06, the most recent manifests were for SPEC values
of:nightly-2020-05-06beta-2020-04-26stable-2020-04-23(version1.43.0)On that date, performing a download with--targetlinuxand--specnightly,beta,stablewould yield the following downloaded manifests:dist/
  channel-rust-beta.toml
  channel-rust-nightly.toml
  channel-rust-stable.toml
  channel-rust-1.43.0.toml
  2020-04-23/
    channel-rust-stable.toml
    channel-rust-1.43.0.toml
  2020-04-26/
    channel-rust-beta.toml
  2020-05-06/
    channel-rust-nightly.tomlWhere the dateless manifests housed directly indist/are copies of those
from the dated directories.Because the contents of dateless manifests are subject to change, cached copies
of these files are re-downloaded during adownloadcommand.Packing/unpackingDownloaded toolchains may be packed into anARCHIVEfile using theromt toolchain packcommand.The archive file may be moved to another machine and unpacked using theromt toolchain unpackcommand.For bothpackandunpack, theARCHIVEfile is namedtoolchain.tar.gzby default; this may be changed via the option--archiveARCHIVE.Anunpackcommand automatically performs averify(described below).  In
addition, dateless manifests are reconstructed automatically duringunpackas part of a fixup operation (described below).An archive file contains files from dated subdirectories only.  Given the
example above for thedownloadcommand, theARCHIVEwould contain only
these manifests:dist/
  2020-04-23/
    channel-rust-stable.toml
  2020-04-26/
    channel-rust-beta.toml
  2020-05-06/
    channel-rust-nightly.tomlFixupEach toolchain identified by a SPEC has a canonical manifest file stored in the
toolchain’s dated directory.  This file has a path of the formYYYY-MM-DD/channel-rust-{channel}.toml, where{channel}is one of the
channel namesnightly,beta, orstable.The “fixup” operation is responsible for making any necessary copies of each
canonical manifest in thedist/tree.  If the given on-disk manifest is
found in the latest dated directory, it will be copied into the top-leveldist/directory.  In addition, for each SPEC on thestablechannel a
version-specific manifest file of the formchannel-rust-X.Y.Z.tomlwill be
copied into the dated directory and the top-leveldist/directory.A fixup operation may be explicitly requested via theromt toolchain fixupcommand, though that should rarely be required because it is automatically
performed after anydownloadorunpackcommand.Consider the example above for thedownloadcommand; it would generate an
archive containing only these canonical manifests:dist/
  2020-04-23/
    channel-rust-stable.toml
  2020-04-26/
    channel-rust-beta.toml
  2020-05-06/
    channel-rust-nightly.tomlThefixupcommand would copy these manifests to create:dist/
  channel-rust-beta.toml
  channel-rust-nightly.toml
  channel-rust-stable.toml
  channel-rust-1.43.0.toml
  2020-04-23/
    channel-rust-stable.toml
    channel-rust-1.43.0.toml
  2020-04-26/
    channel-rust-beta.toml
  2020-05-06/
    channel-rust-nightly.tomlListing downloaded toolchainsTheromt toolchain listcommand prints information about on-disk toolchains
for the provided SPEC values.  Wildcards are permitted.For example, the most recent on-diskstablerelease can be shown via:romttoolchainlist--select'stable-latest'With resulting output:stable-2020-04-23(1.43.0)    targets[1/82]    packages[12/311]
  x86_64-unknown-linux-gnuTo suppress information about targets, use--quiet:romttoolchainlist--select'stable-latest'--quietWith resulting output:stable-2020-04-23(1.43.0)    targets[1/82]    packages[12/311]With wildcards, Romt can provide a listing of all available toolchains for a
given channel:romttoolchainlist-s'nightly-*'With example resulting output:nightly-2020-05-06(1.45.0)   targets[1/84]    packages[12/316]
  x86_64-unknown-linux-gnu
nightly-2020-05-04(1.45.0)   targets[1/84]    packages[12/316]
  x86_64-unknown-linux-gnu
nightly-2020-04-30(1.45.0)   targets[1/84]    packages[12/313]
  x86_64-unknown-linux-gnuAfter toolchain importation, it may be useful to list toolchains for each
channel for reference:romttoolchainlist-s'nightly-*'>nightly.txtromttoolchainlist-s'beta-*'>beta.txtromttoolchainlist-s'stable-*'>stable.txttoolchainscenariosFor the laptop scenario, only thedownloadcommand is needed.  After
downloading a toolchain, it will be available for serving viaromt serve(or other means).  For example, to download the latest stable toolchain for
Linux:romttoolchaindownload--selectstable--targetlinuxFor the disconnected network scenario, toolchains are downloaded and packed on
an Internet-connected Export machine, then unpacked on an Import machine, e.g.:On the Export machine:First, download the latest stable toolchain for Linux into a localdist/directory and pack it into an archive for transfer:romttoolchaindownloadpack--selectstable--targetlinuxTransfer the resultingtoolchain.tar.gzfile onto the Import machine.On the Import machine:Unpack the archive into a localdist/directory:romttoolchainunpackMiscellaneous commandsA few additional commands are provided forromt toolchain.romt toolchainfetch-manifestis the same asdownload, but only the
manifest is downloaded.romt toolchain verifyvalidates the SHA256 hashes and GPG signatures of
on-disk toolchains.  It is implicitly done as part ofdownloadandunpack.romt toolchainall-targetsprints a list of all known targets mentioned in
the given SPEC.Command-line option detailsThe option--warn-signatureinstructs Romt to treat signature failures as
warnings instead of as failures.  Signature files will still be downloaded and
transferred.  This might be helpful in case the signing key changes.The option--no-signatureprevents both downloading and checking of GPG
signature files (*.asc).  This is mainly for testing.rustupoperationTherustupoperation deals with the Rustup toolchain multiplexer.SPECEach rustup version is identified by a SPEC value which takes on one of the
below forms:{version}
stable
latest
*In the above SPEC forms:{version}is a version number of the formX.Y.Z.A literalstablerefers to the current stable version given in therelease-stable.tomlfile (described later).A literal*(asterisk) is a wildcard that expands to all on-disk versions.A literallatestis a wildcard that expands to the latest on-disk version.Wildcards (*andlatest) may not be used when downloading, butstableis permitted.SPEC values are given by the option--selectSPEC.  Multiple SPEC options
may be given, and each SPEC will be split at commas and whitespace to produce
a list of desired SPEC values.  E.g.:--select stable,1.20.0 --select '1.19.0 1.20.1'TARGETSee the TARGET section of Commonalities above for details.DownloadingDownloading is requested via theromt rustup downloadcommand.A rustup executable is specified by a SPEC/TARGET pair.  Both must be given.
Wildcarding (via*orlatest) is not permitted, though SPEC may be the
literalstableto download the latest stable release, and TARGET may be the
literalallto download all known targets for the SPEC.Files are downloaded fromhttps://static.rust-lang.org/rustupby default;
this may be changed via the option--url<URL>.Files are downloaded to the destination directoryrustup/by default;
this may be changed via the option--destDEST.When downloaded, files will be stored on-disk in the following layout:rustup/
  release-stable.toml
  archive/
    {version}/
      {target}/
        {rustup}
        {rustup}.sha256
  dist/
    {target}/Where:release-stable.tomlis a configuration file that indicates the most recent
stable version of rustup.{version}is a rustup version of the formX.Y.Z.{target}represents a target tuple (e.g.,x86_64-unknown-linux-gnu).{rustup}is the name of the rustup executable.  On most platforms, this isrustup-init; on Windows, it’srustup-init.exe.For example, if version 1.21.1 were the most recent stable version, after
downloading with this command:romtrustupdownload--specstable--targetlinuxThe tree would contain:rustup/
  release-stable.toml
  dist/
    x86_64-unknown-linux-gnu/
      rustup-init
      rustup-init.sha256
  archive/
    1.21.1/
      x86_64-unknown-linux-gnu/
        rustup-init
        rustup-init.sha256For convenience, all targets found in the most recently released rustup version
will be copied directly into therustup/dist/directory.Because therelease-stable.tomlfile is subject to change, this file will be
re-downloaded during adownloadcommand when SPEC isstable.Packing/unpackingDownloaded rustup executables may be packed into anARCHIVEfile using theromt rustup packcommand.The archive file may be moved to another machine and unpacked using theromt rustup unpackcommand.For bothpackandunpack, theARCHIVEfile is namedrustup.tar.gzby default; this may be changed via the option--archiveARCHIVE.Anunpackcommand automatically performs averify(described below).  In
addition, therustup/dist/tree is created automatically duringunpackas part of a fixup operation (described below).An archive file contains files fromrustup/archive/{version}subdirectories
only.  Given the example above for thedownloadcommand, theARCHIVEwould contain only these files:rustup/
  archive/
    1.21.1/
      x86_64-unknown-linux-gnu/
        rustup-init
        rustup-init.sha256FixupEach rustup version is stored in a directory of the formrustup/archive/{version}.The “fixup” operation is responsible for copying the most recent on-disk
rustup version torustup/dist/, and for updatingrustup/release-stable.tomlto contain the most recent version number.A fixup operation may be explicitly requested via theromt rustup fixupcommand, though that should rarely be required because it is automatically
performed after anydownloadorunpackcommand.Consider the example above for thedownloadcommand that generated the
following archive contents:rustup/
  archive/
    1.21.1/
      x86_64-unknown-linux-gnu/
        rustup-init
        rustup-init.sha256Assuming this is the latest on-disk version, thefixupcommand would copyrustup/archive/1.21.1torustup/archiveas shown below, and it would
createrelease-stable.tomlto point to version1.21.1:rustup/
  release-stable.toml
  archive/
    1.21.1/
      x86_64-unknown-linux-gnu/
        rustup-init
        rustup-init.sha256
  dist/
    x86_64-unknown-linux-gnu/
      rustup-init
      rustup-init.sha256Listing downloaded rustup versionsTheromt rustup listcommand prints information about on-disk rustup
versions for the provided SPEC values.  Wildcards are permitted.For example, the most recent on-disk version can be shown via:romtrustuplist--select'latest'With resulting output:List: 1.21.1
1.21.1   targets[1]
  x86_64-unknown-linux-gnuTo suppress information about targets, use--quiet:romtrustuplist--select'latest'--quietWith resulting output:1.21.1With wildcards, Romt can provide a listing of all available rustup versions:romtrustuplist-s'*'With example resulting output:List: 1.21.1
1.21.1   targets[1]
  x86_64-unknown-linux-gnu
List: 1.21.0
1.21.0   targets[1]
  x86_64-unknown-linux-gnu
List: 1.20.0
1.20.0   targets[1]
  x86_64-unknown-linux-gnurustupscenariosFor the laptop scenario, only thedownloadcommand is needed.  After
downloading a rustup executable, it will be available for serving viaromt serve(or other means).  For example, to download the latest stable rustup for
Linux:romtrustupdownload--selectstable--targetlinuxFor the disconnected network scenario, rustup versions are downloaded and packed
on an Internet-connected Export machine, then unpacked on an Import machine,
e.g.:On the Export machine:First, download the latest stable rustup for Linux into a localrustup/directory and pack it into an archive for transfer:romtrustupdownloadpack--selectstable--targetlinuxTransfer the resultingrustup.tar.gzfile onto the Import machine.On the Import machine:Unpack the archive into a localrustup/directory:romtrustupunpackMiscellaneous commandsA few additional commands are provided forromt rustup.romt rustup verifyvalidates the SHA256 hashes of on-disk rustup
executables.  It is implicitly done as part ofdownloadandunpack.romt rustupall-targetsprints a list of all known targets in Romt’s
hard-coded list.crateoperationThecrateoperation deals with crates (community-written packages of Rust
source code) from the serverhttps://crates.io.Crates.io INDEXIndividual crates are indexed via a Git repository called INDEX.  By default,
INDEX is cloned fromhttps://github.com/rust-lang/crates.io-index; this may be
changed with the option--index-urlINDEX_URL.The INDEX contains one text file for each crate name, where each line of the
file is a JSON-formatted description of a single version of that crate.  When a
new crate file is uploaded, another line is appended to the file and a new
commit is made.The on-disk INDEX directory defaults togit/crates.io-index; it may be
changed via the option--indexINDEX.INDEX branchesINDEX is essentially a standard Git clone with some additional conventions.
It uses the following branches:remotes/origin/masterThemasterbranch of theoriginrepository.  Typically this is the
repository on Github given by the default value of INDEX_URL.masterThe localmasterbranch.  This is based onremotes/origin/master,
with possible changes to theconfig.jsonfile (described later).origin_masterA local convenience branch that tracksremotes/origin/master.  This
makes it easy to pushmasterandremotes/origin/masterto a server.markA branch for tracking progress (detailed later).workingA branch checked out to the working tree and used for merging and
modifying repository content; changes are then published atomically to themasterbranch to avoid race conditions.INDEX file structureTo keep the number of files in each directory down to a manageable size, the
text files for each crate are distributed into subdirectories based on the first
few characters of the crate’s name.  The path within INDEX for a crate named{crate}is given by{prefix}/{crate}, where{prefix}is calculated
based on the length of the crate’s name; variations exist for 1-, 2-, 3-, and
4-or-more characters:{prefix}crate name lengthcrate name (as lowercase)11a22ab3/a3abcab/cd4 or moreabcd*The directory names are based on the crate name converted to lowercase so that
the repository may be cloned on case-insensitive filesystems (such as on
Windows).For example, the file for theserdecrate would be found by default atgit/crates.io-index/se/rd/serde.In addition to per-crate files, there is aconfig.jsonfile in the INDEX
that configures the URL for downloading crate files.INDEX rangeA RANGE is defined by a START commit and an END commit.  The changes made to the
INDEX between START and END represent the list of crates in RANGE that were
uploaded to crates.io.Because START and END represent Git commits, any valid Git commit reference may
be used.  In addition, START may be given the value0when there is no
starting commit, in which case all commits through END are in RANGE.The START commit is selected via the option--startSTART.The END commit is selected via the option--endEND.In general, START and END must both be valid commits in the INDEX; but because
Git branches can’t refer to an empty commit, there is no way to initialize a
branch name to a value (like0) that means “the start of the repository”.
To handle this case, the option--allow-missing-startindicates that Romt
should treat an unknown branch name for START to be the same as0.Crate filesCrate files (*.crate) are tarballs containing Rust source code.  Filenames
follow the naming convention{crate}-{version}.crate, where{crate}is
the name of the crate (e.g.,serde) and{version}is the crate’s version
number in the formX.Y.Z.The URL for a given crate file is given by the template CRATES_URL.  The default
value ishttps://static.crates.io/crates/{crate}/{crate}-{version}.crate; it may
be changed with the option--crates-urlCRATES_URL.For each crate, the CRATES_URL template will be expanded by replacing{crate}with the name of the crate and{version}with its version.  For
example, the default URL for version1.0.99of theserdecrate would be:https://static.crates.io/crates/serde/serde-1.0.99.crateAs an alternative, to use the crate.io API for downloading crates, set
CRATES_URL to:https://crates.io/api/v1/crates/{crate}/{version}/downloadCRATES_ROOTCrate files (*.crate) are stored on-disk in a directory tree rooted at
CRATES_ROOT, which defaults tocrates/and may be changed via the option--cratesCRATES_ROOT.As with the INDEX, crate files are distributed into subdirectories based on the
first few characters of the crate’s name.  By default, the prefixes are
lowercase (unless forced to mixed-case viaromt crate--prefix=mixed).  Romt
versions before 0.4.0 used mixed-case prefixes exclusively, as the author did
not know how to compute lowercase prefixes in nginx rules (this is now solved
using Perl with nginx).  Mixed-case prefixes caused problems when accessing a
crates mirror via both case-sensitive and case-insensitive shares
simultaneously, so lowercase prefixes are now preferred.{prefix}crate name lengthcrate name11a22ab3/a3abcab/cd4 or moreabcd*A crate with name{crate}and version{version}is found within
CRATES_ROOT at{prefix}/{crate}/{crate}-{version}.crate.For example, version 1.0.99 of theserdecrate would be found by default atcrates/se/rd/serde/serde-1.0.99.crate.InitializingThe INDEX and CRATES_ROOT areas must be initialized before use.  The
initialization method depends on the use.Theromt crate initcommand creates the INDEX and CRATES_ROOT areas and
prepares the INDEX as a Git repository with remote namedoriginthat points
to a Git remote given by INDEX_URL.  This is suitable for the laptop scenario
and for the Export machine in the disconnected network scenario.Theromt crateinit-importcommand is for use on the Import machine in the
disconnected scenario.  It’s similar toinit, but instead of configuring
INDEX’soriginremote to INDEX_URL, it configuresoriginto be a local
bundle file at BUNDLE_PATH that conveys INDEX commits sent from the Export
machine.  Subsequentunpackcommands will query theurlkey for theoriginremote within INDEX to determine BUNDLE_PATH.  The default value of
BUNDLE_PATH isorigin.bundlewithin the INDEX directory; this may be changed
via--bundle-pathBUNDLE_PATH.By default, crate files are stored on-disk using lowercase prefixes.  Usingromt crate--prefix=mixedforces the use of mixed-case prefixes (as used in
Romt before version 0.4.0).  Lowercase prefixes are recommended.  Romt will not
permit the use of--prefix=mixedwhen using case-insensitive filesystems
(such as on Windows) to avoid creating unpredictable-case prefixes due to case
aliasing issues.Romt (as of version 0.4.0) creates aconfig.tomlfile in CRATES_ROOT as an
implementation detail to aid in the transition to lowercase crate prefixes;
users should generally not have to interact with it.  Future versions of Romt
may remove this configuration file and use lowercase prefixes exclusively.configAfter initialization viainitorinit-import, the local INDEX repository
will be properly setup.  If the INDEX contents will be served to clients
directly (e.g., for the laptop scenario or the Import machine in the offline
network scenario), it must be configured for the URL of the offline server by
editing the fileconfig.jsonwithin the top-level directory of INDEX.  The
default contents ofconfig.json(as found on Github) are:{
  "dl": "https://crates.io/api/v1/crates",
  "api": "https://crates.io"
}Thedlkey in particular informscargoand other INDEX consumers how to
download crate files cataloged by INDEX.Theromt crate configcommand editsconfig.jsonbased on the value of
SERVER_URL; this defaults tohttp://localhost:8000(as used byromt serve, described later).  It may be changed via the option--server-urlSERVER_URL.Given SERVER_URL, thedlkey will be set to:SERVER_URL/crates/{crate}/{crate}-{version}.crateBy default, this will be:http://localhost:8000/crates/{crate}/{crate}-{version}.crateRust tooling (e.g., Cargo) will start with the value of thedlkey and
substitute{crate}with the name of the crate and{version}with the
crate’s version number to form the URL for a given crate file.Only the SERVER_URL portion of thedlkey is currently configurable; the
rest of the URL is hard-coded to match the conventions ofromt serve.
However, any changes manually committed toconfig.jsonwill be preserved by
subsequent Romt operations.Changes toconfig.jsonare committed to the localworkingbranch, and
ultimately published to the localmasterbranch (via themarkcommand).
As upstream commits are merged intomaster, Romt will ensure that the localconfig.jsonchanges take precedence over possible upstream changes.markRomt uses a branch namedmarkas a commit placeholder within INDEX.  It
tracks progress through the INDEX, marking one operation’s END commit for use as
the next operation’s START commit.Theromt crate markcommand sets both themarkbranch and themasterbranch to the commit indicated by END.  START defaults tomarksuch that
subsequent operations pick up where previous ones left off.  END defaults toHEAD(generally theworkingbranch) such that RANGE includes all
unprocessed commits.Note that working copy modifications (merges and edits) are done on theworkingbranch.  Changes won’t be visible on themasterbranch until
after themarkcommand is executed, ensuring clients won’t see partially
complete modifications while the repository is being updated.Pulling INDEX commitsBefore downloading crate files, the INDEX must be updated.  Theromt crate pullcommand fetches the latest commits from INDEX’soriginremote into
theremotes/origin/masterbranch, then marks this location in the local
branchorigin_masterfor convenience of reference.  The fetched commits are
then merged into the HEAD branch (typicallyworking), preserving any local
modifications that may have been made toconfig.json.  If the merge
operation fails, the working copy is reset toremotes/origin/masterand any
local changes toconfig.jsonthat may have been present inHEADbefore
the pull are re-applied.Note: In Romt version 0.1.3 and earlier,HEADdefaulted tomaster,
leaving a small race window where partial modifications to the repository could
be visible to clients (e.g.,mastermight include mention of a crate that
hasn’t yet been downloaded).  Therefore, Romt now defaults to using the branchworkingfor merging and other modifications to the repository.  These
changes won’t be visible onmasteruntil themarkcommand is invoked.
At eachpulloperation, Romt will upgrade the repository to use aworkingbranch ifHEADis not set toworkingand theworkingbranch does not yet exist.  To avoid this, pre-create aworkingbranch (with
arbitrary content) before executing apullcommand, and Romt will not switchHEADtoworking.DownloadingDownloading of crate files is requested via theromt crate downloadcommand.The subset of crate files to download is determined by the RANGE of commits
(from START through END) in the INDEX.  Each file is downloaded from the
upstream location indicated by CRATES_URL as explained previously.  As part of
downloading, Romt verifies the SHA256 hash of each crate against the value
stored in INDEX to ensure file integrity.Each crate file is stored below CRATES_ROOT using the prefix mechanism described
earlier.Sometimes individual crate files are removed from the upstream mirror.  Romt
warns about such failures and continues with the rest of the crates in the
RANGE.  After attempting all crates in RANGE, by default Romt will abort if
any crates failed to download.  The option--keep-goingallows Romt to
continue past download failures to subsequent steps (e.g., packing an archive
file).Packing/unpackingTheromt crate packcommand creates a Git bundle file of the commits in
RANGE, then packs the bundle file along with the downloaded crate files included
in RANGE into anARCHIVEfile.The archive file may be moved to another machine and unpacked using theunpackcommand.For bothpackandunpack, theARCHIVEfile is namedcrates.tar.gzby default; this may be changed via the option--archiveARCHIVE.For thepackcommand, a Git bundle file is written to disk at BUNDLE_PATH
before being inserted into the ARCHIVE.  The default value of BUNDLE_PATH isorigin.bundlewithin the INDEX directory; this may be changed via--bundle-pathBUNDLE_PATH.Anunpackcommand extracts the Git bundle file and all crate files, placing
the bundle at the BUNDLE_PATH value specified with theinit-importcommand.
Crate files are unpacked into CRATES_ROOT.  Note that crate files are not
verified automatically as part of theunpackoperation.An archive file uses the directory structure of CRATES_ROOT for crate files and
the default on-disk location for the Git, and it places the Git bundle file into
the archive with the hard-coded pathgit/crates.io-index/origin.bundle.  For
example:git/crates.io-index/origin.bundle
crates/3/n/num/num-0.0.1.crate
crates/gl/ob/glob/glob-0.0.1.crate
crates/se/mv/semver/semver-0.1.0.crate
crates/uu/id/uuid/uuid-0.0.1.crateVerifyTheromt crate verifycommand checks the integrity of each downloaded crate
included in RANGE within INDEX.  Using the SHA256 hash values contained in INDEX
for each crate file, Romt ensures that the downloaded crate files have not been
corrupted and that no files in RANGE are missing.update,export, andimportFor each of the three main use cases, there is short command name that implies
the needed steps:updateis the same aspull download mark.  This is useful for the
laptop scenario.exportis the same aspull download pack mark.  This is useful for the
Export machine in the disconnected network scenario.importis the same asunpack pull verify mark.  This is useful for the
Import machine in the disconnected network scenario.Listing downloaded crate filesTheromt crate listcommand prints the filename for each crate
included in RANGE within INDEX, independent of whether those crate files have
been downloaded.For example, to see what new crates are available, firstpullthe latest
INDEX and thenlist:romtcratepulllistSample output might be:pull...
list...
gc-0.3.4.crate
brs-0.2.0.crate
cxx-0.3.1.crate
irc-0.14.0.crate
scd-0.1.3.crate
[...]cratescenariosFor the laptop scenario, only theupdatecommand is needed, after which
crates will be available for serving viaromt serve(or other means).  For
example, to download the latest crates:romtcrateupdateFor the disconnected network scenario, crate versions are downloaded and packed
on an Internet-connected Export machine, then unpacked on an Import machine,
e.g.:On the Export machine:First, download the latest crates and pack them intocrates.tar.gz:romtcrateexportTransfer the resultingcrates.tar.gzfile onto the Import machine.On the Import machine:Unpack the archive:romtcrateimportserveoperationTheserveoperation runs a local HTTP server exposing toolchain, rustup, and
crate artifacts.serveURLBy default,romt servelistens at the following URL:http://localhost:8000To usehttp://ADDR:PORT, use the switches--bindADDRand/or--portPORT.servedirectory layoutromt serveexpects the current working directory ($PWD) to contain all
artifacts being served.  Artifacts must be laid out in their default locations
described elsewhere, as follows:$PWD/
  dist/
  rustup/
  crates/
  git/
    crates.io-index/URLs of the formhttp://ADDR:PORT/{path}generally map directly to$PWD/{path}; exceptions are noted below.URLs with paths below/crates/are expected to be of the following form:http://ADDR:PORT/crates/{crate}/{crate}-{version}.crateromt servewill rewrite the URL to insert the expected{prefix}used in
CRATES_ROOT, effectively transforming the URLs to:http://ADDR:PORT/crates/{prefix}/{crate}/{crate}-{version}.crateURLs with paths below/git/refer to Git repositories.  Romt usesgit-http-backendas distributed with Git to serve these repositories.
For this purpose,romt serveuses acgi-bin/directory in the current
working directory to interface via CGI withgit-http-backend.Upon launchingromt serve, Romt searches for one of the following files incgi-bin/(depending on the platform):On Windows:git-http-backend.bat
git-http-backend.exeOn non-Windows:git-http-backend.sh
git-http-backendIf found, Romt will use that file for serving Git repositories via CGI.  If not
found, Romt will look in known locations for thegit-http-backendexecutable
and create a platform-dependent wrapper script incgi-bin/to invoke the
executable; the script is namedgit-http-backend.baton Windows andgit-http-backend.shon non-Windows.Currently, Romt probes for the backend in these hard-coded locations (depending
on the platform):On Windows:C:/ProgramFiles/Git/mingw64/libexec/git-core/git-http-backend.exeOn non-Windows:/usr/lib/git-core/git-http-backend(typical Linux)/usr/libexec/git-core/git-http-backend(Alpine Linux)To manually setup the Git backend, create a script file incgi-bin/with
contents similar to these examples (depending on platform):On Windows, createcgi-bin/git-http-backend.batwith contents:@echo off
"C:\Program Files\Git\mingw64\libexec\git-core\git-http-backend.exe"On non-Windows, createcgi-bin/git-http-backend.shwith contents:#!/bin/sh
exec '/usr/lib/git-core/git-http-backend'Then make the script executable:chmod+xcgi-bin/git-http-backend.shnginx configurationRust artifacts may optionally be served via the nginx web server.  A simple
example for Ubuntu Linux is shown below.  If you change host or port values
below, configure the index repository via:
.. code-block:: shromt crate config –server-url <SERVER_URL>Below is a sample nginx configuration.Place the following content into/etc/nginx/sites-available/rust.  Make
adjustments as indicated by eachTODO.  These instructions assume crates
are stored using lowercase prefixes; if using mixed-case prefixes, adjust as
directed by theTODOcomments:server {
  listen 8000 default_server;
  listen [::]:8000 default_server;

  # TODO: Change to absolute path to mirror directory:
  root /ABSOLUTE/PATH/TO/mirror;

  server_name _;

  location / {
    autoindex on;
  }

  # Support serving of Git repositories via git-http-backend.
  location ~ /git(/.*) {

    # TODO: Change to absolute path to mirror/git directory:
    fastcgi_param GIT_PROJECT_ROOT    /ABSOLUTE/PATH/TO/mirror/git;

    include       fastcgi_params;
    fastcgi_pass  unix:/var/run/fcgiwrap.socket;
    fastcgi_param SCRIPT_FILENAME     /usr/lib/git-core/git-http-backend;
    fastcgi_param GIT_HTTP_EXPORT_ALL "";
    fastcgi_param PATH_INFO           $1;
  }

  # Rewrite URLs like /crates/{crate}/{crate}-{version}.crate to use
  # a prefix based on the crate name.  Special cases for crate names
  # with 1, 2, 3, and 4-or-more characters:
  #   a/a-{version}.crate         -> 1/a/a-{version}.crate
  #   ab/ab-{version}.crate       -> 2/aa/ab-{version}.crate
  #   abc/abc-{version}.crate     -> 3/a/abc/abc-{version}.crate
  #   abcd*/abcd*-{version}.crate -> ab/cd/abcd*-{version}.crate

  # TODO: Comment out this line for mixed-case crate prefixes:
  rewrite "^/crates/.*$" "$crates_uri"  last;

  # TODO: Uncomment these four lines for mixed-case crate prefixes:
  # rewrite "^/crates/([^/])/([^/]+)$"                     "/crates/1/$1/$2"  last;
  # rewrite "^/crates/([^/]{2})/([^/]+)$"                  "/crates/2/$1/$2"  last;
  # rewrite "^/crates/([^/])([^/]{2})/([^/]+)$"            "/crates/3/$1/$1$2/$3"  last;
  # rewrite "^/crates/([^/]{2})([^/]{2})([^/]*)/([^/]+)$"  "/crates/$1/$2/$1$2$3/$4" last;

}Serving crates with lowercase prefixes requires Perl support in nginx (on
Ubuntu, this requires the packagenginx-extrasinstead ofnginx-full);
Perl support is not required for mixed-case prefixes.  To serve crates with
lowercase prefixes, create the file/etc/nginx/conf.d/perl.confwith the
below contents:# Reference: https://nginx.org/en/docs/http/ngx_http_perl_module.html
# Include the perl module
perl_modules perl/lib;

# The variable `$crates_uri` will be computed by the Perl subroutine
# below, adding a lowercase prefix as required based on the crate name.

perl_set $crates_uri 'sub {
    my $r = shift;
    my $uri = $r->uri;
    # Remove all newline characters to avoid CRLF injection vulnerability
    # (https://stackoverflow.com/questions/3666003/how-i-can-translate-uppercase-to-lowercase-letters-in-a-rewrite-rule-in-nginx-we/68054489#68054489):
    $uri =~ s/\R//g;

    if ($uri =~ m@^/crates/([^/])/([^/]+)$@) {
        $uri = "/crates/1/" . "$1/$2";
    } elsif ($uri =~ m@^/crates/([^/]{2})/([^/]+)$@) {
        $uri = "/crates/2/" . "$1/$2";
    } elsif ($uri =~ m@^/crates/([^/])([^/]{2})/([^/]+)$@) {
        $uri = lc("/crates/3/$1/") . "$1$2/$3";
    } elsif ($uri =~ m@^/crates/([^/]{2})([^/]{2})([^/]*)/([^/]+)$@) {
        $uri = lc("/crates/$1/$2/") . "$1$2$3/$4";
    }
    return $uri;
}';Activate therustsite via:ln -s /etc/nginx/sites-available/rust /etc/nginx/sites-enabled/Amazon S3 storageCurrently static artifacts hosted on Rust CDNs are served via Amazon S3 buckets.
At times directly accessing the bucket can be helpful.A helpful command-line tool for use with S3 buckets isawscli:https://github.com/aws/aws-cliRust https URLs map to S3 bucket URLs as follows:https://static.rust-lang.org-> s3://static-rust-lang-orghttps://static.crates.io-> s3://crates-ioNote: unfortunately, the “list” privilege is disabled for thecrates-iobucket.Here are some common operations on S3 buckets:List files beginning with PREFIX:awss3ls--no-sign-requests3://BUCKET_NAME/PREFIXAdd--recursiveflag to recurse into subdirectories.Download a file:awss3cp--no-sign-requests3://BUCKET_NAME/path/filelocal_fileExamples:List channel files for toolchain for 2020-04-30:awss3ls--no-sign-requests3://static-rust-lang-org/dist/2020-04-30/chanwith output:2020-04-29 20:23:44         10 channel-rust-nightly-date.txt
2020-04-29 20:23:44        833 channel-rust-nightly-date.txt.asc
2020-04-29 20:23:44         96 channel-rust-nightly-date.txt.sha256
2020-04-29 20:23:44         40 channel-rust-nightly-git-commit-hash.txt
...Listrustupversions:awss3ls--no-sign-requests3://static-rust-lang-org/rustup/archive/with output:PRE 0.2.0/
PRE 0.3.0/
PRE 0.4.0/
...Downloadserde-1.0.99.crate:awss3cp--no-sign-requests3://crates-io/crates/serde/serde-1.0.99.crate.This is functionally equivalent to:curl-Ohttps://static.crates.io/crates/serde/serde-1.0.99.crateTroubleshootingProxy server troubleshootingThe author has not tested Romt with a proxy server, but user feedback indicates
it’s possible (seehttps://github.com/drmikehenry/romt/issues/10).  Thehttpxlibrary’s support for proxying is documented at:https://www.python-httpx.org/advanced/#http-proxyinghttpxunderstands several environment variables (documented at the page
above) that may be used to influence proxy operation.  In addition,httpxhas information about debugging proxy-related issues at:https://www.python-httpx.org/contributing/#development-proxy-setupAlso,httpxcan produce more debugging information by setting the
environment variableHTTPX_LOG_LEVELtotrace(as documented athttps://www.python-httpx.org/environment_variables/).  As a sample invocation on
Linux:HTTPX_LOG_LEVEL=trace romt toolchain -v -s nightly -t all fetch-manifestDownload timeoutsRomt 0.3.0 added support for simultaneous downloading based on thehttpxlibrary; this came with a a default timeout of five seconds which can lead toConnectTimeoutorReadTimeouterrors depending on choice of--num-jobsand network characteristics (seehttps://github.com/drmikehenry/romt/issues/16).Romt 0.4.0 adds a--timeoutswitch to control this timeout, and changed the
default value to sixty seconds.  If timeouts are still occurring, use a larger
timeout value (or use--timeout0to disable timeouts altogether).Reference“Downloading all the crates on crates.io” provides good reference information
on mirroring Rust artifacts:https://www.pietroalbini.org/blog/downloading-crates-io/More information on Rust checksumming, signatures, etc., can be found at:https://internals.rust-lang.org/t/future-updates-to-the-rustup-distribution-format/4196Information on the “rustup” project:https://github.com/rust-lang/rustup