0

We have a hook setup on our remote repositories to automatically update the repo after it receives a push. It works great except when we locally delete a file and then push. We receive messages like this:

remote:  local changed path/to/file/file.ext which remote deleted
remote: use (c)hanged version or (d)elete? c

It automatically pickes 'c'. Is there a way for us to have Mercurial use 'd' and delete the file instead?

Here are the hooks, also posted in the comments but hopefully linebreaks are preserved here:

[hooks]

changegroup = hg update >&2

incoming = /path/filename.sh > /dev/null 2>&1

The .sh file resets some permissions after the hg update.

mrceolla
  • 51
  • 1
  • 5

2 Answers2

0

The error message means "Your local working copy contains modified files which the update tries to delete."

If you run "hg st" on the remote server (i.e. inside of the remote repository), you should see modified files. Note that changing the permission of a file is considered a change.

So what happens is this:

  • Your local Mercurial pushes the files to the remote repository
  • The hook changes file in the remote repository (by modifying their permissions).
  • Someone tries to delete one of those files

Mercurial always tries to prevent data loss, so the default option is "preserve local changes" (because you can always delete those files later if you want to but you might not be able to restore them).

What can you do?

  • Instead of "fixing" the permissions on the remote repo, refuse to accept change sets with wrong permissions. That is, instead of fixing the permissions, check them in a pretxnchangegroup hook. If the permissions are wrong, abort. That way, you can't push as long as the permissions are broken. Docs.

  • Instead of modifying the working copy, copy the files into a new place and change the permissions there. This wastes some disk space (but not as much as you'd think if you use soft or hard links) but it separates concerns (special permissions from versioned files).

[EDIT]

New files, added locally then pushed to the remote repo, loose execute permissions.

They don't lose it, they didn't have it in the first place: Windows doesn't support this Unix feature.

Unfortunately, you can't tell Mercurial to set the bit from Windows.

To fix this properly, use this approach:

  1. Add and push files from Windows as before
  2. Create a cron job on the Unix server which checks the permissions and sends an email fi they are wrong.
  3. When the email comes in, connect to the Unix server and fix the permissions
  4. Commit and push the changes from Unix.

Mercurial will preserve the execute bit if you modify the file on Windows.

I suggest to put the last two steps into a script. I don't think you can completely automate it; the script will (often?) fail when someone pushes a change while it runs.

PS: I've filed a feature request asking for a better solution: Provide a way to modify the Unix permissions from Windows

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
  • Thank you for the information. We push from Windows machines to Red Hat. We test the files via a Red Hat virtual machine on our Windows boxes and all the permissions are fine there. However once they make it to the remote Red Hat server they are no longer correct. I don't know why this is. We actually do use links however the permissions are always the same in both locations. What am I missing? And is there simply no way to change Mercurial's default behavior in this situation and allow it to delete the 'modified' files? Thank you. – mrceolla Oct 11 '12 at 13:20
  • How do the permissions change? – Aaron Digulla Oct 11 '12 at 13:52
  • New files, added locally then pushed to the remote repo, loose execute permissions. – mrceolla Oct 11 '12 at 17:44
  • Ah, that's what I wanted to know. – Aaron Digulla Oct 12 '12 at 08:47
  • Thank you Aaron for that input and also filing that feature request. How would one go about checking permissions and acting on incorrect permissions? If we can figure that out and only modify the problem files then we may have a solution here. We want this fully automated. It appears the problem w/ our current approach is that all files have permissions reapplied after a push. This must mark all files as modified even if the permissions didn't 'change'. Does that sound correct? Does re-applying the exact same permissions mark the file as 'modified' to Mercurial? – mrceolla Oct 15 '12 at 19:51
  • It's hard to say without the sources of the "fix" script. But Mercurial can only notice when permissions change, it can't tell when you reapply the same permissions. Try to fix the permissions once on Unix and commit there. – Aaron Digulla Oct 16 '12 at 07:34
  • Thank you again for your reply. I'm not sure this would add anything to the conversation but the 'fix' script contains a line like this (chmod -R +x /path/to/repo/*). I haven't messed with changing Windows permissions to see if a change is detected, but I know I can change the file an infinite number of times, and if the contents of the file are still the same as the previous commit (by undoing my infinite number of changes; ctrl-z), Mercurial does not detect any modifications. When I do an hg status on my remote repo there are TONS of 'M' files which have been unedited since the beginning. – mrceolla Oct 16 '12 at 19:06
  • Windows doesn't have an `x` permission (or you could say that every file on Windows is executable by default). So the command above changes every file in the repository as far as Mercurial is concerned. So **as I said several times now**: Fix the permissions on Unix **once** then **commit on Unix** and the problem will go away. And you shouldn't make **every** file executable either; **just change the permissions of the scripts and executables**. – Aaron Digulla Oct 17 '12 at 07:25
0

A co-worker has pointed this out to me, which may be our solution:

https://bz.mercurial-scm.org/show_bug.cgi?id=3302

https://www.mercurial-scm.org/repo/hg/rev/95e45abe7e8e

We haven't tried yet but I will report back after we do.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
mrceolla
  • 51
  • 1
  • 5