HG: Checkout 'tipmost' tag - mercurial

In mercurial, is there an easy way to programmatically check out the 'latest' tag?
Meaning, if hg tags produces this:
tip
Tag3
Tag2
Tag1
Is there an easy way to checkout Tag 3 in a generic way? Meaning, not just hg checkout Tag3, but a generic way of doing so.
EDIT: If I must use scripting, I can. However, I'm stuck on windows and would like to avoid scripting if possible.

You can do it with revsets. Probably something like this:
hg update -r 'max(tagged())'

If you're using bash:
hg checkout $(hg tags | sed -n '2p')
Note that this degrades gracefully: if there are no tags the subcommand will return blank and you'll get a simple checkout of the tip.

Related

Deleting all the tags in a new forked project

Is it OK to open the .hgtags file in the mercurial root directory with NotePad and remove all the tags, if you have forked a template project?
Or is there a single command where I can simply say remove all previous/old tags?
Is it OK to open the .hgtags file ... and remove all the tags?
Maybe
The way .hgtags works is that Mercurial tracks it across all heads (branches) in your repository. This is so tags can be propagated intelligently and new tags from 2 developers can be combined when a merge is done so that tags from both are usable.
The file itself is user-editable. For instance, it could have a merge conflict that you would resolve by manually editing it. So editing it per-se is not prohibited.
But if you simply delete from it, and later merge from another branch, deleted tags could come back!
So the correct general approach is to delete them properly. However there is a shortcut...
Standard way to delete would be:
hg tag --remove tagname one by one...
OR you can add tagname 0000000000000000000000000000000000000000 to the end of .hgtags. Do this for the name of each tag you wish to delete.
(The 000... code tells Mercurial to treat it as deleted.)
So in summary - if you are confident you could NEVER merge in any tags you wish to delete, then you can just remove all the tag lines in .hgtags.
Otherwise, if you only have a few tags to delete, use command hg tag remove.
If you have a huge # of tags, manually inserting the deletion code might be a faster approach.
Reference: https://www.mercurial-scm.org/wiki/Tag#How_do_I_remove_a_tag.3F

Generating a file with Tag or Branch Name in mercurial

I need in my source code to have a text file which contains the current Tag and Branch name.
Generally I want it for browsers "cache killer", I can read this file and append it to every script/css call.
for example: <script src='file.js?v=1.0'></script> the 1.0 will be coming from this generated config file.
I am working in PHP and C# So I need this kind of functionality built in the source control.
Is it possible? I dont want to do it manually, to risky.
Thanks
hg log -r. --template='{branch}-{latesttag}' would give you the branchname of the currently checked-out revision and the last tag preceeding it in its list of ancestors. Either use that call to hg directly or write it to a config file.
See hg help templates and maybe also hg help revsets

How to convert Mercurial diff output to HTML?

Is there a way to add the HTML tags to Hg diff output? Currently our team of developers receives diffs over email every day and we would like to improve their readability, for example add line highlight and change title styles. I know it can be done in SVN via the special script, but I can't seem to find the instructions on how to do it in Hg. Thanks in advance.
I've never used it, it's only from a search on Google but you can try this:
http://colorer.sourceforge.net/
hg diff | colorer -h > diff.html
You can combine the output of this command with a hook after a commit. So, after every commit, mercurial can send an email with the diff in HTML. You just need to put the glue between the line above an the examples given for setting hooks in Mercurial.

How do I prevent someone from pushing multiple heads?

I have colleagues who push multiple heads by using the --force switch because they haven't merged properly.
Are there any ways to prevent this?
You can do this with a pretxnchangegroup hook on the server side.
Here are a few examples: http://www.softwareprojects.com/resources/programming/t-mercurial-hook-forbid-2-heads-1910.html
All those hooks are doing is making sure that after the changegroup is applied that there's still only one head (or only one per branch if you want to get fancy).
Tell them they shouldn't do it, and enforce the workflow with hooks on a repository you control.
At work, we restrict it to one head / branch. Essentially replace forbid_2head.sh with this:
#!/bin/bash
# Ensure only one head per branch in hg repository
for BRANCH in `hg branches -qa`
do
COUNT=`hg heads -q $BRANCH | wc -l`
if [ "$COUNT" -ne "1" ] ; then
echo "Error: Trying to push more than one head to branch $BRANCH."
exit 1
fi
done
exit 0
This is the best from top proficient developers: http://hg.python.org/hooks/file/default/checkheads.py
Visit http://hg.python.org/hooks/file/default/ for list of another useful hooks.
You could revoke their push rights to the repository that they are --forceing to, and make them push to a different server, or submit changes via patch.
First off, I'd tell developers that a --force push is not allowed.
I'd also use the server side hook solution as prescribed above, and in the hook add an email to everyone stating WHO tried to push multiple heads into the central repo [and then format his hard drive ;)]

How to get the tag changeset after you clone or pull to a tag using mercurial?

As the definite guide aptly points out (search for "Tags and cloning"):
When you run hg clone -r foo to clone a repository as of tag foo, the new
clone will not contain any revision newer than the one the tag refers to,
including the revision where the tag was created. The result is that you'll
get exactly the right subset of the project's history in the new
repository, but not the tag you might have expected.
It means hg tags in your new clone does NOT show the foo tag. Same thing happens if you had cloned before foo tag was added, and you do hg pull -r foo.
(Digression: tag is about the only thing I don't quite get in hg. I understand there are advantages (e.g. merge) in putting it in a changeset, but it always feels weird to have meta data mixed with source code.)
It should be obvious that I'm asking for an automated way, instead of pulling the tag changeset as a separate manual step.
I know I could check for this scenario in an incoming hook (so it works for both clone and pull), or wrap clone and pull.
But is there a better/easier way?
UPDATE hg bug tracker already has this issue.
You want a giant hack with bash and an embedded Perl script? Well, here it is...
#!/bin/bash
if [[ "$1" == "" || "$2" == "" || "$3" == "" ]]; then
echo 'hgclonetag <src> <tgt> <tag>'
exit 1;
fi
REV=`hg log -R $1 --rev $3: --limit=2 | perl -F: -lane 'if (/:([\dA-Fa-f]+)$/) {print $F[2] if defined($flag);$flag=1;}'`
hg clone --rev $REV $1 $2
This invokes the hg log command to extract the revision number after the first tag-related revision and then clones to this revision.
Currently this does not work on remote repos: -R switch only works on local repos unfortunately.
The more I think about it the more I'm convinced the right answer is to just clone everything and update to the tag, which can be done in a single step:
hg clone http://host/path#tagname
That gets you everything and then does hg update to tagname which sets your working directory to the correct revision. Given delta compression that's not necessarily much larger, and if it is you can automate cloning the bulk of it from a previous local clone.
There is a postclone hook. It's called post-clone (the hgrc manpage shows a post-ANYCOMMAND and pre-ANYCOMMAND exist) though as you pointed out you could also use *changegroup or update hooks too, since clone uses both of those functions (unless you suppress update with -U).
What about just adding a --localtag so you have the name but not the extra changeset if you need it for reference only. Something like
hg clone -r tagname URL
hg tag --local tagname
which you could easily build into a shell alias.
Other than that there's not necessarily guaranteed to be a way to have revision X and the revision where revision X is tagged without also having other revisions you don't want since the tag could have been applied after other work was done. You can, of course, always update to 'X' and to have subsequent changesets in you working dir, but they'll still be in your repo.
Honestly, once I figured out that the tag name doesn't come a long when you clone up to a tag, which I admit confused the heck out of me at first, I didn't find any need to bring along the changeset with the tag in it.
Yes it can be done by post-clone/pull hooks, but there are a couple of crooks.
First, it only works for local repo, since you can't get the list of tags in a remote repo.
Second, dealing with clone/pull arguments and options is not trivial. (For clone I need to get the target repo, -r, -u, -U. For pull I need -r and -u.) I tried to use fancyopts, but it can't deal with global options, which are processed away in dispatch. I managed to hack dispatch to give me only the args and opts of a command, but it feels and looks ugly.
Using command wrapper would eliminate the second problem.
I hope one day hg will add an option to clone and pull to do it cleanly.