1

The context of this question is the hg-ssh script. It is helpful but not critical to know something about Mercurial. This script sets up a forced command using public keys so the given public key setup on the server will only allow the owner of the corresponding private key to push to a permitted set of repositories on the server. This forced commands is usually prefixed to the public key in the file ~/.ssh/authorized_keys on the server. With regard to this permitted set, the documentation before the script in the link above says:

You can use pattern matching of your normal shell, e.g.:
command="cd repos && hg-ssh user/thomas/* projects/{mercurial,foo}"

The idea is to permit only pushing to repositories on the server that match this pattern. I've been using hg-ssh with the forced command

command="cd /srv/hg && /usr/local/bin/hg-ssh * */* */*/* */*/*/*",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa [...]

to match all repositories (up to some number of path components) under /srv/hg, using shell globbing. I belatedly realized that it is not matching paths which contain components starting with .. My current non-working example is the MQ repository /srv/hg/faheem/bixfile/.hg/patches. So, my question is, can I select a pattern that corresponds to all paths? I would prefer to use shell globbing, which are less of a headache than regular expressions in general, but I'd take a regular expression if globbing is not an option.

Faheem Mitha
  • 35,108
  • I was kindly pointed to http://unix.stackexchange.com/questions/6393/how-do-you-move-all-files-including-hidden-in-a-directory-to-another by Gilles. I wonder if sticking in a shopt -s dotglob before the command would work. – Faheem Mitha Jul 03 '11 at 21:09

1 Answers1

2

For recursive matching, the right tool is often find. Since you want to match all files in the current directory and its subdirectories recursively, but only down to a certain depth, specify -maxdepth. This isn't in POSIX, but exists on all current *BSD and in GNU find (Linux, Cygwin) and in Busybox (embedded Linux) so it's a safe bet that you have it. -exec … {} + is a relatively recent addition to POSIX, but it's been in GNU and FreeBSD/NetBSD/OSX for a while now.

cd /srv/hg && find . -type d -maxdepth 3 -exec /usr/local/bin/hg-ssh {} +

(I added -type d because you seem to want to match directories only, even though your attempt with * */* etc. matches files of all types.)

  • Ok, thanks. How would this look exactly, in the context of the script as posted above, ie command="cd /srv/hg && /usr/local/bin/hg-ssh * */* */*/* */*/*/*",no-port-forwarding,...? Does everything up to the curly brackets go inside the command? Also, really, the idea is to match only the directories, not the files, since a repository can only correspond to a directory, and not a file. – Faheem Mitha Jul 03 '11 at 21:20
  • @FaheemMitha Everything, from cd to +, is the shell command. I copied what you did, matching all files regardless of type. If you want to match only directories, add -type d before -exec. But I wonder if this is really what you want (note that I know nothing about hg-ssh): are you looking for .hg directories? – Gilles 'SO- stop being evil' Jul 03 '11 at 21:25
  • No, all directories are possible Mercurial repositories. The example I gave (/srv/hg/faheem/bixfile/.hg/patches) is the special case of a MQ repository, which lives inside the .hg directory corresponding to another Mercurial repository. I tried it and got remote: find: Expected a positive decimal integer argument to -mindepth, but got '-maxdepth'. Can one just leave mindepth out, or does it need to be given a number? – Faheem Mitha Jul 03 '11 at 21:42
  • It works if I take out -mindepth, but does it then default to mindepth 1? I'm currently using command="cd /srv/hg && find . -maxdepth 4 -type d -exec /usr/local/bin/hg-ssh {} +". – Faheem Mitha Jul 03 '11 at 21:50
  • @FaheemMitha I meant -mindepth 1 to exclude . (depth 0), but I guess you want to include it? So no -mindepth. – Gilles 'SO- stop being evil' Jul 03 '11 at 21:55
  • Well, any directory under /srv/hg is a possible match. So, level 0 would correspond to matching /srv/hg/foo for some directory foo, yes? And excluding mindepth means depth goes from 0 up? BTW, can you add a link to the -exec … {} + syntax, please? Thanks. – Faheem Mitha Jul 03 '11 at 22:01
  • @FaheemMitha Depth 0 is what you pass to find, here . (which is /srv/hg). Depth 1 is ./*, depth 2 is ./*/*, etc. So /srv/hg/foo is at depth 1 here. I've added a link to the POSIX spec of find. – Gilles 'SO- stop being evil' Jul 03 '11 at 22:17
  • Ok, then I guess I want searches at depth 1 and lower. – Faheem Mitha Jul 03 '11 at 22:27