Mercurial update source code with current revision numer - mercurial

I there a way to update a source code file with the current revision number each time i do a commit?
Something like, let's say that in my footer.php i have something like
Rev. number: {REVISION}
And when i commit {REVISION} will be replaced with current revision number.
I'm using TortoiseHG

You can use RCS-type keyword expansion:
https://www.mercurial-scm.org/wiki/KeywordPlan
But if your last changeset didn't include footer.php, then the keywords won't be expanded, so your probably better off having some build procedure write the current revision ID via hg id. There's an example on how to do this in the link above.

Related

Mercurial: Most recent change per file

I'm looking for a way to make Mercurial output a table like this:
File Most recent revision changing the file Date of that revision
==== ====================================== =====================
foo.py 44159adb0312 2018-09-16 12:24
... ... ...
This is just like github does it on the "Code" overview page. (screenshot from torvalds/linux):
"Most recent" could refer the date or to the DAG hierarchy relative to the current changeset, or maybe to the current branch. Perhaps the latter is more useful, but in my particular use case, it doesn't make a difference.
I'd also like to be able to provide a list of files or a subdirectory for which I want the table. (I don't necessarily want it for everything)
I am aware that I could do it using a small script, looping over hg log -l 1 <file>, but I was wondering if there is a more efficient / more natural solution.
You won't get around looping over all files. Yet with hg manifest you get that list of files. Then template the output as needed:
for f in $(hg ma); do hg log -l1 $f -T"$f\t\t{rev}:{node|short}\t\t{date|isodate}"; done
This gives output like
.hgignore 38289:f9c426385853 2018-06-09 13:34 +0900
.hgsigs 38289:f9c426385853 2018-06-09 13:34 +0900
.hgtags 38289:f9c426385853 2018-06-09 13:34 +0900
You might want to twiddle more with the output formatting. See the mercurial wiki for a complete overview of output templating.
Git will follow the commit DAG, because that's all it has. In Mercurial, you have (many) more options because you have more data.
Probably the ideal option here is follow(file, .) (combined with first or last as appropriate). But as hg help revset will tell you, you have the following options (I've shrunk the list to the obvious applicable ones):
ancestors(set[, depth])
Use this with the set being . to get ancestors of the current commit, for instance, if you want to do DAG-following a la Git. Or, use ::., which is basically the same.
branch(string or set)
Use this with . to get all commits in the current branch. Combine with other restrictors (e.g., parents) to avoid looking at later commits in the current branch if you're not at the tip of the current branch.
file(pattern)
Use this with a glob pattern to find changesets that affect a given file.
filelog(pattern)
Like file but faster, trading off some accuracy for speed (see documentation for further details).
follow([file[, startrev]])
To quote the documentation:
An alias for "::." (ancestors of the working directory's first parent).
If file pattern is specified, the histories of files matching given
pattern in the revision given by startrev are followed, including
copies.
modifies(pattern)
Use this (with any pattern, not just glob) to find changesets that modify some file or directory. I think this is limited to M type modifications, not addition or removal of files, as there is also adds(pattern) and removes(pattern). Use all three, or-ed together, to find any add/modify/remove operations.
first(set, [n])
last(set, [n])
limit(set[, n[, offset]])
Use this to extract a particular entry out of the revset.
When searching forwards (the default), last(follow(file, .)) seems to work nicely to locate the correct revision. As you noted, you have to do this once per file—it will definitely go faster if you write your own Mercurial plug-in to do this without reloading the rest of the system all the time.
Somehow more efficient / more natural solution can be:
create template|style for desired log output (I can't predict, which way will be better for you)
create alias for hg log -l 1 --template ... or hg log -l 1 --style ...
EDIT
A lot later, more correct solution (from recent discoveries) with hg grep
hg grep "." "set:**.py" --files-with-matches -d -q -T"{files % '{file} {date|age}\n'}"
Part of output in test-repo
hggit/__init__.py 7 weeks ago
hggit/git_handler.py 7 weeks ago
hggit/gitdirstate.py 7 weeks ago
…
You have to modify fileset in order to get results only for part of your tree (for all branches) and, maybe, template in order to fulfill your needs.
I didn't have fileset for selecting "files in branch X" just now, I think, it will be something using revs() predicate
"revs(revs, pattern)"
Evaluate set in the specified revisions. If the
revset match multiple revs, this will return file matching pattern in
any of the revision.
because some not published predicates (according to examples, see # "set:revs('wdir()'..." for referencing working directory) can be used for defining revset and I can't discover/predict the correct form for branch predicate

How to update to a branch by name when there's a hash collision?

So my coworker just won the hash lottery. We create a feature branch for every ticket we resolve, following the convention b##### where ##### is the issue number.
The trouble is that when he tried updating to that branch (before it existed) via hg up branch(b29477), it took him to default instead of saying that the branch doesn't exist.
It turns out that branch(b29477) actually returns the name of branch of the thing inside the parens (instead of forcing Mercurial to evaluate the thing inside the parens as a branch name as I thought!), and there so happened to be a changeset beginning with b29477 which was on default, so instead of saying the branch didn't exist, it took him to the tip of default!
Now we can work around this problem by choosing a different branch name, but I want to know if there's any way to hg update <branch_name_and_dont_interpret_this_as_anything_else>?
BTW, hg log also lies about what it's --branch parameter does. It says:
-b --branch BRANCH [+] show changesets within the given named branch
But that's not true at all. Go ahead and run it with a hash. e.g.,
hg log --branch eea844fb
And it will turn up results. If you dig through the docs, you'll discover that it's actually the same as:
hg log -r 'branch(eea844fb)'
Try this:
hg update -r "branch('literal:b29477')"
From the Mercurial help page:
branch(string or set)
All changesets belonging to the given branch or
the branches of the given changesets.
If string starts with re:, the remainder of the name is treated as a
regular expression. To match a branch that actually starts with re:,
use the prefix literal:.
This means that if you use the literal prefix, you are specifying a string. And a string is not a set.
As the text says, if you specify a changeset, Mercurial will show:
the branches of the given changesets

Mercurial - files modified in current branch

Can you help me to create a proper revset for mercurial hg status ?
I would like to list all the files that were changed in the current branch since it was created.
I tried
hg status --rev "branch(foo)"
where foo is the name of my branch, but this also lists files that were changed in the branch from which my branch was created (?).
I don't get how to create a proper revset for this.
I created my branch and made several changes in multiple files. Now I want to reload these files in my application, but only them.
This seems pretty straightforward (see hg help revsets and hg help revisions for where this comes from).
We might start with the set of all commits in a branch, e.g., for branch foo:
-r 'branch(foo)'
Obviously this can produce a dozen, or even a million, revisions; but you want to see what happened between "branch creation"—which needs to examine the parent of the first such revision—and "current status of branch", which needs to examine the last such revision.
The first1 revision of a large set is obtained by first() and the last by last(). However, when various commands are given a revision specifier, they look it up as a single revision, and here a branch name suffices to name the last commit on the branch anyway.
To get the (first) parent of a revision, we use the p1() function (the suffix ^ is only allowed on a literal revision, not a function that returns a revision). Hence the parent of the first revision on branch foo is:
-r 'p1(first(branch(foo)))'
To get a full diff of this against the last commit in the branch:
hg diff -r 'p1(first(branch(foo)))' -r 'foo'
But you don't want a full diff, you want the file names. The command that produces this is hg status, and it has a slightly different syntax:
hg status --rev 'p1(first(branch(foo)))' --rev 'foo'
The status includes the letters at the front, as well as the names: A for newly added files, M for modified files, and so on. Note the use of --rev rather than just -r (in fact, you can use --rev with hg diff as well).
Note that there's a much shorter syntax, ::foo, that gets all the ancestors of the given branch up to and including the last revision in the named branch. However, this gets too many ancestors. You can, however, use p1(first(branch(foo)))::foo as the (entire) argument to --rev, and this also works. so:
hg status --rev 'p1(first(branch(foo)))::foo`
is a slightly shorter way to express this.
Last, note that comparing the first commit in the branch to the last (as would happen with hg status --rev 'first(branch(foo))' --rev foo, for instance) can miss changes made in that first commit on the branch. That's why we use p1 here.
1The first function selects the first in the set, which may not be the same as the numerically-first revision. For instance, suppose the set is made from x | y and a revision in y is numerically lower than a revision in x, or you use reverse(branch(foo)) to put the commits in high-to-low order. In this case, min instead of first would be the function to use.

Mercurial & Keyword ext.: updating keywords when tagging a revision

I'm using Mercurial with the keyword extention, and I'm very pleased with it. Expect one thing, expanding the version tag which is:
Version = {latesttag|nonempty}
All the keywords are expanded as expected on every check in. But when I'm tagging a revision, nothing happens at this moment. I expect/want to expand the tags in all files. Right now the version tag gets updated/expanded on the next commit of a file. I guess, I have to do this with a hook, but i stuck with this.
Any suggestions?
Thank you very much
Roland
Your filter do nothing, because for repository without tags `{latesttag} returns "null" text-string
Keywords in files have "this file" scope, not global, i.e reflect only state at the time of last change of file, and, for tagging (which commit only .hgtags) not changing $Version$ is expected
All the keywords are expanded as expected on every check in
Only for files in this changeset, not included files aren't touched. See at final content of two (originally identical) files in repo
Current version of file: $Version$ and $Revision$
each of which was committed some times separately
>hg log file.txt -l 1
changeset: 5:3ceaea734895
>hg log file2.txt -l 1
changeset: 3:09939c9b8243
file.txt
Current version of file: $Version: v 0.1 $ and $Revision: 3ceaea734895 $
file2.txt
Current version of file: $Version: v 0.1 $ and $Revision: 09939c9b8243 $
If you want to change keywords in all files for every commit, you can|have to include files in questions in every commit (it can be alias, which uses commit -I)

Find all changesets in named branch where file "X" was modified (including merges) [duplicate]

This question already has an answer here:
How do I find the merge that moved my changeset to another branch?
(1 answer)
Closed 9 years ago.
I am looking for a way with TortoiseHg (or plain hg if no other possibility exists) to locate all the changes to a particular file.
I've tried using a revision set query:
merge() and file("path/to/filename.cs")
but that didn't get me what I'm looking for. It returns an empty set. I assume this is because merge() only returns merges, and file() only (appears to) returns non-merges, so the intersection is empty.
I've also tried modifies(pattern) but that doesn't appear sufficiently different from file(pattern) (looks to me like file() is the union of adds() and modifies()). contains(pattern) doesn't return any elements at all.
So, is it possible to get a list of changesets in which a particular file has been modified in any way?
It looks like you're running into the "how did my change get into this branch" problem. When you merge a changeset into a branch, Mercurial doesn't record that as a change. Instead, it makes a note that the merged changeset is now part of the destination branch. The only time a merge will show that a file was modified is if there was a merge conflict, which results in a new changeset.
Finding what merge brought a changeset into a branch is a two step process. First, you have to find the changeset where the change you're interested in occurred.
hg log -r "file('<PATTERN>')
Once you have that revision, find the first descendant changeset in the destination branch:
hg log -r "first(branch(<BRANCH>) and descendants(<REVISION>))"
hg log -r "branch(BRANCH) and file('PATTERN')"
Revset also can be used and entered into Filter Tooolbar in THG Workbench
hg log grep name_of_your_file
Does the trick for me in terms of finding all the change sets that have resulted in a change to a given file. Of course if you would like something pretty:
thg log name_of_your_file