mercurial/helptext/subrepos.txt
author Manuel Jacob <me@manueljacob.de>
Mon, 11 Jul 2022 01:51:20 +0200
branchstable
changeset 49378 094a5fa3cf52
parent 43632 2e017696181f
permissions -rw-r--r--
procutil: make stream detection in make_line_buffered more correct and strict In make_line_buffered(), we don’t want to wrap the stream if we know that lines get flushed to the underlying raw stream already. Previously, the heuristic was too optimistic. It assumed that any stream which is not an instance of io.BufferedIOBase doesn’t need wrapping. However, there are buffered streams that aren’t instances of io.BufferedIOBase, like Mercurial’s own winstdout. The new logic is different in two ways: First, only for the check, if unwraps any combination of WriteAllWrapper and winstdout. Second, it skips wrapping the stream only if it is an instance of io.RawIOBase (or already wrapped). If it is an instance of io.BufferedIOBase, it gets wrapped. In any other case, the function raises an exception. This ensures that, if an unknown stream is passed or we add another wrapper in the future, we don’t wrap the stream if it’s already line buffered or not wrap the stream if it’s not line buffered. In fact, this was already helpful during development of this change. Without it, I possibly would have forgot that WriteAllWrapper needs to be ignored for the check, leading to unnecessary wrapping if stdout is unbuffered. The alternative would have been to always wrap unknown streams. However, I don’t think that anyone would benefit from being less strict. We can expect streams from the standard library to be subclassing either io.RawIOBase or io.BufferedIOBase, so running Mercurial in the standard way should not regress by this change. Py2exe might replace sys.stdout and sys.stderr, but that currently breaks Mercurial anyway and also these streams don’t claim to be interactive, so this function is not called for them.

Subrepositories let you nest external repositories or projects into a
parent Mercurial repository, and make commands operate on them as a
group.

Mercurial currently supports Mercurial, Git, and Subversion
subrepositories.

Subrepositories are made of three components:

1. Nested repository checkouts. They can appear anywhere in the
   parent working directory.

2. Nested repository references. They are defined in ``.hgsub``, which
   should be placed in the root of working directory, and
   tell where the subrepository checkouts come from. Mercurial
   subrepositories are referenced like::

     path/to/nested = https://example.com/nested/repo/path

   Git and Subversion subrepos are also supported::

     path/to/nested = [git]git://example.com/nested/repo/path
     path/to/nested = [svn]https://example.com/nested/trunk/path

   where ``path/to/nested`` is the checkout location relatively to the
   parent Mercurial root, and ``https://example.com/nested/repo/path``
   is the source repository path. The source can also reference a
   filesystem path.

   Note that ``.hgsub`` does not exist by default in Mercurial
   repositories, you have to create and add it to the parent
   repository before using subrepositories.

3. Nested repository states. They are defined in ``.hgsubstate``, which
   is placed in the root of working directory, and
   capture whatever information is required to restore the
   subrepositories to the state they were committed in a parent
   repository changeset. Mercurial automatically record the nested
   repositories states when committing in the parent repository.

   .. note::

      The ``.hgsubstate`` file should not be edited manually.


Adding a Subrepository
======================

If ``.hgsub`` does not exist, create it and add it to the parent
repository. Clone or checkout the external projects where you want it
to live in the parent repository. Edit ``.hgsub`` and add the
subrepository entry as described above. At this point, the
subrepository is tracked and the next commit will record its state in
``.hgsubstate`` and bind it to the committed changeset.

Synchronizing a Subrepository
=============================

Subrepos do not automatically track the latest changeset of their
sources. Instead, they are updated to the changeset that corresponds
with the changeset checked out in the top-level changeset. This is so
developers always get a consistent set of compatible code and
libraries when they update.

Thus, updating subrepos is a manual process. Simply check out target
subrepo at the desired revision, test in the top-level repo, then
commit in the parent repository to record the new combination.

Deleting a Subrepository
========================

To remove a subrepository from the parent repository, delete its
reference from ``.hgsub``, then remove its files.

Interaction with Mercurial Commands
===================================

:add: add does not recurse in subrepos unless -S/--subrepos is
    specified.  However, if you specify the full path of a file in a
    subrepo, it will be added even without -S/--subrepos specified.
    Subversion subrepositories are currently silently
    ignored.

:addremove: addremove does not recurse into subrepos unless
    -S/--subrepos is specified.  However, if you specify the full
    path of a directory in a subrepo, addremove will be performed on
    it even without -S/--subrepos being specified.  Git and
    Subversion subrepositories will print a warning and continue.

:archive: archive does not recurse in subrepositories unless
    -S/--subrepos is specified.

:cat: Git subrepositories only support exact file matches.
    Subversion subrepositories are currently ignored.

:commit: commit creates a consistent snapshot of the state of the
    entire project and its subrepositories. If any subrepositories
    have been modified, Mercurial will abort.  Mercurial can be made
    to instead commit all modified subrepositories by specifying
    -S/--subrepos, or setting "ui.commitsubrepos=True" in a
    configuration file (see :hg:`help config`).  After there are no
    longer any modified subrepositories, it records their state and
    finally commits it in the parent repository.  The --addremove
    option also honors the -S/--subrepos option.  However, Git and
    Subversion subrepositories will print a warning and abort.

:diff: diff does not recurse in subrepos unless -S/--subrepos is
    specified.  However, if you specify the full path of a file or
    directory in a subrepo, it will be diffed even without
    -S/--subrepos being specified.  Subversion subrepositories are
    currently silently ignored.

:files: files does not recurse into subrepos unless -S/--subrepos is
    specified.  However, if you specify the full path of a file or
    directory in a subrepo, it will be displayed even without
    -S/--subrepos being specified.  Git and Subversion subrepositories
    are currently silently ignored.

:forget: forget currently only handles exact file matches in subrepos.
    Git and Subversion subrepositories are currently silently ignored.

:incoming: incoming does not recurse in subrepos unless -S/--subrepos
    is specified. Git and Subversion subrepositories are currently
    silently ignored.

:outgoing: outgoing does not recurse in subrepos unless -S/--subrepos
    is specified. Git and Subversion subrepositories are currently
    silently ignored.

:pull: pull is not recursive since it is not clear what to pull prior
    to running :hg:`update`. Listing and retrieving all
    subrepositories changes referenced by the parent repository pulled
    changesets is expensive at best, impossible in the Subversion
    case.

:push: Mercurial will automatically push all subrepositories first
    when the parent repository is being pushed. This ensures new
    subrepository changes are available when referenced by top-level
    repositories.  Push is a no-op for Subversion subrepositories.

:serve: serve does not recurse into subrepositories unless
    -S/--subrepos is specified.  Git and Subversion subrepositories
    are currently silently ignored.

:status: status does not recurse into subrepositories unless
    -S/--subrepos is specified. Subrepository changes are displayed as
    regular Mercurial changes on the subrepository
    elements. Subversion subrepositories are currently silently
    ignored.

:remove: remove does not recurse into subrepositories unless
    -S/--subrepos is specified.  However, if you specify a file or
    directory path in a subrepo, it will be removed even without
    -S/--subrepos.  Git and Subversion subrepositories are currently
    silently ignored.

:update: update restores the subrepos in the state they were
    originally committed in target changeset. If the recorded
    changeset is not available in the current subrepository, Mercurial
    will pull it in first before updating.  This means that updating
    can require network access when using subrepositories.

Remapping Subrepositories Sources
=================================

A subrepository source location may change during a project life,
invalidating references stored in the parent repository history. To
fix this, rewriting rules can be defined in parent repository ``hgrc``
file or in Mercurial configuration. See the ``[subpaths]`` section in
hgrc(5) for more details.