Hemisphera
Hemisphera

Reputation: 876

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:

  1. precommit: unsuitable as it fires before hg knows any metadata of the commit
  2. pretxncommit: unsuitable, as the documentation clearly states that we should not change the working dir at this point
  3. 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?

Upvotes: 0

Views: 592

Answers (3)

Lazy Badger
Lazy Badger

Reputation: 97285

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

Upvotes: 1

Reimer Behrends
Reimer Behrends

Reputation: 8730

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.

Upvotes: 2

planetmaker
planetmaker

Reputation: 6044

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.

Upvotes: 0

Related Questions