Two way git mirror: Difference between revisions

From Arianne
Jump to navigation Jump to search
imported>Hendrik Brummermann
Created page with "== Motivation == == Setup == == Mirror == We use the following script to do the actually mirroring. It can be invoked with the name of a known repository as parameter or wi..."
imported>Hendrik Brummermann
Created page with "== Motivation == == Setup == == Mirror == We use the following script to do the actually mirroring. It can be invoked with the name of a known repository as parameter or wi..."
(No difference)

Revision as of 02:08, 28 December 2015

Motivation

Setup

Mirror

We use the following script to do the actually mirroring. It can be invoked with the name of a known repository as parameter or with the "--all" flag.

#!/bin/bash

function sync_repo {
    cd /srv/gitsync
    cd $1
    echo $1
    # fetch all known remotes
    git fetch --all -p
    # push branches from sourceforge to github and via versa.
    git push github "refs/remotes/sourceforge/*:refs/heads/*"
    git push sourceforge "refs/remotes/github/*:refs/heads/*"
}

cd /srv/gitsync
if [ "$1" == "" ]; then
    # no command line parameters, print help message
    echo "gitsync [report]|--all"
elif [ "$1" == "--all" ]; then
    # "--all": for all known repositories
    for D in *; do
       if [ -d "${D}" ]; then
             sync_repo $D
             cd /srv/gitsync
       fi
    done
elif [ -d "$1" ]; then
    # sync only the specified repository
    sync_repo $1
else echo "gitsync [report]|--all"
fi

In function sync_repo the branches from remotes named github and sourceforge are pushed to each other. You can more mappings here.


As discussed in the previous section, we use webhooks to initiate a mirroring run on every push. This is achieved by the following php script:

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
	die('POST required');
}

if (!isset($_REQUEST['repository'])) {
	die('repository not specified');
}

// validate repository name to prevent injection and traversing attacks
$repo = $_REQUEST['repository'];
if (!preg_match('/^[a-zA-Z0-9]$/', $repo)) {
	die('invalid repository name');
}

header('HTTP/1.0 204 Found');
system('sudo -Hu gitsync /usr/local/bin/gitsync '.$repo);


Security

  • It is important to validate the repository name in order to prevent shell command injection, git parameter injection and directory traversing
  • We use sudo to execute gitsync as user gitsync. Thus the webserver process does not require write access to the repositories
  • Both Sourceforge and Github support a secret to authorize webhook invocations. In the above example this is not verified, so anyone can trigger a sync.

Deleting branches