On git there is an easy way to configure the client to use different servers and protocols, which is great because it allows you to move repositories without breaking complex build scripts.
git config --global url.https://oldserver.com/aaa/.insteadOf git://newserver.com/bbb/ccc/
I am looking for a similar feature to mercurial.... anyone?
The closest alternatives that Mercurial offers are the paths config section and the schemes extension, which enables a schemes config section. Here, paths allows you to define aliases for URLs, while schemes allows you to define aliases for URL prefixes.
For example, if you add the following to your .hgrc or pass the config option on the command line:
[paths]
foo = ssh://example.com/path/to/real/foo
Then you can do:
hg clone foo
hg push foo
hg pull foo
etc.
Similarly, you can enable the scheme "extension" (it's actually built-in, you don't need to install anything, just turn it on) and use that to define a prefix:
[extensions]
scheme=
[schemes]
ourstuff = ssh://example.com/path/to/reporoot
And then you can do:
hg clone ourstuff://foo
hg push ourstuff://foo
hg pull ourstuff://foo
etc.
This is useful if you have multiple repositories underneath the same location. Note that you can also use paths and schemes combined, e.g.
[extensions]
scheme=
[schemes]
ourstuff = ssh://example.com/path/to/reporoot
[paths]
foo = ourstuff://foo
Related
I need a mercurail template/keyword "hostname" to get the name (or IP) of the computer where the repo is located. as far as i read the wiki, namely "Chapter 11. Customizing the output of Mercurial", hg help templates, and the web, I think it should be similar to the date keyword, dynamicly expanded. How can i define my own template/keyword?
Thank you verry much
The following extension should do the trick:
from mercurial import templatekw
testedwith = "3.5"
_ipname = None
def showipname(repo, ctx, templ, **args):
""":ipname: String. The hostname of the machine that the repository
resides on."""
import socket
global _ipname
if not _ipname:
_ipname = socket.gethostname()
return _ipname
def uisetup(ui):
templatekw.keywords["ipname"] = showipname
Then use (say):
hg log -r . -T '{node|short} at {ipname}\n'
Note that the value of socket.gethostname() may depend on your internet connectivity. If you need the value in /etc/hostname or something else that identifies your machine, use that method instead.
To use an extension, put it in a file, say ipnametempl.py somewhere, then add the following lines to your .hgrc:
[extensions]
ipnametempl=/path/to/ipnametempl.py
This can be either your user/global hgrc or the .hg/hgrc in your repository (the latter if you only want to enable it for a specific repository). See hg help hgrc to find out where the user/global hgrc files are on your system.
Either the repository is local to your machine (then you can get the absolute path via hg root) and query the name via the normal system tools. You can embed those also in your templates:
$ hg log -r. --template="{branch}-{rev} from $(hostname) running debian $(cat /etc/debian_version)"
trunk-22248 from MYHOSTNAME running debian 8.2
Or you know already the URL (remote path) in order to operate with it as you need to specify it as argument to hg pull/clone/outgoing/incoming
If the remote URL is not explicitly specified on the command line it is specified in your .hgrc in the [path] section. When there is a remote repository at all, then usually a default = URL is defined there.
If you need the URL printed, then install hooks for clone, pull and push (and maybe outgoing and incoming) which prints the $URL as available in those hooks - or maybe just the changegroup hook. Check http://hgbook.red-bean.com/read/handling-repository-events-with-hooks.html#sec:hook:changegroup and hg help config.
Is there any Mercurial command or Python API that could yield the repo name? This will help developing cross-repo scripts.
The only related solution that I found is to parse the .hg/hgrc [paths] section 'default' config option.
[paths]
default = ssh://server//path/tools
There must be a more elegant solution, I think.
There is no real concept of a "repository name" in Mercurial (a repository doesn't "know" or care about its own name). I think you mean "last past component of the default pull path"?
If so, then parsing the output of hg path default would be the most direct way to get that information.
However, you should note that the default path can (and often is) changed: think of cloning a local clone time for testing:
$ hg clone http://server/lib-foo
$ hg clone lib-foo lib-foo-test
$ hg clone lib-foo-test lib-foo-more-testing
The lib-foo-more-testing clone has a default push path back to lib-foo-test.
This means that parsing hg paths default wont be much more reliable than using basename $(hg root) — both can be completely different from the (base)name of the repository that was originally cloned.
If what you really want is to get an "identity" for a repository, then you should instead use
$ hg log -r 0 --template "{node}"
The first changeset hash in a repository will normally uniquely identify the repository and it will be stable even when clones change names. (If a repository has two or more roots, then the zeroth changeset can in principle differ between clones. People will have to actively try to make it differ, though.)
If you want to get last segment of path for remote default alias, processing output of hg path default will be better choice
If you want to get local directory name of you mercurial repository, I haven't good solution, except checking code of Notify extension (in which, after some tricks, you can get project-name)
For our project, we have two repositories: Main and Automated Testing. In the Testing repository, we allow multiple heads, so one commonly used "hg push -f" when pushing to the Testing repository. But using "push -f" is a bad habit, as one may accidentally use this for other repositories, too.
So I am looking for some configuration option, preferably on the repository side, which allows pushing multiple heads without using -f -- does Mercurial provide such an option?
(I know that I can install a hook to an repository to prevent it being the target of a forced push, but I would like to get rid of the need to use -f altogether.)
A simple solution (unfortunately needed per-client) is to setup an alias in your ~/.hgrc as follows:
[alias]
testboardpush = push -f ssh://example.com/testboard
You can then use hg testboardpush to push your commits to the automated testing repository, instead of getting into the bad habbit of using push -f.
If you have multiple repositories with multiple testboard locations, you can instead setup your alias inside your ~/.hgrc file as follows:
[alias]
testboardpush = push -f testboard
And then for each HG repository's .hg/hgrc file, have the lines:
[paths]
testboard = ssh://example.com/testboard
With this setup, typing hg testboardpush will always push to the correct place for the particular HG repository you are currently working in (or fail with an error if the path hasn't been setup).
Unfortunately, it does not appear you can do this from the server side without a custom version of HG; in particular, my reading of the push implementation in the localrepo.py file of the HG sources indicates it unconditionally checks for new heads using discovery.checkheads (and aborts) unless the force argument is set.
We're trying to clone a Mercurial repository A where it references a subrepository B that's moved hosts. We'd like to update .hgsub in A to point to the new location of B, but it's a chicken and egg problem if we can't hg clone A in the first place.
Does anyone know how to work around this?
$ hg help subrepos
...
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.
$ man hgrc
...
subpaths
Defines subrepositories source locations rewriting rules of the form:
<pattern> = <replacement>
Where pattern is a regular expression matching the source and replacement is the replacement string used to
rewrite it. Groups can be matched in pattern and referenced in replacements. For instance:
http://server/(.*)-hg/ = http://hg.server/\1/
rewrites http://server/foo-hg/ into http://hg.server/foo/.
All patterns are applied in definition order.
...
So, you can do it in .hgrc in a [subpaths] section.
First note that clone is init + pull + update and that subrepo cloning is part of the update step, not the pull step. This means that you can avoid clone failing simply by skipping the update step:
$ hg clone -U <url>
Now the problem is reduced to "how do I update to a revision with a problematic .hgsub/.hgsubstate file?" There are two possibilities here:
remap subrepos using the [subpaths] feature (see hg help subrepo and hg help config)
manual update and repair
A "manual update" can be done like this:
$ hg revert -a -r default -X problematic-file
[adding a bunch of files]
$ hg debugrebuildstate -r default
Now you can manually fix-up your subrepos and .hgsub and commit. Be sure to test your fix with a clone before pushing it.
Also, see this mailing list thread on the topic: http://markmail.org/thread/ktxd2rsm7avkexzr
It could be easier to tamper with DNS as a quick workaround (e.g. hosts file on Windows) and then fix .hgsub.
I have a Mercurial repository containing a handful of related projects. I want to branch just one of these projects to work on it elsewhere.
Is cloning just part of a repository possible, and is that the right way to achieve this?
What you want is a narrow or partial clone, but this is unfortunately not yet supported.
If you already have a big repository and you realize that it would make sense to split it into several smaller repositories, then you can use the convert extension to do a Mercurial to Mercurial conversion. Note that this creates a new repository foo and you cannot push/pull between your-big-repo and foo.
The convert extension is not enabled by default so add the following to your repo's hgrc file or your mercurial.ini file:
[extensions]
hgext.convert=
Then create a map.txt file with
include "libs/foo"
rename "libs/foo" .
(note you can use forward slashes even on Windows) and run
$ hg convert --filemap map.txt your-big-repo foo
That will make foo a repository with the full history of the libs/foo folder from your-big-repo.
If you want to delete all evidence of foo from your-big-repo you can make another conversion where you use exclude libs/foo to get rid of the directory.
When you have several repositories like that and you want to use them as a whole, then you should look at subrepositories. This feature lets you include other repositories in a checkout — similarly to how svn:externals work. Please follow the recommendations on that wiki page.
Instead of doing a partial clone, you can use the Convert Extension to split your repo into more than one repo by sub repository.
Specifically, see the section, Converting from Mercurial:
It's also useful to filter Mercurial repositories to get subsets of an existing one. For example to transform a subdirectory subfoo of a repository foo into a repository with its own life (while keeping its full history), do the following:
$ echo include subfoo > /tmp/myfilemap
$ echo rename subfoo . >> /tmp/myfilemap
$ hg convert --filemap /tmp/myfilemap /path/to/repo/foo /tmp/mysubfoo-repo
I've stumbled accross this issue and found one way to do it: Using symlinks (Linux only unfortunately)
For example, if you only need /project in the repository, on your computer clone the repo in another folder, then use ln -s /repo/location/ project. Mercurial will handle it
(Late 2016) Mainline Mercurial still doesn't package support for "narrow clones" but there are third party extensions that tackle the problem in different ways.
If you can cope with just a narrow checkout (aka "sparse checkout" or "partial checkout by file path") then Facebook's sparse.py extension from the hg-experimental repository (look inside the hgext3rd/ directory) may be workable. In this scenario, you still clone the full history (thus the .hg directory is no smaller) but your working directory only shows/acts on a subset of the full repository.
Alternatively Google have created a NarrowHG extension that does narrow cloning (aka "partial cloning by file path"). You will need to be in control of the server, the client and be willing to use experimental features but it really does restrict the clone's copied history in .hg to a subset of what was in the original repository.
(2019) The sparse extension was merged into Mercurial 4.3 as the experimental sparse extension. The NarrowHG extension was merged into Mercurial 4.6 as the hgext.narrow extension.
It is not possible, hg clone will clone the whole repository.
You can take a look a the sub-repository extension that allows you to have repositories inside a repository, which might match your needs.
This is straight forward with the Convert extension.