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
Related
Is there any way to get the list of all files (say all js or all css files) in my repo across ALL THE BRANCHES.
For example:
In my 'default' branch, i might not have a file named file1.js.
But in another branch named 'NEW_BRANCH', file1.js may exists.
I wanted to get the list of all files from one place or one command.
What about getting all files from all revisions including those still present, renamed and deleted?
hg manifest --all
If you only want files from the top of all branches (thus heads, then we iterate over all named and unnamed branches), you'll have to resort to some bash or similar, e.g.
for h in $(hg heads -T"{rev}\n"); do hg ma -r$h; done | sort | uniq
Some thing as?:
for b in `hg branches|cut -d ' ' -f 1` ; do echo "${b}: " ; hg manifest -r "branch(${b})"|grep ".css" ; echo
I have lot of tags for the project as it is very old and there are many releases to the
client.
Now when I list all the tags to view it; I ended up with a big list on my terminal.
Is there any command to show the top 5 tags or top 10 tags something like this.
I use
hg tags
command to list.
What exactly do you mean by "top"? Or do you want to only show 5 or 10 from the list?
To accomplish the last thing, use
hg tags | head -n 5
or
hg tags | tail -n 5
(if you're using *nix).
If you want to have Mercurial-only platform-independent soulution (without *Nix-specific), you can use Mercurial's revsets and templating (BTW, hg tags always show unwanted tip in list), something like
hg log -r "last(tag(),5)" --template "{tags}\t{rev}:{node|short}\n"
In order to decrease typing in process, you can write write (parametrized) revset in `[revsetalias] section on config-file like
[revsetalias]
lt = last(tag(),$1)
and use hg log -r "lt(<ANY NUMBER HERE>)" --template "{tags}\t{rev}:{node|short}\n" for getting <ANY NUMBER HERE> chronologically newest tags
or define additionally hg log --template as new command in [alias] section
[alias]
latestags = log -r "lt($1)" --template "{tags}\t{rev}:{node|short}\n"
and use later hg latestags(5) or hg latestags(10)
Using templates, I want to find out how many times a file has been revised across all changesets. So, put another way, how many changesets feature that file.
Is there a way to do it? And can it be done with the Keywords extension?
And yes, I realise it's not really what Mercurial is about. I have sucky requirements:)
hg log -q filename | wc -l will output amount of changesets
It is a normal feature of an VCS to track, when a file was changed, just run hg log THE_FILENAME to see all changesets which affect one specific file.
To count them, run for example hg log THE_FILENAME | grep -c "^changeset".
I thought I'd just add one more option to the list here since grep and wc (word count) may not be available in your console (Windows users especially). There is an equivalent functionality in PowerShell:
hg log -q filename | Measure-Object
This will return the count by default (and as you can see there are other options you can play with using Measure-Object)
Count : 14
Average :
Sum :
Maximum :
Minimum :
Property :
And if you are interested in how many commits you have done for the entire repository you can omit the -q filename parameter:
hg log | Measure-Object
Count : 492
Average :
Sum :
Maximum :
Minimum :
Property :
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
After pushing changesets to a repository called 'A' how can I see the list of changesets waiting to be applied when I am in 'A'?
Expanding on that,
In repo B I push changesets to repo B
I change to repo B
How can I list the changesets pushed in step 1?
Not sure what you mean by "unapplied" changesets, however here's a couple thoughts.
You can easily see what changesets will be pushed to a repository by doing hg outgoing prior to doing the hg push. This will list all of the changesets that will be pushed using default options.
Similarly you can use hg incoming in the destination repository to show what changesets would be pulled from another repo.
As for "unapplied" changesets, if I assume you mean changesets that are newer than the working directory, you could use hg log -r .:tip, which should (I've not had a chance to test it) show all newer revisions, but not actually all recently-pushed ones.
Edit: I've updated the revision set in the -r option to something that should work. Have a look at revsets on the Mercurial manpage for more possibilities.
$ hg summary
parent: 0:9f47fcf4811f
.
branch: default
commit: (clean)
update: 2 new changesets (update) <<<<<
The update bit tells you what (I think) you want.
I had written a different answer, but I ended up with a better way of doing what is needed here (an even better and definitive –for me– solution is at the end of this post, in the [EDIT] section).
Use hg log.
Specifically, issue an hg sum command first. This will give me:
parent: 189:77e9fd7e4554
<some commit message>
branch: default
commit: (clean)
update: 2 new changesets (update)
To see what those 2 new changesets are made of, I use
hg log -r tip -r 2 -v
Obviously, 2 is to be replaced with the number of changesets that hg sum reports.
This works because tip will refer to the most recent (or "unapplied") changeset. By limiting the output to the 2 latest changes (-l 2), the information is shown only for those changesets that I'm interested in. With -v, the list of files affected by the changeset is also shown.
To make things simpler, I have defined a user command in my .bashrc file:
alias hglog="hg log -r tip -l $1"
This allows me to type hg sum (to get the number of pending/unapplied changesets) and then to type hglog x where x is the number of changesets revealed by hg sum.
There is probably a more complete way of doing this, for instance using custom templates, but I guess it's pushing things too far in terms of sophistication.
[EDIT] (Third iteration)
I have reached the most satisfying answer to this question by expanding on the alias idea so that I no longer have to type hg sum. My .bashrc file now contains this:
show_pending_changesets() {
nb=$(hg sum | grep "update:" | sed 's/update: \([0-9]*\) .*/\1/');
if [ `expr $nb + 1 2> /dev/null` ] ; then
hg log -r tip -v -l $nb
else
echo "Nothing new to report"
fi ;
}
...
alias hgwhatsnew=show_pending_changesets
Explanation: I'm using sed to extract the number of changesets from the last line (which is the one that starts with update:) of the output of hg sum. That number is then fed to hg log. All I have to do then is to type hgw and tab-complete it. HTH