How to generate a clean patch from Mercurial? - mercurial

The diff command, even using git option, includes path prefixes commonly used on DCS:
--- a/file.ext
+++ b/file.ext
So applying such patches you should need to using -p1 instead of -p0.
Is there any way to generate clean patched from Mercurial?

Mercurial won't emit -p0 patches. As #Ringdig points out, they're very seldom what you want.

You could adapt the see script given in this answer : transforming patch strip level to remove the first directory instead of adding it.
Something like this should work (untested) :
sed \
-e 's!^--- a/!--- !' \
-e 's!^+++ b/!+++ !' \
< p1.patch \
> p0.patch
Assuming your "p1 patch" is in a file named p1.patch, the output will be in p0.patch

Related

How to set up a different pager and color mode in Mercurial?

I set up Mercurial in .hgrc to use less as a pager together with customized colors and templates following this guide:
[pager]
pager = LESS='FSrX' less
[templates]
# ...
[color]
mode=terminfo
This works very nicely and I'd like to keep this for all commands except for hg diff. For this command only I'd like to use a completely different mechanism:
No ANSI escape codes in output.
Use https://github.com/dandavison/delta as a pager.
Is it possible to configure Mercurial this way?
I found a solution here which achieves this setup using the extdiff extension.
[extensions]
hgext.extdiff =
[extdiff]
cmd.delta =
[alias]
diff = delta
Earlier I had this workaround - to create a separate alias:
[alias]
d = !$HG diff "$#" | delta
Unfortunately it's not possible to replace the original diff command this way. While it's possible (although discouraged) to replace a command with an alias, in this case it doesn't work: Invoking $HG diff from a diff alias would cause an infinite loop.
Beware of using manuals for Mercurial from 2014 in 2022, they can be outdated and just irrelevant
Correct using less now as pager will be (without artefacts of pager extension)
[pager]
pager = less -FRX
According to hg help pager in fresh HG (6.2), you can, with active pager, disable using it for some command(s)
You can disable the pager for certain commands by adding them to the pager. Ignore list
i.e. have smth. like
[pager]
ignore = diff
and get diff totally without paging
From the other side (contrary to the above point), you can use --config
set/override config option (use 'section.name=value')
option on calling hg diff (when|if you'll have delta as working pager) and for simplicity create hg-alias for "hg diff with delta" like
ddiff = diff --config pager.pager=delta $#

How to add different colors to mercurial template command?

What I want:
A command that prints number of added (+) and removed (-) from change log, where the added portion(+) written in green and deleted portion (-) written in red.
What I have currently:
hg log -T {diffstat} prints what I want (+20/-31:) but in black color.
hg log -T "{label('custom.colorcode', diffstat)} \n" prints the entire diffstat (+20/-31:) in green (my custom.colorcode is set to green in .hgrc)
References:
https://www.mercurial-scm.org/repo/hg/help/templates
Can I add custom colors to mercurial command templates?
I don't believe there is a way for Mercurial to automatically parse the diffstat output and to assign colors to parts of it, but you can use a workaround by doing the parsing yourself. E.g. with the following template:
hg log -T '{sub("(.*): (.*)/(.*)", "\\1: \033[0;32m\\2\033[0m/\033[0;31m\\3\033[0m", diffstat)}\n'
Note that this hardcodes ANSI color escapes (32 for green, 31 for red). If you want to do it with labels, this is also possible, but much slower (because diffstat has to be calculated multiple times). This approach can still be useful for other keywords, so I'm explaining it anyway. Here is an example template:
{sub(":.*","",diffstat)}: \
{label("diff.inserted", sub(".*([+][0-9]+).*", "\\1", diffstat))}/\
{label("diff.deleted", sub(".*(-[0-9]+).*", "\\1", diffstat))}
The easiest way to use such a long template is to put it in a file (for example ~/.hgtemplates/diffstat) and then use hg log -T ~/.hgtemplates/diffstat. If a template contains a slash or backslash and corresponds to an existing file, Mercurial will look at the contents of the file instead. Long templates can also be put in the templates section of your .hgrc, e.g.:
[templates]
diffstat = "{sub(":.*","",diffstat)}: \
{label("diff.inserted", sub(".*([+][0-9]+).*", "\\1", diffstat))}/\
{label("diff.deleted", sub(".*(-[0-9]+).*", "\\1", diffstat))}\n"
And can then be used with the corresponding name (e.g. hg log -T diffstat).

Exclude addition of certain types of files (add -X not working?)

According to the man pages
hg add -X [pattern]
Should exclude all files matching [pattern] from being added. The man entry is
-X, --exclude
exclude names matching the given patterns
However, when I try to use -X it does not work.
hg add -X *.map
hg add -X "*.map"
both include all ".map" files in all subdirectories. Example:
adding map_files/tRNAs/tRNAs_chr8.map
adding map_files/tRNAs/tRNAs_chr9.map
adding map_files/tRNAs/tRNAs_chrX.map
What gives?
I think (because I'm too lazy to test)
hg add -X "set:**.map"
will play game (maybe even without set: part), just because
The “*” character matches any string, within a single directory
noted in "Using patterns to identify files" section on mentioned by #VonC page
This pattern (Shell-style glob patterns) should work better:
hg add -X 'glob:*.map'
The page "Chapter 7. File names and pattern matching" details the possible syntax.
With re pattern (regexp), it could be hg add -X '.*\.map' (not tested).

How to make 'hg log --verbose' show files on multiple lines?

By default all files changed in a changeset are on the same line, which makes them very easily to skip one or two, and hard to read.
How to make each file show on its own separate line?
The real way to see information about changed files is to use hg status. This shows the files that were modified in revision 100:
$ hg status -c 100
But if you want to have the log messages as well, then hg log is of course a natural starting point. Unfortunately there is no built-in switch that will make it display one file per line.
However, the output of hg log is controlled by a template system and you can write your own styles for it. The default style is here and you can customize to do what you want by changing
file = ' {file}'
to
file = '{file}\n'
Then save the new style as my-default.style and add
[ui]
style = ~/path/to/my-default.style
to your configuration file. This gives you one file per line and it even works when there are spaces in your file names.
I'm aware of one problem: you lose colors in the hg log output. It turns out that Mercurial is cheating here! It doesn't actually use the default template I showed you when generating log output. It doesn't use any template system at all, it just generates the output using direct code since this is faster. The problem is that the color extension only work with the hard-coded template. When you switch to a custom template and thereby invoke the template engine, you lose the color output.
However, you can recover the colors by inserting the ANSI escape codes directly into your template (on Unix-like systems). Changing
changeset = 'changeset: {rev}:{node|short}\n{branches}...
to
changeset = '\033[33mchangeset: {rev}:{node|short}\033[0m\n{branches}...
does the trick and hard-codes a yellow header line for the changeset. Adjust the changeset_verbose and changeset_quiet lines as well and you'll have colored output with your own template.
The hg template help file has this gem in its examples.
Format lists, e.g. files:
$ hg log -r 0 --template "files:\n{files % ' {file}\n'}"
This works on Windows without any translation.
I believe there is no built-in way to achieve this, but a bit of sed (also available for Windows: http://gnuwin32.sourceforge.net/packages/sed.htm) can help:
hg log --template "Rev: {rev}:{node}\nDate: {date|isodate}\nFiles: {files}\n\n" -l 10 | sed -e '/^Files:/s/ /\n /g'
Output:
Rev: 1:2538bd4661c755ccab9b68e1d5e91144f6f97d33
Date: 2011-12-20 15:47 +0100
Files:
test1.txt
Rev: 2:853a6f3c505308c9babff5a5a2f1e09303f1689c
Date: 2011-12-20 15:44 +0100
Files:
test2.txt
test3.txt
Explanation of sed -e '/^Files:/s/ /\n /g':
/^Files:/ searches for lines starting woth "Files:", and applies the following search and replace just to those line
s/ /\n /g replaces all lines with a newline, followed by the spaces.
This solution won't work when file names contain spaces.
To see all files that changed in a revision, use:
hg status --change REV
hg log --style changelog
OR
hg log --template "Description: {desc}\n" - supported keywords like desc, files etc. are listed here

Counting changed lines of code over time in a repository

Is there a way to obtain the number of changed lines of code over a certain time period in a mercurial repository? Something along the lines of what statsvn does would be great, but anything counting the number of changed lines of code within 6 months will do (including a clever combination of arguments to hg log).
The hg churn extension is what you want.
You can get visual results with hg activity or hg chart.
Edit: hg diff and hg log both support a --stat option that can do this for you, only better and quicker.
I made an alias called lines to count changed lines (not necessarily lines of code) for me. Try putting this alias in your .hgrc file:
[alias]
lines = !echo `hg log -pr $# | grep "^+" | wc -l` Additions; echo `hg log -pr $# | grep "^-" | wc -l` Deletions;
Then pass it the revision first, followed by any optional arguments:
hg lines tip or hg lines 123:456 -u brian
Sometimes you want to know the number of lines changed excluding whitespace-only changes. This requires using diff -w underneath instead of log -p. I set up a linesw alias for this:
#ignore whitespace
linesw = ![[ $1 =~ : ]] && r=$1 || r="$1~1:$1"; echo `hg diff -wr $r | grep "^+\([^+]\|$\)" | wc -l` Additions; echo `hg diff -wr $r | grep "^-\([^-]\|$\)" | wc -l` Deletions;
hg linesw tip or hg lines 123:456
Note they behave slightly differently because diff and log behave differently -- for example, log will take a --user parameter while diff will not, and when passing a range, log will show changes commited in the first revision given in the range, while diff will not.
This has only been tested using bash.
I needed to do this, and spent quite a bit of time with the hg churn extension and similar solutions.
In the end, I found that what worked best for me was CLOC (Count Lines of Code): http://cloc.sourceforge.net/
You can give it two folders containing two versions of a project, and it will count all of the lines that are the same, modified, added, removed. It recognises multiple languages and itemises code, comments and blank lines.
To use it, I pulled out the two versions of my code from Hg into two parallel folders, and then used cloc --diff --ignore-whitespace