Get rid of "nameless" node in mercurial repository - mercurial

I found a nameless node in my mercurial repository.
On executing the tag listing command "hg tags" as part of the generated output, I find the same node mentioned twice.
The output of hg tags command contains the following duplicate nodes:
xyz_release_tag daa262c10
daa262c10
In one of the entries, the node has a name but the other entry the node does not have a name.
I am in the process of migrating the mercurial repository to git and I am using fast-export to do the conversion.
The presence of this "nameless" node causes errors during the conversion process. Similar issue has been discussed at: https://github.com/frej/fast-export/issues/1.
As a quick workaround, I made a quick change to my local repository cache file. There is a file by name "tags2-visible" that gets created after I run the hg tags command for listing. Once I modify this file to remove the entry for the nameless node, it disappears and the conversion process succeeds.
I am not very sure if this is the right way to do it or if at all there is any other way.
Any thoughts ?

Resulting quickfix:
hg tags # Creates .hg/cache/tags2-visible
# Fix the nameless tag
sed -rie 's/^([^ ]+) $/\1 \1/' .hg/cache/tags2-visible
How I came to the solution:
$ hg tags | tail -3
PRODUCION_18032010 216:3e0a6415bbde
166:809065c08005
PRODUCION 125:d98f65c06bac
$ # Where is the problem?
$ grep -r 809065c08005
.hg/cache/tags2-visible:809065c08005ef2d261f10f72f17ea5fcd1e7540
$ # Add " test" to the end of this line
$ sed -i .hg/cache/tags2-visible -e 's/809065c08005ef2d261f10f72f17ea5fcd1e7540/809065c08005ef2d261f10f72f17ea5fcd1e7540 test/'
$ # Checking the edition
$ grep -r 809065c08005
.hg/cache/tags2-visible:809065c08005ef2d261f10f72f17ea5fcd1e7540 test
$ # Checking the validity of the hack
$ hg tags | tail -3
PRODUCION_18032010 216:3e0a6415bbde
test 166:809065c08005
PRODUCION 125:d98f65c06bac
After editing .hg/cache/tags2-visible adding a label to the branch fast-export worked for me.
Anyone see any problem in editing .hg/cache/tags2-visible in this way?

Related

How can I pipe a GitHub CLI command into an xargs Git command?

Background: I file pull requests to an upstream repo which I’m not a maintainer of. I want to delete my local and remote branches from which I filed those PRs and which have been merged/closed. I want to do this in one swoop from the terminal.
Steps taken: I use the GitHub CLI to check which of my branches have been merged/closed upstream, for example, with gh pr list -A author -s merged --json 'headRefName'. Then I pipe this into jq -r '.[].headRefName' in order to get a list of branch names that have been merged.
One result of running the command is: patch-36
But when I pipe these results into xargs git branch -d, I get: error: branch 'patch-36?' not found. The problem seems to be that a question mark is being inserted with the last piping.
Goal: How can I prevent the question mark being added to the input of xargs git branch -d?
Output of cat -t: patch-36^M
OS: Windows 10
Terminal: Powershell & Git Bash

mercurial diff + unxutil "patch"

How do you make the mercurial "diff" command produce output that is compatible with the unix or unxutil patch command?
I need to create a patch file that I can send to a coworker who doesn't have Mercurial installed.
I've tried using hg diff -r 3:5 > patch1.diff and I get an error from the patch command when applying it. (hold on, I will post the error message as soon as I have a chance....)
OK, here is a test case that I've uploaded to bitbucket:
hg clone https://bitbucket.org/jason_s/test-patch-apply P2base
hg update -r 2 -R P2base
hg diff -r 2:4 -R P2base > p2base.patch
rm -r P2base/.hg
cd P2base
patch < ../p2base.patch
I get this on my Windows PC:
C:\tmp\hg\P2base>patch < ../p2base.patch
patching file bar.txt
Assertion failed: hunk, file ../patch-2.5.9-src/patch.c, line 354
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
Never mind, this is a documented problem (with a REALLY POOR ERROR MESSAGE) that can be overcome. From http://gnuwin32.sourceforge.net/packages/patch.htm :
On MS-Windows, the patchfile must be a text file, i.e. CR-LF must be
used as line endings. A file with LF may give the error: "Assertion
failed, hunk, file patch.c, line 343," unless the option '--binary' is
given.
I used --binary and it worked fine.

How to stop tracking a file without deleting it on Mercurial

I saw this thread which discusses a solution for git, and found this thread on the mailing list for Mercurial (the thread is four years old though)
The solution proposed in the mailing list is to use hg rm -Af file (and they leave open the possibility of implementing this behavior as a new, more intuitive option). I'm wondering if that option exists now.
Also, if I try the command above:
> hg rm -Af my_file
> hg st
R my_file
there is an R next to my_file, but the file my_file is technically on disk, and I have told Mercurial to stop tracking it, so why am I getting R next to it?
You can just use hg forget or maybe add the file to your .hgignore file
And to answer the last question about the R in my_file. If you see the help for hg rm --help:
hg remove [OPTION]... FILE...
aliases: rm
remove the specified files on the next commit
Schedule the indicated files for removal from the current branch.
This command schedules the files to be removed at the next commit. To undo
a remove before that, see "hg revert". To undo added files, see "hg
forget".
Returns 0 on success, 1 if any warnings encountered.
options:
-A --after record delete for missing files
-f --force remove (and delete) file even if added or modified
-I --include PATTERN [+] include names matching the given patterns
-X --exclude PATTERN [+] exclude names matching the given patterns
[+] marked option can be specified multiple times
use "hg -v help remove" to show more info
As you can see you are forcing the deletion of that file and that's why you can see the R (Removed)

Is there an equivalent to git's "describe" function for Mercurial?

I'm currently adding packaging to a something that is maintained in Mercurial. Currently the version is defined in the Makefile. I would like to change this so I can build daily packages or properly versioned packages.
Git provides a use "describe" function that can give you a description of the closest tagged build and current revision. For example if I run this in the kernel:
git describe HEAD
GIT returns:
v3.0-rc7-68-g51414d4
telling me that the revision is later than v3.0-rc7, with a git commitish of 51414d4
Is there something similar I can do in Mercurial?
Maybe something like this?
hg log -r . --template '{latesttag}-{latesttagdistance}-{node|short}\n'
Of course you should make an alias for that with AliasExtension.
Note however, unlike "git describe", this command will always show the "latesttagdistance" and "node|short" parts, instead of omitting them when latesttagdistance is 0.
This is a close emulation of git describe:
hg log -r . -T "{latesttag}{sub('^-0-.*', '', '-{latesttagdistance}-m{node|short}')}"
The {sub(...)} function ensures that a working copy that's exactly at tag v0.1.0 will show up as v0.1.0 and not v0.1.0-0-m123456789abc.
Note that the m before the hash is for mercurial, similar to the way git describe uses a g for git.
For convenience, create an alias by adding the following to your ~/.hgrc:
[alias]
describe = log -r . -T "{latesttag}{sub('^-0-.*', '', '-{latesttagdistance}-m{node|short}')}"
Then use the alias by simply typing hg describe.
If you'd like to emulate git describe --dirty, things get even messier – but you can still hide it all in an hg alias:
[alias]
describe = !
dirtymark=;
case " $1 " in " --dirty ") dirtymark=-dirty; ;; esac;
echo $($HG log -r . --template "{latesttag}-{latesttagdistance}-m")$($HG id -i) |
sed -r -e "s/\+\$/${dirtymark}/" -e 's/-0-m[[:xdigit:]]+//'
Now running hg describe --dirty will produce strings like:
v0.1.0
v0.1.0-dirty
v0.1.0-1-mf6caaa650816
v0.1.0-1-mf6caaa650816-dirty
Omitting the --dirty option means that you'll never get a -dirty suffix like (2) and (4), even when the working copy contains uncommitted changes.

Using mercurial to manage linux kernel, tags, and hg id

Anybody using mercurial to manage a linux kernel? This is a bit long, but I'm not sure if there's an answer to this. I wanted to give some examples for help
Here's what I'm seeing:
Within the linux kernel, there's a command used when building called scripts/setlocalversion. Inside this script, it sets the kernel version based on the repository information. Currently, it understands git, mercurial, and svn repo's.
For git, it creates the tag with this code:
if head=`git rev-parse --verify --short HEAD 2>/dev/null`; then
# If we are at a tagged commit (like "v2.6.30-rc6"), we ignore it,
# because this version is defined in the top level Makefile.
if [ -z "`git describe --exact-match 2>/dev/null`" ]; then
# If we are past a tagged commit (like "v2.6.30-rc5-302-g72357d5"),
# we pretty print it.
if atag="`git describe 2>/dev/null`"; then
echo "$atag" | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}'
.....
So, here's an example I did to understand how this works:
[1536][mcrowe:test]$ git tag -a -m"Creating a tag" KernelTest
[1537][mcrowe:test]$ git rev-parse --verify --short HEAD
d024e76
[1537][mcrowe:test]$ git describe --exact-match
KernelTest
[1537][mcrowe:test]$ git describe
KernelTest
So, in this example, the local version would be set to "KernelTest" when the kernel builds.
In mercurial, however, the code to get the local version is this:
if hgid=`hg id 2>/dev/null`; then
tag=`printf '%s' "$hgid" | cut -d' ' -f2`
# Do we have an untagged version?
if [ -z "$tag" -o "$tag" = tip ]; then
id=`printf '%s' "$hgid" | sed 's/[+ ].*//'`
printf '%s%s' -hg "$id"
fi
....
My expectation was that I could tag a release, and have that tag be what this script uses, as happens in git. However, it appears that "hg id" never prints out the tag like this script expects:
[1546][mcrowe:test2]$ hg tag -m"Creating a tag" KernelTest -r tip
[1548][mcrowe:test2]$ hg id
3ccda5e738ae+ tip
[1548][mcrowe:test2]$ hg tags
tip 115:3ccda5e738ae
KernelTest 114:be25df80ce76
So that act of tagging changes the revision so hg id will never show what the tag is.
Core Question: AFAIK, this would never work for the linux kernel. The question is how should this be implemented in the kernel tree to allow hg tag to perform like git tag?
Try doing:
hg log -r . --template '{latesttag}'
I think that does what you want.
There's also {latesttagdistance} which can let you know you're N commits past a tag for handy version string.