Combination commit history of Mercurial repositories (for Gource) - mercurial

How to me to combine some repositories that the commit history was adequately displayed in Gource?
Merging two different repositories I did everything as is specified there
But in Gource the commits of only one repository is shown

Here's a batch file I wrote today that solves the problem for subrepos:
REM Remember the directory we started in.
set PreDir=%cd%
REM Clean up old data
DELETE dump.log
DELETE filtereddump.log
REM Generate data for every repo using onsub
hg onsub "gource --output-custom-log test.log"
REM Concatenate all collected data into the one log file
hg onsub "TYPE test.log >> %PreDir%/dump.log"
REM Sort file to get correct chronological order
sort dump.log > filtereddump.log
REM Run gource with the filtered data
gource filtereddump.log
Obviously, there are a couple of assumptions here... this is windows specific, subrepository-specific, and relies on the mercurial extension 'onsub' and a sort tool I picked up here: http://gnuwin32.sourceforge.net/packages/coreutils.htm
Hope that helped.
PS: This batch script was inspired by info on the Gource wiki. Check out https://code.google.com/p/gource/wiki/GourceMashups

Related

Reliably check if there are dirty or untracked files in working set

I'm trying to write some scripts for doing some simple housekeeping tasks in mercurial and one of the things I frequently need to do is check if the working set is "empty" (depending on context, that could mean untracked files or modified tracked files).
The hg status command exits with exit status 0 unless there was an internal error, in which case it exits with exit status 255.
If a few of my scripts, I'm doing something silly like capturing the output of the hg status command and checking whether it's empty or not.
In other cases I'm checking the exit status of hg id -i | grep -qvF + to check whether there are dirty tracked files.
Both of these seem a little brittle. Are there dedicated subcommands for "querying" the repository to see if there are "untracked files" or "dirty tracked files" or "removed files" or various other interesting things in the working set?
hg status is the command to check for modifications of the working directory with respect to the checked-out revision - thus you are doing the right thing.
You can get away with exclusively using hg status. Using the --mard (or --modified --added --removed --deleted) flags will yield empty if the tracked files didn't change. And using -u or --unknown will show files which are neither ignored nor tracked - and empty output should always indicate no changes to tracked files nor any non-ignored files (but there might be new files which match one of the ignore patterns).
The output format of these commands (at least in the English original, thus LC_ALL=C hg status) is treated by mercurial as API, thus you should be able to rely on it.
Depending on your actual use-case you might want to look at the mercurial command server - but for a script which runs occasionally it might be quite over the top.
test -z "$(hg status -mard --template x)" && echo clean || echo dirty
Seems to work

Mercurial - Add tag to committed files on commit

We are looking for a way to add / update a custom tag at the beginning of each file being committed during a commit. Its some kind of local timestamp we need.
I was thinking of hooks.
Unfortunately I cannot find a useful hook for that:
precommit: unsuitable as it fires before hg knows any metadata of the commit
pretxncommit: unsuitable, as the documentation clearly states that we should not change the working dir at this point
commit: unsuitable, as it fires when the commit has already happened.
EDIT:
I can not use hg's inline changeset-hash and / or datetime. For the following reason:
Our files get later imported into an external system (we do not have control over) which does not support any kind of versioning.
To simplify stuff: let's say tag is an ever-incrementing no. (everytime we commit). This tag is then used to help getting an idea of the version / status of the file on the system in respect to the file in the repo - like "no. of changes we're missing" and such.
Any ideas?
I would suggest a two-stage solution. First, create an alias along the following lines:
[alias]
tcommit = !tag-changed-files && $HG commit "$#"
Here, tag-changed-files would retrieve a list of modified and added/moved files via $HG status -ma -n or $HG status -ma -n -0 and tag them. I am assuming that re-tagging files that have been modified but aren't being committed yet is a harmless operation; more on that below. Note that you can even redefine commit if you absolutely want to via:
[alias]
commit = !tag-changed-files && $HG --config alias.commit=commit commit "$#"
However, this is potentially problematic, because it may confuse scripts.
You could also integrate the commit step in the program if you wanted to, and even try and parse the command line arguments to only tag those files that you are committing. For this approach, using hglib might be appropriate to avoid the overhead of invoking Mercurial multiple times. (Note that hglib and other tools that use the command server ignore aliases and command defaults, so this works even if you alias commit).
Second, you'd install a pretxncommit hook that verifies that files that are being committed have indeed been tagged appropriately (to ensure that the tag-changed-files program hasn't been bypassed by accident).
This should work without a problem on full commits; for partial commits, any files that were changed but have not been committed would also have been retagged, but since they will be either committed later (and get tagged properly at that point) or reverted, that should be harmless.
an idea of the version / status of the file on the system in respect to the file in the repo
Just one idea
Stop reinvent the wheel
Incremental counter is just shit, if you task is "to know, which version is on LIVE and which - in Mercurial's tip" (and this is your real business-task, yes?!)
Keyword Extension give you last changes per file.
If you want to inject changeset of repository into files (it's reasonable good way), re-read this part of wiki-page
If you just want to version your entire repo, do not use this
extension but let your build system take care of it. Something along
the lines of
hg -q id > version
before distribution might be well enough if file-wise keyword
expansion in the source is not absolutely required
You can insert hg id output into files at export stage (in planetmaker's sed-style), bu you can also have this additional metadata in files permanently in VCS with special encode|decode filters
There is - to my knowledge - no intrinsic system in mercurial which supports what you describe. However I can recommend an approach which somewhat is adopted from building a software release package from the repository: Make a small export script which replaces a certain KEYWORD in your files with the version information you need. A Makefile target could look like which creates a zip export for revision XXX with version information in all files which support it (thus contain the verbatim KEYWORD - use something truely unique here):
VERSION=$(hg log -rXXX --template="Version: {node|short} from {date|isodate}")
export:
hg archive -rXXX -t files export
for i in $(hg ma -rXXX); do sed -i "s/KEYWORD/$VERSION/g" $i; done
zip -9rq export.zip export
I use a similar approach in my Makefiles where I create versioned export for the source of a particular revision of my software.
EDIT: if your purpose (as stated by the comment) is only to implant the number of commits made to that file: then you can use indeed a pre-commit hook and modify the file. You can count the number of modifications made to a file with hg log FILENAME --template="{node}\n" | wc -l. Do that for every file and do the sed replacement in the header of each file in the pre-commit hook.

Mercurial move followed by diff

I had two very large projects in my Mercurial repository.
I am in the process of refactoring both of them into smaller sub-projects.
That involves moving sets of sources from a parent project directory into a sub-project's sub-directory.
For most files, I simply moved them.
For some files, I also had to make changes.
Before I commit my refactoring changes, I would like to review any edits that I made to any source files. In the GUI tool SourceTree - it shows me any modifications (in addition to indicating that the file has been moved/renamed). Is there any way to determine what files have also been modified from the Mercurial command line?
Here is a specific example of what I am talking about:
iphonedev:EveryScape cdoucette$ hg status -C Engineering/iOS/ESSDK/src/ESSDK-Miscellaneous/ESDataManagerInMemory.m
A Engineering/iOS/ESSDK/src/ESSDK-Miscellaneous/ESDataManagerInMemory.m
Engineering/iOS/ESSDK/src/ESDataManagerInMemory.m
How can I compare the old revision with the current working copy in a different location?
If I just do this:
hg diff Engineering/iOS/ESSDK/src/ESSDK-Miscellaneous/ESDataManagerInMemory.m
It shows me the entire contents of the file (since technically it was added in its new location).
Instead, I want to diff between:
Engineering/iOS/ESSDK/src/ESDataManagerInMemory.m (repository copy - previous revision)
Engineering/iOS/ESSDK/src/ESSDK-Miscellaneous/ESDataManagerInMemory.m (working copy)
I did search for similar questions. This post was close - but appears to only make sense if I went ahead and committed my changes. Instead, I would like to find and review my changes before committing.
Mercurial diff not working after move/rename
I would script it up like this:
hg cat -r <oldrev> <oldfilename> > oldfile.oldrev
diff <newfilename> oldfile.oldrev

How can I label my build with revision number and not the GUID (in TeamCity)?

I am trying to do "continuous integration" with TeamCity. I would like to label my builds in a incremental way and the GUID provided by the VCS is not as usefull as a simple increasing number. I would like the number to actually match the revision in number in Mercurial.
My state of affairs:
Mercurial info:
I would like the build to be labeled 0.0.12 rather than the GUID.
Would someone be so kind and save me hours of trying to figure this out ?
As Lasse V. Karlsen mentioned those numerical revision numbers are local-clone specific and can be different for each clone. They're really not suitable for versioning -- you could reclone the same repo and get different revision numbers.
At the very least include the node id also creating something like 0.0.12-6ec760554f2b then you still get sortable release artifacts but are still firmly identifying your release.
If you're using numeric tags to tag releases there's a particularly nice option:
% hg log -r tip --template '{latesttag}.{latesttagdistance}'
which, if the most recent tag on that clone was called 1.0.1 and was 84 commits ago gives a value like:
1.0.1.84
Since you can have different heads that are 84 commits away from a tag in different repos you should still probably include the node id like:
% hg log -r tip --template '{latesttag}.{latesttagdistance}-{node|short}'
giving:
1.0.1.84-ec760554f2b
which makes a great version string.
The best and easiest way to see rev. number in TeamCity build number is to use Build Script Interaction with TeamCity. Namely, it has a possibility to set Build Number.
So, add to your project a new very first build step Command Line with following Command Executable
for /f %%i in ('c:\tortoisehg\hg id -n') do echo ##teamcity[buildNumber '%%i']
And you will get the Mercurial revision number as a label for your every build.
Of course you can change the command in quotes to anything you wish.
I believe my answer is way more correct than the accepted one.
EDIT:
Also you can do the same via MSBuild task rather than Command Executable. Have a MSBuild project file with following code, setup TeamCity to run it as first step, and it will alter its global variable buildNumber:
<Message Text="##teamcity[buildNumber '$(CurrentVersion)']" Importance="High" />
Where CurrentVersion is a string containing full version (for example "1.0.56.20931").
hg id produces the hash (6ec760554f2b), hg id -n produces the local revision number (12).
(Note this is an answer purely from the hg side, how you then get that into TeamCity, I don't know, as I've never used it.)
I managed to use it in Teamcity using a workaround:
<Exec Command="hg log -r tip --template {latesttag}.{latesttagdistance} > $(BuildAgentTempDir)\version.txt"/>
<ReadLinesFromFile File="$(BuildAgentTempDir)\version.txt">
<Output TaskParameter="Lines" ItemName="versionInfo"/>
</ReadLinesFromFile>
<TeamCitySetBuildNumber BuildNumber="#(versionInfo)-{build.number}" />
If you see the MSBuild task "TeamCitySetBuildNumber" I'm using the "{build.number}" variable because it substitutes this with what you set in the build number originally. I used %build.vcs.number% in my original settings (in the Web UI) and the result is just what Ry4an wrote above!
Hope it works for you!
When I used to use Subversion I used to do something similar in TeamCity. The format was:
{Major}.{Minor}.{TeamCity Build No.}.{Subversion Revision No.}
This allowed me to look at an assembly and see which build it came from on TeamCity and the revision number from subversion.
I have now moved to Git which has put me in the same situation as you. After playing with various ideas I have come to the conclusion that I don't actually need the revision, the build is good enough. Because TeamCity is such a powerful tool, all you need is the build number, given the build number you can look at the build history and determine the revision from that.
{Major}.{Minor}.{Macro}.{TeamCity Build No.}
Additionally you can get TeamCity to label your repository with the build number allowing you to look up a given build in your source control.
When providing your build number with numeral mercurial revision, you must be aware, that those numbers are clone-specific and can differ from clone to clone.
In our project we had the same issue. We're using TeamCity 7.1.1. We solved it in the following way:
Add Command line build step to your configuration.
Make this build step run first.
In the build step properties select "Run: 'Executable with parameters'"
Add the following text to Command Executable:
for /f %%i in ('hg id -n') do echo ##teamcity[buildNumber '%%i']
Save changes.
You can also use previously generated build number when performing step 3.
Example:
for /f %%i in ('hg id -n') do echo ##teamcity[buildNumber '%system.build.number%.%%i']
You can use this to make build counter present in your build number.
Read this to get more information!
Remember that teamcity compiles configurations build number before build starts and the correct build number will appear only after your build step will finish its job. That's why, in some cases (f.e. inserting your mercurial revision into artifact's name) you should define build number's value in preceding configuration and refer to it.
Example:
%dep.bt82.build.number%
Read this to get more information!

Mercurial - How do I create a .zip of files changed between two revisions?

I have a personal Mercurial repository tracking some changes I am working on. I'd like to share these changes with a collaborator, however they don't have/can't get Mercurial, so I need to send the entire file set and the collaborator will merge on their end. I am looking for a way to extract the "tip" version of the subset of files that were modified between two revision numbers. Is there a way to easily do this in Mercurial?
Adding a bounty - This is still a pain for us. We often work with internal "customers" who take our source code releases as a .zip, and testing a small fix is easier to distribute as a .zip overlay than as a patch (since we often don't know the state of their files).
The best case scenario is to put the proper pressure on these folks to get Mercurial, but barring that, a patch is probably better than a zipped set of files, since the patch will track deletes and renames. If you still want a zip file, I've written a short script that makes a zip file:
import os, subprocess, sys
from zipfile import ZipFile, ZIP_DEFLATED
def main(revfrom, revto, destination, *args):
root, err = getoutput("hg root")
if "no Merurial repository" in err:
print "This script must be run from within an Hg repository"
return
root = root.strip()
filelist, _ = getoutput("hg status --rev %s:%s" % (revfrom, revto))
paths = []
for line in filelist.split('\n'):
try:
(status, path) = line.split(' ', 1)
except ValueError:
continue
if status != 'D':
paths.append(path)
if len(paths) < 1:
print "No changed files could be found."
return
z = ZipFile(destination, "w", ZIP_DEFLATED)
os.chdir(root)
for path in paths:
z.write(path)
z.close()
print "Done."
def getoutput(cmd):
p = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
return p.communicate()
if __name__ == '__main__':
main(*sys.argv[1:])
The usage would be nameofscript.py fromrevision torevision destination. E.g., nameofscript.py 45 51 c:\updates.zip
Sorry about the poor command line interface, but hey the script only took 25 minutes to write.
Note: this should be run from a working directory within a repository.
Well. hg export $base:tip > patch.diff will produce a standard patch file, readable by most tools around.
In particular, the GNU patch command can apply the whole patch against the previous files. Isn't it enough? I dont see why you would need the set of files: to me, applying a patch seems easier than extracting files from a zip and copying them to the right place. Plus, if your collaborator has local changes, you will overwrite them. You're not using a Version Control tool to bluntly force the other person to merge manually the changes, right? Let patch deal with that, honestly :)
In UNIX this can be done with:
hg status --rev 1 --rev 2 -m -a -n | xargs zip changes.zip
I also contributed an extension, see the hgexportfiles extension on bitbucket for more info. The export files extension works on a given revision or revision range and creates the set of changed files in a specified directory. It's easy to zip the directory as part of a script.
To my knowledge, there's not a handy tool for this (though a mercurial plugin might be doable). You can export a patch for the fileset, using hg export from:to (where from and to identify revisions.) If you really need the entire files as seen on tip, you could probably hack something together based on the output of hg diff --stat -r from:to , which outputs a list of files with annotations about how many lines were changed, like:
...
src/test/scala/RegressionTest.scala | 25 +++++++++++++----------
src/test/scala/SLDTest.scala | 2 +-
15 files changed, 111 insertions(+), 143 deletions(-)
If none of your files have spaces or special characters in their names, you could use something like:
hg diff -r156:159 --stat | head - --lines=-1 | sed 's!|.*$!!' | xargs zip ../diffed.zip
I'll leave dealing with special characters as an exercise for the reader ;)
Here is a small and ugly bash script that will do the job, at least if you work in an Linux environment. This has absolutely no checks what so ever and will most likely break when you have moved a file but it is a start.
Command:
zipChanges.sh REVISION REPOSITORY DESTINATION
zipChanges.sh 3 /home/hg/repo /home/hg/files.tgz
Code:
#!/bin/sh
REV=$1
SRC_REPO=$2
DST_ZIP=$3
cd $SRC_REPO
FILES=$(hg status --rev $1 $SRC_REPO | cut -c3-)
IFS=$'\n'
FILENAMES=""
for line in ${FILES}
do
FILENAMES=$FILENAMES" \""$SRC_REPO"/"$line"\""
done
CMD="tar czf \"$DST_ZIP\" $FILENAMES"
eval $CMD
I know you already have a few answers to this one but a friend of mine had a similar issue and I created a simple program in VB.Net to do this for him perhaps it could help for you too, the prog and a copy of the source is at the bottom of the article linked below.
http://www.simianenterprises.co.uk/blog/mercurial-export-changed-files-80.html
Although this does not let you pick an end revision at the moment, it would be very easy to add that in using the source, however you would have to update to the target revision manually before extracting the files.
If needed you could even mod it to create the zip instead of a folder of files (which is also nice and easy to manually zip)
hope this helps either you or anyone else who wants this functionality.
i just contributed an extension here https://sites.google.com/site/alessandronegrin/pack-mercurial-extension
I ran into this problem recently. My solution:
hg update null
hg debugsetparents (starting revision)
hg update (ending revision)
This will have the effect of deleting all tracked files that were not changed between those two revisions. You will have to remove any untracked files yourself, though. After doing this, the local branch will be in an inconsistent state; you can fix this by running hg debugrebuildstate (or simply deleting the local branch, if you no longer need it).