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.

Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
Faheem Mitha
  • 34,649
  • 32
  • 119
  • 183
  • 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](http://unix.stackexchange.com/users/885/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.)

Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
  • 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