repo-cloner/mirror-recursive

114 lines
2.6 KiB
Bash
Executable File

#!/bin/bash
#
# Mirror git repository with submodules - recursively
#
# Usage:
# mirror-recursive <main repo url> [<depth=1000>]
# strict mode
set -euo pipefail
IFS=$'\n\t'
# Scratch - temp
tmpdir=$(mktemp -d -t mirror-recursive-XXXXXXX)
function finish {
rm -rf "$tmpdir"
}
trap finish EXIT
source $(dirname $(realpath $0))/config
source $(dirname $(realpath $0))/gen-mirror-path
function progress(){
local progress=${1:-100}
echo -n "..$progress%"
if [ $progress -eq 100 ]
then
echo
fi
}
function submoduleDiscovery(){
# main parameters
local repo=$1
local gitdir=$(getRepoPath $repo)
# depth (empty or prefixed from main script)
local depth=${2:-}
# temporary path
local tmpname=$(getRepoUniq $repo)
tmpname=$tmpdir/$tmpname
local tmpCommitList=$tmpname.commits
local tmpSubmoduleList=$tmpname.submodules
# cache paths
local cachePath=$(getRepoCache $repo)
local cacheCommits=$cachePath/commits-checked
local cacheSubmodules=$cachePath/submodules-checked
# check, if cache exists
[ -d $cachePath ] || mkdir -p $cachePath
[ -f $cacheCommits ] || touch $cacheCommits
[ -f $cacheSubmodules ] || touch $cacheSubmodules
# avoid recursion - if commit list exists
# there was activity with this run recently
if [ ! -f $tmpCommitList ]
then
# cache submodules reuse
cat $cacheSubmodules > $tmpSubmoduleList
echo -n "Discovering submodules of $repo.. "
git --git-dir $gitdir log --all $depth --format="%H" | sort > $tmpCommitList
# check against cache
echo -n "cache check.."
comm -13 $cacheCommits $tmpCommitList > $tmpname
mv $tmpname $tmpCommitList
local commits=$(wc -l $tmpCommitList | cut -d' ' -f1)
echo -n "$commits commits"
# this can take long time...
local processed=0
local nextStamp=$(($(date +"%s") + 3))
while read -r line || [[ -n "$line" ]]
do
submodule-describe $gitdir $line | cut -f 3 >> $tmpSubmoduleList
# progress indication
processed=$(($processed + 1))
if [ $(date +"%s") -gt $nextStamp ]
then
progress $((100*$processed/$commits))
nextStamp=$(($nextStamp + 3))
fi
done < $tmpCommitList
# finish the bar
progress
# archive to cache
cat $tmpCommitList $cacheCommits > $tmpname
sort $tmpname > $cacheCommits
sort $tmpSubmoduleList | uniq > $tmpname
cat $tmpname > $cacheSubmodules
# Recursion++
while read -r submodule || [[ -n "$submodule" ]]
do
mirror-main-repo $submodule
submoduleDiscovery $submodule $depth
done < $cacheSubmodules
fi
}
# main repo
mainrepo=$1
depth=${2:-}
[ -n "$depth" ] && depth="-$depth"
# Make first mirror
mirror-main-repo $mainrepo
submoduleDiscovery $mainrepo $depth