Merge pull request #1121 from AladW/fix-json-search
[aurutils.git] / lib / aur-fetch--mirror
blobc2e5bc035c93fbdaff5bf82a3ca129da87d37858
1 #!/bin/bash
2 set -o errexit
3 [[ -v AUR_DEBUG ]] && set -o xtrace
4 #argv0=fetch--mirror
5 XDG_CACHE_HOME=${XDG_CACHE_HOME:-$HOME/.cache}
6 AUR_MIRROR=${AUR_MIRROR:-https://github.com/archlinux/aur}
7 AUR_MIRROR_TTL=${AUR_MIRROR_TTL:-300}
8 AUR_MIRROR_BRANCH=${AUR_MIRROR_BRANCH:-main}
9 AUR_ROOT=${AUR_ROOT:-$XDG_CACHE_HOME/aur}
10 startdir=$PWD
11 local_clones=0
13 # Avoid CDPATH screwing with cd (#1047)
14 unset -v CDPATH
16 if [[ $1 = '--lclone' ]]; then
17 local_clones=1
18 shift
20 mkdir -p -- "$AUR_ROOT"
22 # --------------------------------------------------
23 # Step 1. Create a sparse checkout of the AUR mirror
24 git_active_remotes() {
25 git config --get-all remote.origin.fetch | awk -F'[/:]' '{print $3}'
28 # XXX: this includes refs/heads (which we do not use) but unlike
29 # git-config this accepts multiple arguments in one call
30 git_set_branches() {
31 git remote set-branches origin --add "$AUR_MIRROR_BRANCH" # ensure at least 1 remote
32 sort -u | xargs -d '\n' git remote set-branches origin
35 git_ls_remote_ttl() {
36 local cachetime now ttl=$AUR_MIRROR_TTL
37 printf -v now '%(%s)T' -1
39 if ! cachetime=$(stat -c %Y "$1" 2>/dev/null) || (( now > (cachetime + ttl) )); then
40 git ls-remote origin 'refs/heads/*' | awk -F/ '{print $3}' >"$1"
44 exec {fd}< "$AUR_ROOT"
45 { flock --wait 5 "$fd" || exit 1
46 cd -- "$AUR_ROOT"
48 # Shallow clone
49 if [[ ! $(git rev-parse --is-inside-git-dir 2>/dev/null) ]]; then
50 git init --bare --initial-branch="$AUR_MIRROR_BRANCH"
51 git remote add origin "$AUR_MIRROR"
54 # Keep a refcache to filter out packages which are not in AUR. This is
55 # includes unlisted packages (unlike `aur pkglist --pkgbase`)
56 git_ls_remote_ttl 'remote-pkgbase'
58 # Retrieve list of active remotes
59 mapfile -t active_remotes < <(git_active_remotes | grep -v "$AUR_MIRROR_BRANCH")
61 # Only consider AUR targets
62 mapfile -t target_remotes < <(printf '%s\n' "$@" | grep -Fxf 'remote-pkgbase')
64 # Set remote branches as union of active remotes and arguments. If '*' is set
65 # instead, `git fetch origin` in $AUR_ROOT will pull in the entire history.
66 printf '%s\n' "${target_remotes[@]}" "${active_remotes[@]}" | git_set_branches
68 # Retrieve objects
69 if (( ${#target_remotes[@]} )); then
70 git fetch origin "${target_remotes[@]}"
73 # Resetting branches is only needed when .git/config contains both refs/heads
74 # and refs/remotes/origin, i.e. when using git-clone. `--lclone` uses git-init
75 # and refspec manipulation instead.
76 # for b in "${target_remotes[@]}"; do
77 # git branch --force "$b" origin/"$b"
78 # done
79 } >&2
81 # ------------------------------------------------------------
82 # Step 2. Propagate each branch in the mirror to a local clone
83 (( ! local_clones )) && exit
84 results=()
86 git_srcdest_origin() {
87 local refspec=refs/remotes/origin/$1
89 git config remote.origin.fetch "+$refspec:$refspec"
90 git fetch --quiet
91 git checkout --quiet -B master "$refspec"
94 for b in "${target_remotes[@]}"; do
95 cd -- "$startdir"
97 # XXX: "Cloning into an existing directory is only allowed if the
98 # directory is empty"
99 if [[ ! -d $b/.git ]] && mkdir -- "$b"; then
100 cd -- "$b"
101 git init --quiet
102 git remote add origin "$AUR_ROOT"
104 # Compared to git clone --local, using $refspec as both source and
105 # destination allows updates from `git-fetch` in $AUR_ROOT to be
106 # directly visible in local clones. $AUR_ROOT does not require
107 # local branches or refs/heads for this to work.
108 git_srcdest_origin "$b"
110 # Export results to aur-fetch
111 head=$(git rev-parse --verify --quiet HEAD)
112 results+=("$b:$head")
113 fi >&2
114 done
116 # The lock is only released here, because we do not want an instance to modify
117 # AUR_ROOT while local git-clones are still underway. Additionally, local clones
118 # use cp(1) and are thus a cheap operation. See --local in git-clone(1).
119 exec {fd}<&-
121 if (( ${#results[@]} )); then
122 printf '%s\n' "${results[@]}"