Is there a command that can be constructed to list all the subrepositories of a Mercurial repository? Something like what the git submodule command does? (I am attempting to process them programmatically.)
As far as I can tell, the best option currently is to write a parser that processes .hgsub (dealing with the various optional sections like [subpaths]) and that seems much less optimal than relying on hg to parse the file. But I can't find a command that does it.
Is there one?
You can use the onsub extension. The repository linked in the Mercurial wiki disappeared, but I found https://bitbucket.org/kvaster/onsub which looks maintained.
I created a mini repo with two subrepos as follows:
$ find . -type d -name '.hg'
.hg <== outer repo
nested/.hg <== subrepo
nested2/.hg <== subrepo
The corresponding .hgsub is very simple:
nested = nested
nested2 = nested2
Example 1:
$ hg --config extensions.onsub=~/src/onsub/onsub.py onsub --verbose "hg status"
executing 'hg status' in nested
executing 'hg status' in nested2
Example 2:
$ hg --config extensions.onsub=~/src/onsub/onsub.py onsub "hg root"
/Users/hello/tmp/foo/nested
/Users/hello/tmp/foo/nested2
Example 3: using environment variables provided by onsub:
$ hg --config extensions.onsub=~/src/onsub/onsub.py onsub "echo; set | grep HG_"
HG_REPO=/Users/hello/tmp/foo
HG_SUBPATH=nested
HG_SUBURL=nested
HG_REPO=/Users/hello/tmp/foo
HG_SUBPATH=nested2
HG_SUBURL=nested2
As usual, you can get help with:
hg --config extensions.onsub=~/src/onsub/onsub.py help onsub
The --config ... on the command-line shows how to enable an extension without editing your $HOME/.hgrc.
Instead of parsing .hgsub I'd parse .hgsubstate instead - it is guaranteed to have one line per subrepository instead:
for i in $(cat .hgsubstate | cut -d\ -f2); do echo $i; done
Related
I have a mercurial repository (main repo) with several sub repositories.
I need a mercurial command to show if the revision of a sub repo changed (including information on old and new revision) in the working copy or if the sub repo state is dirty.
How can I do this?
Most mercurial commands accept the -S or --subrepos flag. Thus by calling hg st -S you get a list of all changed files which include those in the sub-repos, if their state differs from the state recorded in the .hgsubstate file:
$ cd opengfx/
$ hg st
$ hg id
10065545725a tip
$ cd ..
$ hg st -S
M opengfx/.hgtags
M opengfx/Makefile
A opengfx/lang/japanese.lng
$ cat .hgsubstate
785bc42adf236f077333c55c58490cce16367e92 opengfx
As to your wish to obtain the actual revisions, that's AFAIK not possible with one command. However you can always check the status of the individual sub-repos like above or can check them from the main repo by giving mercurial another path to operate on:
$ hg id -R opengfx
10065545725a tip
In order to get the status of each repo compared to what is required by the parent repo, I'd resort to some simple bash:
for i in $(cat .hgsubstate | cut -d\ -f2); do echo $i is at $(hg id -R $i) but parent requires $(cat .hgsubstate | grep $i | cut -d\ -f1); done
which gives output like
opengfx is at 10065545725a tip but parent requires 785bc42adf236f077333c55c58490cce16367e92
In a similar fashion you can also check whether the state is modified by using hg st instead of hg id.
I have a mercurial repo with subrepos (also mercurial). Imagine the situation where I have changed the subrepos and the main repo. Now I want to see the changes between several commits including the changes in the subrepos.
Is it possible?
I use TortoiseHG and diffmerge. In diffmerege calling for visual diff from TortoiseHg, I can't see the changes in the subrepos between several commits.
In the command line you can do the following. Let us say you want to see all the changes of a subrepo named example between the changesets (in the main repo) c608f6017bd7 and 72d284a44170.
In the main repo
hg diff -rc608f6017bd7:72d284a44170 .hgsubstate | grep example
will return the changesets of the subrepo example, something like:
-001fc0acef220bcd42898ef3932dee8330ea64c0 example
+77f9db4d51c4b483607178aba91c872b0adedf1e example
Now you can see the logs and the diffs of the subrepo changes with:
cd example
hg log -r001fc0acef220bcd42898ef3932dee8330ea64c0:77f9db4d51c4b483607178aba91c872b0adedf1e
hg diff -r001fc0acef220bcd42898ef3932dee8330ea64c0:77f9db4d51c4b483607178aba91c872b0adedf1e
If you need it often, you can create a bash script named sublog like:
#!/bin/bash
r=$(hg diff -r$1:$2 .hgsubstate | grep $3 | cut -c 2-41 | tr '\n' ':' | sed 's/:$//'; echo '')
cd $3
hg log -r:$r
and use it like:
sublog c608f6017bd7 72d284a44170 example
I can only tell you how to achieve it on the command line - but that is readily available with tortoiseHG, too:
Most commands can be made aware of subrepositories by using the -S or --subrepos flag. As such, in order to see the diff between two changesets X and Y, including those on all subrepositories, do at the main repository:
hg diff -S -rX:Y
Mind, of course, that it will not show a diff in the subrepositories if there was no change of the sub-repository version(s) committed to the main one.
With the versions of TortoiseHg I've used (which doesn't include the last few releases), I haven't seen a way of doing what you're asking about. There are a few options though:
you can type commands directly in the output log window in TortoiseHg, so you can do hg diff -S -rX:Y there.
Archive the versions of the parent repo which you want to diff to some directories (hg archive --repository <path-to-repo> -r <rev> -S -t files -- <outputfolderpath>, or in TortoiseHg, right-click the changeset, select Export -> Archive). Then use diffmerge on the archive directories. This is a bit tedious (especially if you want to diff many changesets), but you will get a "deep" visual diff.
I've looked for that in the manual, but I can't generate a patch for the last commit.
I tried
hg qnew patch_name
but it does only file with
# HG changeset patch
# Parent a6a8e225d16ff5970a8926ee8d24272a1c099f9c
I also tried
hg export tip
but it doesn't do anything. I committed the changes exactly.
How to generate a patch file with the last commit in?
The command to do this is export:
$ hg export -o FILE -r REV
It doesn't require redirection and will thus work correctly on any platform/shell.
Your hg export tip is the best way to do it, and the hg diff and hg log based answers are just lesser versions of the same. What exactly do you see/get when you type hg export tip? What does the output of hg log -p -r tip show?
The changeset tip is just means "the changeset that most recently arrived in my repository" which isn't as useful a concept as you might think, since hg pull and hg tag all create changesets too. If you really want the last thing you committed you'll need a more precise revspec.
Like so:
hg diff -r tip > tip.patch
You can use this command:
hg log -r tip -p > tip.patch
this will generate a patch for just that revision.
If you want to convert the latest commit to a patch file, use
hg qimport -r tip
This will replace the topmost regular commit with an applied MQ patch file.
To generate patches using "mq extensions" in mercurial, you can follow the below given steps. This will create a patch using mercurial:
1) Enabling mq extensions: Add the following lines to your hgrc file and save it.
[extensions]
mq =
2) Creating a patch using mq extensions: To create a patch using mq extensions you can do the following.
hg qnew -e -m "comment you want to enter" bug_name.patch
In the above command, -e flag is for editing the patch and -m flag is for adding a message to the patch.
3) Updating the patch: For updating the patch, you can use the following command when a patch is already applied.
hg qrefresh
I have a repo located at x:/projects/repo1. The working directory has been emptied using hg update null. I want to extract the latest version of some files from there to a local directory.
I tried this:
x:\projects\repo1> hg cat -o c:\sql\%s scripts\*.sql -r tip
I get this error:
scripts\*.sql: No such file in rev 14f07c26178b
The same command works fine if the working directory is not empty. Is there a good reason why this does not work? Or do you know another way of extract some files from there to a local directory?
The hg cat command is for single files. If you want multiple files use the hg archive command, which makes zipfiles or directories full of files. Here's your command:
x:\projects\repo1> hg archive --include scripts\*.sql -r tip c:\sql
It seems that hg cat doesn't support wildcard symbols in paths. So you should use the full file name:
hg cat -r tip scripts/foo.sql
When your working copy is up to date with the tip revision, your shell does wildcard substitution for you.
The hg manifest command also might be helpful for getting tracked file listings.
This answer is to your comment on Andrey's answer:
hg manifest takes a --rev argument that you can use to see the list of all files in your repository:
hg manifest --rev tip
To get the list of files matching a pattern at the tip, use:
hg stat --all --include *.sql --rev tip --no-status
hg stat -A -I *.sql --rev tip -n # using abbreviations.
From there you could redirect the output to a file and edit each line into a hg cat command like in your original question. It appears (to me, at least, having done some experimentation) that hg cat uses the contents of the working directory -- rather than the contents of the repository at the revision specified -- for glob-matching, so once you know the exact name of the file, you can hg cat it at any revision.
We can see all the changesets and the files involved using
hg outgoing -v
but the filenames are all scattered in the list of changesets.
Is there a way to just see a list of all the files that will go out if hg push is issued?
First, create a file with this content:
changeset = "{files}"
file = "{file}\n"
Let's say you call it out-style.txt and put it in your home directory. Then you can give this command:
hg -q outgoing --style ~/out-style.txt | sort -u
A somewhat under-appreciated feature: hg status can show information about changes in file status between arbitrary changesets. This can be used to get a list of files changed between revisions X and Y:
hg status --rev X:Y
In this case, we can use hg outgoing, to find the first outgoing changeset X and then do
hg status --rev X:
to see the files changes since revision X. You can combine this into a single line in your shell:
hg status --rev $(hg outgoing -q --template '{node}' -l 1):
I usually use
hg outgoing -v | grep files
It makes the listing shorter, but doesnt sort. But thus far I havent been in a situation where I want to push so much (and at the same time check the files) that its been a problem.
[Edit]
To do what you want:
Use cut to remove the files: part
For changesets with more than one touched file, use tr to put them on separate lines
Finally sort the resulting output with sort
Like so:
hg outgoing -v |grep files: |cut -c 14- |tr ' ' '\n' |sort -u
You can put this in ~/outgoingfiles.sh or something to have it nice and ready.
I use Torgoise Hg, which is a shell extension that has a "synchronize" view allowing you to see outgoing files before you push them. It's convenient for commits as well, and other things.
A simple hg out will also solve this.
It will list all committed but yet to push checkins.