How to display hg status with full paths instead of relative ones? - mercurial

I want to run hg status and display the changed files with full path?
Why? because I want to display changes to 3 different repositories and by default hg displays them relative to the repository root.

Nothing in the hg status man page suggests Mercurial directly supports that.
How about a bit of sed magic?
$ pwd
/var/www/mysite
$ hg st
A static/logo.png
M static/style.css
? temp.txt
$ hg st | sed -e "s~^\(.\) ~\1 ${PWD}/~g"
A /var/www/mysite/static/logo.png
M /var/www/mysite/static/style.css
? /var/www/mysite/temp.txt
You can use shell aliases (described in the manual) to make Mercurial do this instead of the regular hg st.

Inspired by #Helgi's answer here's a variation using PowerShell:
hg status | % { $_ -replace '^([^ ]+ )(.+)$', ('$1' + $(Get-Location) + '\$2') }

Related

Show if the revision of subrepos changed, or if they are dirty

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.

Sort hg status by date

Im looking for a convenient way to sort the ouput of
hg status
to see the newest file at top.
Here is a possible solution that will only work in Linux-like environments (I am trying it in Windows using MSYS). You could use ls to list files sorted by time, passing it the output of hg status:
$ hg st
M modified.txt
A added.txt
R removed.txt
? unknown.txt
$ ls -t1 `hg st -n -a -m -u`
unknown.txt
modified.txt
added.txt
Using this method you lose the MAR?... status, but it shows the files that are changed, added, or are untracked, sorted by modification time. However, it does kind of rely on your allowed parameters to ls.
Effectively you're using the backquoted mercurial command to provide a list of filenames to ls, which will do the sorting for you. Don't think there's a simple way to do this in vanilla Windows. Possibly by using a for loop?
First, create a file with this content:
changeset = "{files}"
file = "{file}\n"
Let's say you call it sorted.txt and put it in your home directory. Then you can give this command:
hg -q outgoing --style ~/sorted.txt | sort -u

Is there a way to see the most recent Mercurial revision for each file in a directory?

When you do hg log on a file, only the revisions that underwent changes are listed. I'd like to see what the most recent revision for all of the files in a directory is. (Think hg blame at a file level rather than a line level.)
I had thought that hg log -l 1 * might work, but it just shows the most recent revision across all of the files.
Here's the kind of output I'd like to see:
> hg blame --files
foo: 15
bar: 2
baz: 15
README: 1
Another alternative is to use a combination of hg status and hg log, like this:
for FILE in $(hg status -nA); do
hg log -l1 --template '{rev}\t' "$FILE"
echo $FILE
done
I suspect that if you want to use hg directly to do this, you'll need to write an extension (but I'm by no means an expert here). But would something like this work, if you're willing to use a script?
for x in *; do
highest=`hg blame "$x" 2>/dev/null | cut -d : -f 1 | sort -nr | head -n1`
if [ "$highest" ]; then echo "$x: $highest" ; fi
done
The obvious downside here is that this is pretty slow.

Is there an equivalent to git's "describe" function for Mercurial?

I'm currently adding packaging to a something that is maintained in Mercurial. Currently the version is defined in the Makefile. I would like to change this so I can build daily packages or properly versioned packages.
Git provides a use "describe" function that can give you a description of the closest tagged build and current revision. For example if I run this in the kernel:
git describe HEAD
GIT returns:
v3.0-rc7-68-g51414d4
telling me that the revision is later than v3.0-rc7, with a git commitish of 51414d4
Is there something similar I can do in Mercurial?
Maybe something like this?
hg log -r . --template '{latesttag}-{latesttagdistance}-{node|short}\n'
Of course you should make an alias for that with AliasExtension.
Note however, unlike "git describe", this command will always show the "latesttagdistance" and "node|short" parts, instead of omitting them when latesttagdistance is 0.
This is a close emulation of git describe:
hg log -r . -T "{latesttag}{sub('^-0-.*', '', '-{latesttagdistance}-m{node|short}')}"
The {sub(...)} function ensures that a working copy that's exactly at tag v0.1.0 will show up as v0.1.0 and not v0.1.0-0-m123456789abc.
Note that the m before the hash is for mercurial, similar to the way git describe uses a g for git.
For convenience, create an alias by adding the following to your ~/.hgrc:
[alias]
describe = log -r . -T "{latesttag}{sub('^-0-.*', '', '-{latesttagdistance}-m{node|short}')}"
Then use the alias by simply typing hg describe.
If you'd like to emulate git describe --dirty, things get even messier – but you can still hide it all in an hg alias:
[alias]
describe = !
dirtymark=;
case " $1 " in " --dirty ") dirtymark=-dirty; ;; esac;
echo $($HG log -r . --template "{latesttag}-{latesttagdistance}-m")$($HG id -i) |
sed -r -e "s/\+\$/${dirtymark}/" -e 's/-0-m[[:xdigit:]]+//'
Now running hg describe --dirty will produce strings like:
v0.1.0
v0.1.0-dirty
v0.1.0-1-mf6caaa650816
v0.1.0-1-mf6caaa650816-dirty
Omitting the --dirty option means that you'll never get a -dirty suffix like (2) and (4), even when the working copy contains uncommitted changes.

In Mercurial (hg), how do you see a list of files that will be pushed if an "hg push" is issued?

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.