summaryrefslogtreecommitdiff
path: root/git-mirror
diff options
context:
space:
mode:
Diffstat (limited to 'git-mirror')
-rwxr-xr-xgit-mirror86
1 files changed, 56 insertions, 30 deletions
diff --git a/git-mirror b/git-mirror
index d9e1932..113379a 100755
--- a/git-mirror
+++ b/git-mirror
@@ -5,6 +5,8 @@
# terms of the Do What The Fuck You Want To Public License, Version 2,
# as published by Sam Hocevar. See the COPYING file for more details.
+# Depends 4.4+, as it uses the '-d' flag to 'mapfile'.
+#
# Depends on the 'gitget' and 'libremessages' commands. On Parabola
# GNU/Linux-libre, those are the 'gitget' and 'librelib' packages,
# respectively.
@@ -12,8 +14,7 @@
# For other systems, they both live at:
# https://git.parabola.nu/packages/libretools.git/
-set -o pipefail
-set -e
+set -o pipefail -euE
. libremessages
usage() {
@@ -27,18 +28,16 @@ main() {
fi
declare -g cfg_file="$1"
- local r=0
while read -r repo; do
- handle-repo "$repo" || r=$?
+ handle-repo "$repo"
done < <(cfg-list-repos)
- return $r
}
handle-repo() {
[[ $# == 1 ]] || panic
local repo=$1
- local local upstream downstreams downstream r=0
-
+ local local upstream downstreams downstream
+
# read configuration
local="$(cfg-get "repo.$repo.local")"
upstream="$(cfg-get "repo.$repo.upstream")" || true
@@ -46,7 +45,7 @@ handle-repo() {
# download
if [[ -n "$upstream" ]]; then
- download "$upstream" "$local"
+ download "$repo" "$upstream" "$local"
fi
# ensure that $local exists
@@ -54,25 +53,29 @@ handle-repo() {
# upload
for downstream in "${downstreams[@]}"; do
- upload "$local" "$downstream" || r=$?
+ upload "$repo" "$local" "$downstream"
done
-
- return $r
}
download() {
[[ $# == 3 ]] || panic
local repo=$1
- local remote=$2
+ local _remote=$2
local local=$3
+ local IFS='&'
+ local remote=${_remote%%#*}
+ local params=(${_remote#"$remote"})
+
# download the repository
local url
+
url="$(remote "$remote" pull-url)"
- gitget -f -n "$repo" "$url" "$local"
+ gitget -f -n "$repo" bare "$url" "$local"
# download the metadata
- remote "$remote" get-meta > "$local/git-mirror.tmp"
- git config --file "$local/config" --rename-section git-mirror git-mirror-bak
+ msg2 "Fetching metadata for repo '%s'" "$repo"
+ get-meta "$remote" > "$local/git-mirror.tmp"
+ git config --file "$local/config" --rename-section git-mirror git-mirror-bak 2>/dev/null || true
local IFS='='
while read -r key val; do
git config --file "$local/config" --add git-mirror."$key" "$val"
@@ -81,20 +84,19 @@ download() {
git config --file "$local/config" --remove-section git-mirror-bak
}
-upload() {
- [[ $# == 2 ]] || panic
- local local=$1
- local remote=${2%%#*}
- local IFS='&'
- local params=(${2#"$remote"})
+upload() (
+ [[ $# == 3 ]] || panic
+ local repo=$1
+ local local=$2
+ local remote=$3
# push metadata
- {
- printf '%q ' set-meta "${remote#*:}"
- git config --file "$local/config" --get-regexp '^git-mirror[.]' -z|sed -z 's/ /=/'|xargs -0r printf '%q '
- printf '%q ' "${params[@]}"
- } | account "${remote%%:*}"
+ msg2 "Pushing metadata for repo '%s'" "$repo"
+ local meta
+ mapfile -d '' meta < <(git config --file "$local/config" -z --get-regexp '^git-mirror[.]'|sed -z 's/ /=/')
+ set-meta "$remote" "${meta[@]}"
# push repository
+ msg2 "Pushing repo '%s'" "repo"
local repo_mode
repo_mode=$(remote "$remote" repo-mode)
if [[ $repo_mode == passive ]]; then
@@ -102,6 +104,30 @@ upload() {
push_url="$(remote "$remote" push-url)"
cd "$local" && git push --mirror "$push_url"
fi
+)
+
+get-meta() (
+ [[ $# = 1 ]] || panic
+ local _remote=$1
+
+ local IFS='&'
+ local remote=${_remote%%#*}
+ local params=(${_remote#"$remote"})
+
+ remote "$remote" get-meta
+ [[ ${#params[@]} = 0 ]] || printf '%s\n' "${params[@]}"
+)
+
+set-meta() {
+ [[ $# -ge 1 ]] || panic
+ local _remote=$1
+ local args=("${@:2}")
+
+ local IFS='&'
+ local remote=${_remote%%#*}
+ local params=(${_remote#"$remote"})
+
+ remote "$remote" set-meta "${args[@]}" "${params[@]}"
}
# Spawn an 'account.type' helper. It will read commands from stdin.
@@ -109,11 +135,11 @@ account() {
[[ $# == 1 ]] || panic
local account=$1
- local account_type
- account_type="$(cfg-get "account.$account.type")"
+ local type
+ type="$(cfg-get "account.$account.type")"
{
- cfg --list -z|sed -zn "s=^account[.]$account[.]=config =p"|grep -z -v '^type='|xargs -r0 printf '%s\n'
+ cfg --list|sed -n "s=^account[.]$account[.]==p"|grep -v '^type='|xargs -r printf 'config %q\n'
cat
} | git mirror-"$type" "$account"
}
@@ -146,7 +172,7 @@ cfg-get-all() {
cfg-list-repos() {
[[ $# == 0 ]] || panic
- cfg --name-only --get-regexp '^repo[.].*[.].*$' -z|sed -z -e 's|^repo[.]||' -e 's|[.][^.]*$||'|sort -zu|xargs -r0 printf '%s\n'
+ cfg --name-only -z --get-regexp '^repo[.].*[.].*$' |sed -z -e 's|^repo[.]||' -e 's|[.][^.]*$||'|sort -zu|xargs -r0 printf '%s\n'
}
main "$@"