diff options
Diffstat (limited to 'server')
-rwxr-xr-x | server/mrrepo | 84 |
1 files changed, 81 insertions, 3 deletions
diff --git a/server/mrrepo b/server/mrrepo index 5e7d0fb..aae1e54 100755 --- a/server/mrrepo +++ b/server/mrrepo @@ -6,7 +6,23 @@ # # Will first download (via http or https if -s specified) the manifest file # from git.example.org which should list all publicly available repositories. -# It will then mirror each repository in /var/scm using the git protocol. +# It will then mirror each remote repository in /var/scm locally, using the +# git protocol. +# +# Afterwards it may mirror it further to a remote repository that can be +# specified in the manifest file. If mirroring via https, then you also most +# likely need to provide credentials for the remote https URLs in the +# mrrepo-config file. This file should be placed next to and will be sourced +# by the mrrepo script (remember to adjust its permissions). +# +# The manifest file line format (lines starting with # are ignored): +# +# <repository-path>[ <remote-mirror-url>] +# +# To specify another credential for a URL add the following line to +# mrrepo-config: +# +# credentials['<https-url-prefix>']='<user>:<password>' # # -v # Run verbose. @@ -68,6 +84,19 @@ if [ ! -d "$path" ]; then error "$path is not a directory" fi +declare -A credentials +config="$(realpath "${BASH_SOURCE[0]}")-config" + +if [ -f "$config" ]; then + source "$config" + + for p in "${!credentials[@]}"; do + if [ "${p:0:8}" != "https://" ]; then + error "https protocol is expected for '$p' in '$config'" + fi + done +fi + cd "$path" curl_ops=() @@ -93,10 +122,44 @@ function fetch () # <url> [<curl-options>] fetch "$prot://$host/manifest" -z manifest -o manifest +function field () # <line> <num> [<name>] +{ + local r + r="$(echo "$1 " | cut -d ' ' -f "$2")" + + if [ "$3" -a -z "$r" ]; then + error "field <$3> (#$2) missing in '$1'" + fi + echo "$r" +} + +# Collect new repositories (in the new array) and while at it fix up remote +# URLs with credentials (in the remotes map). +# new=() -while read r || [ -n "$r" ]; do +declare -A remotes + +while read l || [ -n "$l" ]; do + r=$(field "$l" 1 'path') + u=$(field "$l" 2) + new+=("$r") -done <manifest + + # If the remote URL is specified then add credentials into it, if found. + # Note that currently we only support adding credentials for https URLs. + # + if [ -n "$u" ]; then + for p in "${!credentials[@]}"; do + if [[ "$u" == "$p"* ]]; then + c="${credentials[$p]}" + u="$(echo "$u" | sed 's%^\(https://\)\(.*\)$%\1'"$c"'@\2%')" + break; + fi + done + + remotes["$r"]="$u" + fi +done < <(sed -e '/^\s*#/d;/^\s*$/d;s/\s\s*/ /g' manifest) # Find all the existing repositories (directories that end with .git). # @@ -135,6 +198,21 @@ for r in "${new[@]}"; do # fetch "$prot://$host/$r/description" -z "$r/description" -o "$r/description" fi + + # Mirror to the remote URL, if present. + # + u="${remotes[$r]}" + if [ -n "$u" ]; then + if [ "$verb" -ge 1 ]; then + info "remote URL $u for repository $r, pushing" + info git -C "$r" push "${git_ops[@]}" --mirror "$u" + fi + + # Disable prompting for username/password if credentials are missing for + # the remote URL and fail instead. + # + GIT_TERMINAL_PROMPT=0 git -C "$r" push "${git_ops[@]}" --mirror "$u" + fi done # Remove old repositories. |