3 [[ -v AUR_DEBUG
]] && set -o xtrace
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}
13 # Avoid CDPATH screwing with cd (#1047)
16 if [[ $1 = '--lclone' ]]; then
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
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
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
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
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"
81 # ------------------------------------------------------------
82 # Step 2. Propagate each branch in the mirror to a local clone
83 (( ! local_clones
)) && exit
86 git_srcdest_origin
() {
87 local refspec
=refs
/remotes
/origin
/$1
89 git config remote.origin.fetch
"+$refspec:$refspec"
91 git checkout
--quiet -B master
"$refspec"
94 for b
in "${target_remotes[@]}"; do
97 # XXX: "Cloning into an existing directory is only allowed if the
99 if [[ ! -d $b/.git
]] && mkdir
-- "$b"; then
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")
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).
121 if (( ${#results[@]} )); then
122 printf '%s\n' "${results[@]}"