print all versions of a file in Mercurial - mercurial

I would like to print all versions of a file, including renaming.
hg cat -r rev file can be used to print a single revision, and hg log --template '{rev} ' -f file can be used to print all revisions id of the file. Iterating over all revs is simple enough, but:
The problem is renaming. When file was called oldfile in a previous revision 123, hg log gives us the number 123, but hg cat -r 123 file does not work, because you need hg cat -r 123 oldfile. How can a script get the arguments needed for cat from the log?

Related

How can I list all (new) added files between two change sets in mercurial?

How can I list all (new) added files between two change sets in mercurial?
I can use hg status --rev x:y to get all changes between two revisions, but what if I only want to get the new files?
hg help revsets + hg help templates for hg log -r … -T … command
"x::y"
A DAG range, meaning all changesets that are descendants of x and ancestors of y,
including x and y themselves.
Good correct range
file_adds
List of strings. Files added by this changeset
Keyword for template
>hg log -T {file_adds}\n
file3.txt file4.txt
file2.txt
file1.txt
(last changeset added 2 files)
>hg log -T "{file_adds % '{file}\n'}"
file3.txt
file4.txt
file2.txt
file1.txt
with just added formatting of list

Mercurial: Identify file name after rename

Mercurial tracks the contents of a file throughout renames (hg mv $OLD $NEW), so that hg annotate $NEW also shows up the line-wise changes formerly made to $OLD with their original identification. That works fine.
BUT there seems no straightforward way to find out the name of the $OLD file, to which some given line has belonged within the ancestry of $NEW. hg annot $NEW -r$REV only works down to the rename changeset.
Of course the information is somehow accessible, e. g. by crawling through hg log (without --follow) and identifying the renames with some hg log -r$RENAMEREV -g -p (or by clicking through hg serve's web interface).
But this “workflow” is not only annoying and error-prone, but [most importantly] it isn't non-interactive/scriptable.
My question: Is there a way to get/construct either
some list of the file name history of $NEW (best with respective revision ranges), or
the name of the file in which line $LINE was commited (some kind of filename option for hg annot)?
Ideas in either the hg CLI or Python/hglib appreciated.
Either include the {file_copies} keyword in your hg log template:
$ hg init demo
$ cd demo
$ touch a
$ hg ci -Am 'file a'
adding a
$ hg mv a b
$ hg ci -Am 'moved to file b'
$ hg log -r . -T"{file_copies}\n"
b (a)
The built-in template status will include file copy info when you set the --copies flag:
$ hg log -r 1 -Tstatus --copies
changeset: 1:b37952faaddc
tag: tip
user: Martijn Pieters <mjpieters#fb.com>
date: Sun Jul 31 16:07:04 2016 +0100
summary: moved to file b
files:
A b
a
R a
So file b was taken from a.
See hg help template for more things you can include in log output.

Is there a way to see the most recent Mercurial revision for each file in a directory?

When you do hg log on a file, only the revisions that underwent changes are listed. I'd like to see what the most recent revision for all of the files in a directory is. (Think hg blame at a file level rather than a line level.)
I had thought that hg log -l 1 * might work, but it just shows the most recent revision across all of the files.
Here's the kind of output I'd like to see:
> hg blame --files
foo: 15
bar: 2
baz: 15
README: 1
Another alternative is to use a combination of hg status and hg log, like this:
for FILE in $(hg status -nA); do
hg log -l1 --template '{rev}\t' "$FILE"
echo $FILE
done
I suspect that if you want to use hg directly to do this, you'll need to write an extension (but I'm by no means an expert here). But would something like this work, if you're willing to use a script?
for x in *; do
highest=`hg blame "$x" 2>/dev/null | cut -d : -f 1 | sort -nr | head -n1`
if [ "$highest" ]; then echo "$x: $highest" ; fi
done
The obvious downside here is that this is pretty slow.

how to view previous version of a file in Mercurial

I am using mercurial for version control of a few files in a directory. Suppose I have 10 commits (10 changesets or revisions). I want to just view how a particular file, say thisFile.py, looked in its 7th revision. I don't want to revert back to this older version. I don't want to go and make any changes or fix any bugs in this previous version. I simply want to see it, without affecting the latest version of the file or the mercurial history in any way. Is there a simple way to do it?
Use the hg cat command with the -r (revision) argument.
hg cat path_to/myfile.cpp -r 46
where 46 is the revision number (use hg log to see revision history)
hg cat [OPTION]... FILE...
Print the specified files as they were at the given revision.
If no revision is given, the parent of the working directory is used,
or tip if no revision is checked out.
Output may be to a file, in which case the name of the file is given
using a format string. The formatting rules are the same as for the
export command, with the following additions:
%s: basename of file being printed
%d: dirname of file being printed, or '.' if in repository root
%p: root-relative path name of file being printed
Returns 0 on success.
options:
-o, --output print output to file with formatted name
-r, --rev print the given revision
--decode apply any matching decode filter
-I, --include include names matching the given patterns
-X, --exclude exclude names matching the given patterns
To extract a specific revision of a specific file you can do this in Windows:
hg cat "<FileToBeExtractedPath>" -r 9 > "<ExtractionPath>"
Here, 9 is the revision number.
Or even better:
hg cat "<FileToBeExtractedPath>" -r 9 -o "<ExtractionPath>"

How to use `hg cat` from an empty working directory?

I have a repo located at x:/projects/repo1. The working directory has been emptied using hg update null. I want to extract the latest version of some files from there to a local directory.
I tried this:
x:\projects\repo1> hg cat -o c:\sql\%s scripts\*.sql -r tip
I get this error:
scripts\*.sql: No such file in rev 14f07c26178b
The same command works fine if the working directory is not empty. Is there a good reason why this does not work? Or do you know another way of extract some files from there to a local directory?
The hg cat command is for single files. If you want multiple files use the hg archive command, which makes zipfiles or directories full of files. Here's your command:
x:\projects\repo1> hg archive --include scripts\*.sql -r tip c:\sql
It seems that hg cat doesn't support wildcard symbols in paths. So you should use the full file name:
hg cat -r tip scripts/foo.sql
When your working copy is up to date with the tip revision, your shell does wildcard substitution for you.
The hg manifest command also might be helpful for getting tracked file listings.
This answer is to your comment on Andrey's answer:
hg manifest takes a --rev argument that you can use to see the list of all files in your repository:
hg manifest --rev tip
To get the list of files matching a pattern at the tip, use:
hg stat --all --include *.sql --rev tip --no-status
hg stat -A -I *.sql --rev tip -n # using abbreviations.
From there you could redirect the output to a file and edit each line into a hg cat command like in your original question. It appears (to me, at least, having done some experimentation) that hg cat uses the contents of the working directory -- rather than the contents of the repository at the revision specified -- for glob-matching, so once you know the exact name of the file, you can hg cat it at any revision.