1

I would like to have Mercurial list all tracked files in the repo that are supposed to be symlinks. I can get a list of tracked symlinks that are symlinks in the working copy with hg files "set:symlink()", but that doesn't capture the tracked symlinks that aren't symlinks in the working copy.

What I want instead is a command that looks at the tracked file's properties in the manifest and tells me if the symlink bit is set. I've tried to use hg manifest -v, which the documentation says will "print file permissions, symlink and executable bits". I've tried that, but the symlinks are indistinguishable from non-link files whose executable bit is set. I get lots of:

755 * path/to/file

If I try to use the leading markers (hg manifest -v | grep '755 *'), the files I want are listed, but I also get lots of false positives.

Background: Adding and committing symbolic links seems to work for us, but Mercurial is refusing to create the symlinks when someone else pulls those changesets. I understand why Mercurial is refusing: we run afoul of an undocumented rule. So now we end up with files where the symlinks are supposed to be, and the content of the file is the path to which the symlink is supposed to point. If I can get Mercurial to tell me which files are supposed to be symlinks, I can easily replace the files with the appropriate links.

Thank you!

Edit: In my repository, the symlinks had not been committed properly due to a bug in the client, which is why hg manifest -v wasn't showing the committed files as links.

3 Answers3

1

I've learned a few things, and I wasn't asking the right question, but let's get the close-enough answer out of the way first:

hg manifest -v | grep ' @ '

Caveat: I will guess that it's possible for manifest to put multiple symbols between the permissions number and the path, so ' @ ' as the grep expression may not work perfectly if you have an exotic set of bits on a file. I needed the spaces around the @ because our repository has many files with @ in their names.

The rest of the story: After some experimentation, I was able to determine that a particular mercurial GUI (SourceTree) wasn't committing new symlinks correctly, which turned out to be a longstanding issue with the Mac version. I created a new repo (hg init) and added/committed one target file and one symlink (Link\link.txt) with command-line hg. I then added/committed a second symlink (Link\STlink.txt) with SourceTree. hg manifest -v shows that the links were not treated the same by the different clients:

755 * Link/STlink.txt
644 @ Link/link.txt
644   Target/target.txt

If I clone that repo, even with SourceTree, the Link/link.txt symlink is reproduced faithfully, but the Link\STlink.txt link is not. So the real fix for me is to replace all of the files with links and commit again from the command line and to try to remember not to use SourceTree to commit new symlinks again in the future.

0

To assess which files changed from symlink to 'normal files', you could try to throw some bash at it and compare the output of the fileset of the modified and unmodified versions. Maybe something like

diff <(hg files "set:symlink()" -r.) <(hg files "set:symlink()")

Example:

In a repository where eeg-link was added, foo22-link changed to a normal file and foo edited (and foo-link kept pointing at it):

$ hg diff
diff --git a/eeg-link b/eeg-link
new file mode 120000
--- /dev/null
+++ b/eeg-link
@@ -0,0 +1,1 @@
+eeg
\ No newline at end of file
diff --git a/foo b/foo
--- a/foo
+++ b/foo
@@ -1,2 +1,3 @@
foo is boo!
And this change, too!
+And even this.
diff --git a/foo22-link b/foo22-link
old mode 120000
new mode 100644
--- a/foo22-link
+++ b/foo22-link
@@ -1,1 +1,1 @@
-foo22
\ No newline at end of file
+This is no symlink anymore

we get a nice and clean output of

$ diff <(hg files "set:symlink()" -r.) <(hg files "set:symlink()")
0a1
> eeg-link
2d2
< foo22-link

showing the newly-added symlinks (eeg-link) and the removed symlink (foo22-link).

planetmaker
  • 5,884
  • 3
  • 28
  • 37
  • Thank you! Your solution would be good for a repository where a user was changing files on purpose and you wanted to see the changes. I discovered this morning that my problem was actually that the files were being added/committed improperly by the GUI tool, meaning "set:symlink" would never see them. – Scott Ventura Jun 07 '17 at 15:33
0

I can get a list of tracked symlinks that are symlinks in the working copy with hg files "set:symlink()", but that doesn't capture the tracked symlinks that aren't symlinks in the working copy.

In case it’s not clear from the other answers, the basic answer to the question is (ignoring any complications induced by bugs outside of Mercurial’s control) to add the -r option to hg files, e,g,

hg -r tip files 'set:symlink()'
peak
  • 105,803
  • 17
  • 152
  • 177