Get Mercurial next commit hash - mercurial

I am at revision 56, hash 6af16aa3edf8. Next revision will be 57, with hash ???. Is there a way to know the hash of revision 57? I need it in a pre-commit hook.
WHY THO?
I developed a script, called via pre-commit hook, that update some version files. That way, the compiled executables can give all info about the revision they are build from. I'm adding the revision number of the current commit in my version file, simply retrieved with "parent revision number + 1". Since the revision number is not reliable when collaborating with other people on the same repository, I prefer to add the hash, too. Don't know how to retrieve it...

No, you cannot predict the next hash even when you know its changeset completely. The commit time also plays a role there:
~/hg-test $ hg ci -m "b in foo"
~/hg-test $ hg id
d65d61e6898a tip
~/hg-test $ hg rollback
~/hg-test $ hg ci -m "b in foo"
~/hg-test $ hg id
c7f5ff744e43 tip
https://www.mercurial-scm.org/wiki/Nodeid
I suggest to solve your problem such:
In your build tools, query whether the project is built from a repository. If so: retrieve the repository information. E.g.
ver = $(hg log -r. -T"{node|short} from {date|isodate}")
will give you
c7f5ff744e43 from 2017-07-26 14:05 +0200
Generate the version file from that information in your build chain on the fly
For distribution purposes, generate and amend this file to the package, so that the build process, when it finds it is not started from a repository checkout, still has a version file it can make use of.

Related

How do I diff incoming changesets with Beyond Compare 4 and hg?

I have been using the mercurial and Beyond Compare 4 tools together for about 2 weeks now and feel fairly confident in my usage, however I still seem to have a problem when comparing incoming changesets against my current local codebase. The problem is emphasized when I attempting a complicated merge.
Just to clarify, I am avoiding the use of tools such as TortoiseHg,
although I do have it installed. I am searching for feedback via cmd line operations only.
My current templated method to pull down the incoming changesets via the following ( as an [alias] )
hg in --verbose -T "\nchangeset: \t{rev}\nbranch: \t{branch}\nuser: \t\t{author}\ndate: \t\t{date(date,'%m-%d-%Y %I:%M%p')}\ndescription: \n\t{desc|fill76|tabindent}\n\n{files % ' \t{file}\n'}\n----------\n"
As an example, here is a simplified (and cleverly abstracted) block returned ::
changeset: 4685
branch: Feature-WI209825
user: Jack Handy <jhandy#anon.com>
date: 01-19-2015 10:19AM
description:
Display monkey swinging from vines while whistling dixie
Zoo/MonkeyCage/Resources/Localization.Designer.cs
Zoo/MonkeyCage/Resources/Localization.resx
Zoo/MonkeyCage/Utility/Extensions.cs
If I were to be comparing changes locally, I would simply use the following command ::
hg bcomp -r 4685 -r default <optional file name>
and then I would get an instance of Beyond Compare with a folder structure and files and I could just navigate accordingly to view the changes...however, when I attempt to do this with a changeset that has yet to be pulled into my local repository, I can't.
How do I diff incoming changesets with my local repository?
---- UPDATE --------------------------------
I pursued the idea of bundling the incoming changes and then trying to use BC4 to diff the bundle to any given branch/revision on my local repo.
hg in --bundle "C:\Sandboxes\Temp\temp.hg"
This creates a compressed file archive containing all the new changes.
Now I simply need to diff this bundle with my local, however am having difficulty optimizing this. Currently, I am using variations on the following command:
hg -R "C:\Sandboxes\Temp\temp.hg" bcomp -r default
Alas, I am still having difficulty perfecting this...any insight is appreciated.
I don't see how you can, since your local repository doesn't yet have that changeset, so mercurial can't create a local copy of the revision, as it doesn't have visibility of what the change actually is.
The -p flag to hg incoming will show you the patch for each revision, but that isn't what you want.
Why not just pull the remote changes anyway? It wont hurt unless you actually update. You can then do your diff in the normal way.
hg diff is a local operation.
But you can simply call hg incoming -p in order to obtain a diff view of what you're going to pull. See hg help incoming for more options and refinement (e.g. if you need to diff against a specific rev etc)

Add a parent to the original changeset in Mercurial

I have a project with 24 months of source control history in a Mercurial repository.
I've recently found some old tarballs of the project that predate source control, and i think they would be useful to import into the repository as "pre-historic" changesets.
Can i somehow add a parent to my initial commit?
Alternatively, is it possible to re-play my entire repository history on top of the tarballs, preserving all metadata (timestamps etc)?
Is it possible to have the new parent commits use the timestamps of these old tarballs?
You can use the convert extension to build a new repository where the tarballs are imported as revisions before your current root revision.
First, you import the tarballs based on the null revision:
$ hg update null
$ tar -xvzf backup-2010.tar.gz
$ hg addremove
$ hg commit -m 'Version from 2010'
$ rm -r *
$ tar -xvzf backup-2011.tar.gz
$ hg addremove
$ hg commit -m 'Version from 2011'
I'm using addremove above to give Mercurial a chance to detect renames between each tarball (look at the --similarity flag to fine-tune this and use hg rename --after by hand to help Mercurial further). Also, I remove all the files in the working copy before importing a new tarball: that way the next commit will contain exactly the snapshot present in the tarball you unpack.
After you've imported all the tarballs like above, you have a parallel history in your repository:
[c1] --- [c2] --- [c3] ... [cN]
[t1] --- [t2] --- [tM]
Your old commits are c1 to cN and the commits from the tarballs are t1 to tM. At the moment they share no history — it's as if you used hg pull -f to pull an unrelated repository into the current one.
The convert extension can now be used to do a Mercurial to Mercurial conversion where you rewrite the parent revision of c1 to be tM. Use the --splicemap flag for this. It needs a file with
<full changeset hash for c1> <full changeset hash for tM>
Use hg log --template '{node} ' -r c1 -r tM > splicemap to generate such a file. Then run
$ hg convert --splicemap splicemap . spliced
to generate a new repository spliced with the combined history. The repository is new, so you need to get everybody to re-clone it.
This technique is similar to using hg rebase as suggested by Kindread. The difference is that convert wont try to merge anything: it simply rewrites the parent pointer in c1 to be tM. Since there is no merging involved, this cannot fails with weird merge conflicts.
You should look at using rebase. This can allow you to make the changes the 2nd changeset on your repo ( you have to rebase from the 1st ).
https://www.mercurial-scm.org/wiki/RebaseExtension
However, note that if there are other clones of this repo existing ( such as for fellow developers, or on a repo server ), you will have issues with them pulling the revised repo. You will probably have to co-ordinate with the owners of those clone's to get all work into a single clone, rebase that clone, and then have everyone re-clone from the revised clone. You will also have to change the phase the of the changesets.
https://www.mercurial-scm.org/wiki/Phases
Honestly though, I would just add them to your 'modern-day' repo, I don't think making them pre-historic would give you any notable advantage over adding them to the top.

Get the dates of pull and update in Mercurial

Is it possible to know when a certain commit was pulled from a distant repository and the files updated with Mercurial ?
More precisely, I made a hg pull -u a few days ago, and now I'd like to know if this pull downloaded only the last commit, or if there were some commits that had not been pulled yet, making my last pull getting them as well.
hg log seems to give the dates of the commits, but nothing about the updates. Is this information anywhere ?
This information is not recorded by Mercurial. A Mercurial repository is just a container for changesets and Mercurial does not store how (or when) the changesets entered the repository.
You can setup hooks for this, though you would have to build the scripts yourself. A very rudimentary system would be
[hooks]
pre-pull = (date; hg root; hg tip) >> ~/.pull-log
post-pull = hg tip >> ~/.pull-log
This would record the current date, the current repository, and the current tip in ~/.pull-log just before every hg pull. After the pull the new tip is recorded. You could build scripts that parse the log file to extract information about what each pull did.
hg log seems to give the dates of the commits, but nothing about the updates
Yes, hg log is only concerned with the stored history (changesets) and working copy operations like updating is not part of recorded history.
Finally, let me mention that this is the first time I've seen someone ask for a "pull log". However, the opposite is quite common: there are scripts for maintaining a "push log" on a server to see who pushed what and when. This is done by Mozilla among others. See this README for some starting instructions.
If you want to log when and with which revision hg update was used to update the code, then use these hooks:
[hooks]
pre-update = (echo "---------------------------------"; date --rfc-3339=s; hg root; echo "pre-update:"; hg identify --id --branch) >> .hgupdates
post-update = (echo "post-update:"; hg identify --id --branch) >> .hgupdates
the above hooks produce a log entry like this for each time hg update is run:
2015-12-23 00:44:31+02:00
/var/www/my/project
pre-update:
802120d1d3a0 somebranch
post-update:
302720d1d3d2 otherbranch
This also works when hg update is run without a specific revision flag (-r) set

How can I commit a file before the tag is committed?

I want to automatically bump the version of my project when I use hg tag XXX.
I have set up a pretag hook in my hgrc (note: I have removed the stuff that ensures it is outputting to VERSION in hg root, for clarity):
[hooks]
pretag.bump_version = (echo "$HG_TAG" > VERSION; hg commit -m "Updated VERSION to $HG_TAG" VERSION)
When I create a new tag:
$ hg tag 1.1
I get the error:
warning: ignoring unknown working parent <revision_id>!
I can use a tag hook instead, which succeeds, but then the VERSION number is exactly one revision later than the tag: which means that updating to the tagged revision, and then building will result in the product's version number (which depends upon the VERSION file) will be incorrect.
Is there a better way to handle this? I've looked at SO question #2558531, but that deals with updating the version number each time: I just want to update the version number before I tag the repository.
Switch to a pre-tag instead of a pretag hook. The hook pretag is a special hook which is aware that you're tagging. By contrast the pre-tag hook is a generic pre-* hook which is run before the tag command launches at all and is completely unaware that it's tagging -- which means it runs earlier too. (There are pre-* hooks for everything even, say, pre-log).
I got your example to work like this:
[hooks]
pre-tag.bump_version = echo $HG_ARGS > VERSION; hg commit -m "updated version to $HG_ARGS" VERSION
Using the command line only that looked like:
ry4an#ry4an:~$ hg init tagtest
ry4an#ry4an:~$ cd tagtest
ry4an#ry4an:~/tagtest$ echo text > VERSION
ry4an#ry4an:~/tagtest$ hg commit -A -m initial
adding file
ry4an#ry4an:~/tagtest$ hg tag --config hooks.pre-tag='echo $HG_ARGS > VERSION; hg commit -m "updated version to $HG_ARGS" VERSION' 1.1
Notice I had to switch the argument to $HG_ARGS since it's a pre-* command that doesn't know we're tagging. The details are in the hgrc manpage.
Also note I'm committing only the VERSION file when I commit in the hook by naming it explicitly. You don't want to accidentally commit a bunch of debugging stuff you'd excluded from a previous commit just because you tagged.

Mercurial hooks -- pass information between hooks?

I currently have a pre-commit hook in my mercurial project that gives the user the option to update the version number of the project if they wish (e.g. 1.0 to 1.0.1 or 1.1 or 2.0). They select one of these options, and the hook updates the version number in one of the project's files prior to the commit taking place.
When I run hg commit, this hook runs and updates the relevant file with the new version number, and then performs the commit.
I'd like to add to the hook such that it calls hg tag <new_verson_number> as well.
However, I can't add this to the pre-commit hook, because then the tag will be added before the commit is called, causing the tag to be one revision out of date.
I'd like to add the hg tag command to a commit hook (run after the commit), so that the sequence of events is like so:
hg commit -m "my commit message"
user says yes, I'd like to change the version number
version number is updated in the relevant file
commit occurs [everything up to here is fine]
if the user changed the version number, run a commit hook: hg tag <new_version_number>.
Now, I could add a commit hook that read off the new version number from the file it's stored in and run hg tag <new_version_number>, but what if the user decided not to change the version number? In that case, I don't want a tag added, and if I blindly run hg tag <new_version_number> I'll end up with tags I don't want.
So - is there some way I can tell the pre-commit hook to leave some information for the commit hook (a yes/no of whether to add the tag), and the commit hook can use this to determine whether to add the tag or not?
cheers.
How about a commit hook that checks if the last commit modified the file in which you store the version? Something like:
[hooks]
commit.tagversion = if hg log -r $HG_NODE --template '{files}' | grep -q VERSION_FILE ; then hg tag $(hg cat -r $HG_NODE VERSION_FILE) ; fi
I haven't tested it, but that or something like it should work.
You could extract the tag name that you would add and then check to see if it already exists in hg tags before you add it. That would also catch the case where the developer amends the version number manually.