MM is a tool to ease backing up a large number of repositories.
It currently supports
Its operation is made easier by these DVCS all having replication and
synchronization protocols baked into them and their clients. Because
of that MM did not have to invent anything new, it gets by just by
invoking the existing tools (
All management is done through a command line application with
integrated help, called
Beyond management MM is also capable of exposing the pool of backups
to the web. This is done by
mirror generating a static website which
can then be served by a web engine of the user's choice. This
TclSSG to be installed, expecting its main
application to be accessible under the name
It should be noted MM does not automatically perform repository
updates on its own. It expects to be invoked by some external
scheduler, for example
cron, for this.
Currently the only example of MM in use can be found at https://akupries.tclers.tk/r/tcl. This location collects and mirrors as many Tcl-related repositories as it can find.
Basics of operation
The basic command to add a single repository to the system is
mirror add <url>
MM will try to figure out the type of repository to mirror from the specified url, and further derive a name for the mirror set to hold the repository as well.
If it guesses wrong the options
--name can be used to
explicitly specify the correct values.
mirror add <url> --name <name> --vcs <vcs>
The set of version control systems supported by the installed
can be queried with
Going back to
add and its auto-detection of vcs type, the currently
employed heuristics (.i.e url patterns), are, in order:
As can be seen, the order does matter, and
fossil is the catch-all
The two main concepts here are the repository, identified by its url, and the mirror set, identified by its name.
mirror add always places the specified repository into its own
mirror set the latter can contain more than one repository, while
each repository always belongs to only one mirror set.
Mirror sets are there to group related repositories together. The
command to coalesce mirror sets into one after adding repositories is
The action comes at a price, and with restrictions. All repositories in a mirror set for the same type VCS will share the local backing store.
For fossil repositories MM can and does use the asociated
projectcode to detect attempts at merging unrelated repositories,
and rejects such. For git(hub) no such information exists, and the
only warning will be the message
no common ancestors found when
updating such a mirror set. For mercurial the situation is similar.
On the positive side placing related repositories together reduces the amount of disk space required.
Quick access to content
An important structure maintained by MM is the rolodex.
It is a stack which is updated whenever repositories are added or removed, and mirror sets merged and split. This makes it easy to quickly reference repositories which were recently worked on.
The last and previously used repositories are accessible through the
@p short hands. The repositories further down the history
are accessible via
The new rolodex's contents are always shown after a command changing
it completes, and can be explicitly queried with
Search operations like
mirror list <substring> write their results
to the rolodex as well.
Note, the rolodex is of limited size. The initial default is 20
entries. This configuration can be queried and changed with the
mirror limit command.
The same limit
L also applies to the output of the
command when not used to search for content. In that case it shows
L entries per invokation, and a series of invokations cycles
through the entire list of repositories.
Updating the mirror
The command to update the mirror is
mirror update (sic!).
To prevent overloading both the local machine and the remote locations each invokation of this command will only update a subset of the known mirror sets. To this end MM manages an internal queue new mirror sets are added to, and mirror sets to update are taken from from the front. When the queue runs empty it is simply refilled again with all the mirror sets known at that time.
The current state of the queue is accessible via
with the mirror sets to be taken by the next invokation of
update at the top and marked.
The default is to update 5 mirror sets per invokation. This
configuration can be queried and changed with the
Together with being driven by the liks of
cron this keeps the local
load low, and distributes the remote load over a larger time interval
as well, with cron interval and number of sets taken per cycle the
main knobs to regulate this.
merge are the only operations needed to add new
repositories, and manage their mirror sets, using them still will be
tedious when having to add a large batch.
To simply this case we have the command
mirror import. It takes a
simple text specifying repositories and their mirror sets in simple
markup and imports them all in one batch, performing all the necessary
The file format is line-oriented, with each non-comment line
specifying either a repository, or a mirror set. Comments start with a
#, U+0023) and run to the end of their line. Empty
lines are ignored.
The simplest possible import file looks like
R <vcs> <url> M <name>
and is equivalent to
mirror add <url> --name <name> --vcs <vcs>
To place more repositories into the mirror set
# A comment R <vcs1> <url1> R <vcs2> <url2> ... M <name>
Any number of repositories and mirror sets can be specified.
On the converse side of the above is
mirror export, which writes the
current state of repositories and mirror sets to
stdout, in a format
directly usable to
404 - No contact at this number
Given that MM is for the backup of remote repositories to protect against their loss, it is only right to handle the possibility of remote locations vanishing.
Such a sitation will actually not disturb the operation of
update, and if the loss is temporary the situation will resolve
itself when update comes back to the repository in question, and
simply pull more data from the other side.
However when the situation appears to be permanent then the manager might not wish to spend cycles and bandwidth on querying a repository which is gone. Yet the local backup should not be deleted either.
Thus we have
mirror disable and
mirror enable with which we can
take a repository out of the update rotation, or put it back in. A
repository in the rotation is called active, and inactive
... TODO ...