Jim Hunziker
Jim Hunziker

Reputation: 15380

Setting up Mercurial for members of a unix group

I have a Mercurial repository set up on a Linux server, and some (but not all) users have permission to push to it. They connect to the repository over ssh.

These users are members of a unix group together. Below is the script I'm using to alter a repository to allow it to receive pushes from them.

Can this be improved? Are there unnecessary operations in here? Is anything bad style for a bash script?

#!/bin/bash                                                                     

if [[ $# -lt 2 ]]; then
    echo Usage: $0 directory groupname
    exit 1
fi

if ! chown -R :$2 $1; then
    echo chown failure
    exit 2
fi

if ! find $1/.hg -type d -exec chmod g+s {} \;; then
    echo chmod failure
    exit 3
fi

if ! find $1 -perm -u+r -exec chmod g+r {} \;; then
    echo chmod failure 2
    exit 4
fi

if ! find $1 -perm -u+w -exec chmod g+w {} \;; then
    echo chmod failure 3
    exit 5
fi

if ! find $1 -perm -u+x -exec chmod g+x {} \;; then
    echo chmod failure 4
    exit 6
fi

Upvotes: 1

Views: 472

Answers (2)

Ry4an Brase
Ry4an Brase

Reputation: 78330

Running find with -exec launches a separate chown process for each file. You'll get a lot less process thrash (and more speed) if you do:

find "$1"/.hg -type d -print0 | xargs chmod g+s
find "$1" -perm -u+r -print0 | xargs chmod g+r
find "$1" -perm -u+w -print0 | xargs chmod g+w
find "$1" -perm -u+x -print0 | xargs chmod g+x

As an aside, have you looked at Mercurial's ACL Extension in combination with hg-ssh? So long as the only access is ssh, it does the same sort of thing.

Upvotes: 1

John Kugelman
John Kugelman

Reputation: 361585

Couple minor things: It's a good idea to echo error messages to stderr by redirecting with >&2. And you should add double quotes around variables so your script will work with file names that have spaces.

You could change the initial line to #!/bin/bash -e to have the script immediately exit if there's an error. That'd let you remove all the if statements. Or if you want more control you could use the trap ERR command to call custom error-handling code:

#!/bin/bash

function uhoh() {
    echo "error in script!" >&2
    exit 1
}

trap uhoh ERR

if [[ $# -lt 2 ]]; then
    echo "Usage: $0 directory groupname" >&2
    exit 1
fi

chown -R :"$2" "$1"
find "$1"/.hg -type d -exec chmod g+s {} \;
find "$1" -perm -u+r -exec chmod g+r {} \;
find "$1" -perm -u+w -exec chmod g+w {} \;
find "$1" -perm -u+x -exec chmod g+x {} \;

Personally I'd just go with the /bin/bash -e option if you want to stop the script as soon as something fails. I think checking the result of every command and having a different exit code for each one is overkill. You don't need to be that robust, and nobody's gonna be doing anything different for exit code 3 vs. exit code 4...

Upvotes: 1

Related Questions