gitolite/src/commands/fork
Sitaram Chamarty 198dcfd4c8 POST_CREATE efficiency... (please read below if you care)
The POST_CREATE trigger is called when

  * a user creates a new "wild" repo,
  * a user uses the "perms" command, and
  * a user uses the "fork" command.

The trigger calls 3 programs (see rc file):

    post-compile/update-git-configs
    post-compile/update-gitweb-access-list
    post-compile/update-git-daemon-access-list

(They are also called by the POST_COMPILE trigger, by the way.)

However, the 3 programs shown are a bit wasteful -- they run through
*all* the repos when really only *one* repo has been affected.

This patch

  * passes the repo name to the 3 programs (duh!)

  * adds the optimisation to the first of the 3 programs listed above
    (the one dealing with 'git config').

For the other two programs (gitweb and git-daemon), you have 3 choices:

  * if you don't have too many repos, ignore the problem.

  * take out the 2nd and 3rd lines from the POST_CREATE list in the rc
    file, so they don't run.

    Then run 'gitolite trigger POST_COMPILE' from cron at regular
    intervals.  (Note that is POST_COMPILE not POST_CREATE!)  However,
    this means that gitweb and daemon permissions won't be current
    immediately after someone adds a new repo or sets perms etc.; they
    get updated only on the next cron run.

  * patch the programs to add this optimisation (and send me the
    patches).  The optimisation would check if arg-1 ($1 in shell,
    $ARGV[0] in perl) is 'POST_CREATE', and if it is, take the *next*
    argument as a repo name that may have changed.
2012-04-22 22:44:39 +05:30

63 lines
2.3 KiB
Bash
Executable file

#!/bin/sh
# Usage: ssh git@host fork <repo1> <repo2>
#
# Forks repo1 to repo2. You must have read permissions on repo1, and create
# ("C") permissions for repo2, which of course must not exist.
#
# A fork is functionally the same as cloning repo1 to a client and pushing it
# to a new repo2. It's just a little more efficient, not just in network
# traffic but because it uses git clone's "-l" option to share the object
# store also, so it is likely to be almost instantaneous, regardless of how
# big the repo actually is.
#
# The only caveat is that the repo you cloned *from* must not later become
# unavailable in any way. If you cannot be sure of this, take the scenic
# route (clone repo1, push to repo2).
die() { echo "$@" >&2; exit 1; }
usage() { perl -lne 'print substr($_, 2) if /^# Usage/../^$/' < $0; exit 1; }
[ -z "$1" ] && usage
[ "$1" = "-h" ] && usage
[ -z "$GL_USER" ] && die GL_USER not set
# ----------------------------------------------------------------------
from=$1; shift
to=$1; shift
[ -z "$to" ] && usage
gitolite access -q "$from" $GL_USER R any || die "'$from' does not exist or you are not allowed to read it"
gitolite access -q "$to" $GL_USER ^C any || die "'$to' already exists or you are not allowed to create it"
# ----------------------------------------------------------------------
# IMPORTANT NOTE: checking whether someone can create a repo is done as above.
# However, make sure that the env var GL_USER is set, and that too to the same
# value as arg-2 of the access command), otherwise it won't work.
# Ideally, you'll leave such code to me. There's a reason ^C is not listed in
# the help message for 'gitolite access'.
# ----------------------------------------------------------------------
# clone $from to $to
git clone --bare -l $GL_REPO_BASE/$from.git $GL_REPO_BASE/$to.git
[ $? -ne 0 ] && exit 1
echo "$from forked to $to" >&2
# fix up creator, default role permissions (gl-perms), and hooks
cd $GL_REPO_BASE/$to.git
echo $GL_USER > gl-creator
if gitolite query-rc -q DEFAULT_ROLE_PERMS
then
gitolite query-rc DEFAULT_ROLE_PERMS > gl-perms
fi
ln -sf `gitolite query-rc GL_ADMIN_BASE`/hooks/common/* hooks
# record where you came from
echo "$from" > gl-forked-from
# trigger post_create
gitolite trigger POST_CREATE $to $GL_USER