Full Code of falconindy/asp for AI

master 2a1cd19332ec cached
12 files
24.2 KB
7.6k tokens
1 requests
Download .txt
Repository: falconindy/asp
Branch: master
Commit: 2a1cd19332ec
Files: 12
Total size: 24.2 KB

Directory structure:
gitextract_1nhrilat/

├── .gitignore
├── LICENSE
├── Makefile
├── README.md
├── archweb.inc.sh
├── asp.in
├── man/
│   └── asp.1.txt
├── package.inc.sh
├── remote.inc.sh
├── shell/
│   ├── bash-completion
│   └── zsh-completion
└── util.inc.sh

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
asp
asp.1


================================================
FILE: LICENSE
================================================
Copyright (c) 2014 Dave Reisner

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.



================================================
FILE: Makefile
================================================
PACKAGE_NAME = asp

VERSION := $(shell git describe --dirty 2>/dev/null)

PREFIX = /usr/local

BINPROGS = \
	asp

MANPAGES = \
	man/asp.1

BASH_COMPLETION = \
	shell/bash-completion

ZSH_COMPLETION = \
	shell/zsh-completion

INCLUDES = \
	archweb.inc.sh \
	package.inc.sh \
	remote.inc.sh \
	util.inc.sh

all: $(BINPROGS) $(MANPAGES)

V_GEN = $(_v_GEN_$(V))
_v_GEN_ = $(_v_GEN_0)
_v_GEN_0 = @echo "  GEN     " $@;

edit = $(V_GEN) m4 -P $@.in | sed 's/@ASP_VERSION@/$(VERSION)/' >$@ && chmod go-w,+x $@

%: %.in $(INCLUDES)
	$(edit)

doc: $(MANPAGES)
man/%: man/%.txt Makefile
	$(V_GEN) a2x \
		-d manpage \
		-f manpage \
		-a manversion="$(PACKAGE_NAME) $(VERSION)" \
		-a manmanual="$(PACKAGE_NAME) manual" $<

check: $(BINPROGS)
	@for f in $(BINPROGS); do bash -O extglob -n $$f; done

lint: $(BINPROGS)
	@for f in $(BINPROGS); do shellcheck $$f; done

clean:
	$(RM) $(BINPROGS) $(MANPAGES)

install: all
	install -dm755 $(DESTDIR)$(PREFIX)/bin $(DESTDIR)$(PREFIX)/share/man/man1
	install -m755 $(BINPROGS) $(DESTDIR)$(PREFIX)/bin
	install -m644 $(MANPAGES) $(DESTDIR)$(PREFIX)/share/man/man1
	install -Dm644 $(BASH_COMPLETION) $(DESTDIR)$(PREFIX)/share/bash-completion/completions/asp
	install -Dm644 $(ZSH_COMPLETION) $(DESTDIR)$(PREFIX)/share/zsh/site-functions/_asp

.PHONY: all clean install


================================================
FILE: README.md
================================================
> [!CAUTION]
> **THIS REPO IS ARCHIVED**
> 
> In the context of the [git migration](https://archlinux.org/news/git-migration-announcement/) using `asp` has been deprecated in favor of `pkgctl` or plain `git`.
> 
> For details see the respective wiki entry: https://wiki.archlinux.org/title/Arch_build_system#Retrieve_PKGBUILD_source

---

# asp

`asp` is a tool to manage the build source files used to create Arch Linux
packages. It replaces the `abs` tool, offering more up to date sources (via the
svntogit repositories) and uses a sparse checkout model to conserve diskspace.
This probably won't be interesting to users who want a full checkout (for
whatever reason that may be).

# Setup

None! Though, it should be noted that the `ASPROOT` environment variable
will control where `asp` keeps its local git repo. By default, this is
`${XDG_CACHE_HOME:-$HOME/.cache}/asp`.

# Examples

Get the source files for some packages:

~~~
asp export pacman testing/systemd extra/pkgfile
~~~

Get a fully functional git checkout of a single package:

~~~
asp checkout pkgfile
~~~

List the repositories a package has been pushed to:

~~~
asp list-repos pacman
~~~



================================================
FILE: archweb.inc.sh
================================================
archweb_get_pkgbase() {
  local pkgbase

  pkgbase=$(curl -LGs 'https://archlinux.org/packages/search/json/' --data-urlencode "q=$1" |
      jq -r --arg pkgname "$1" 'limit(1; .results[] | select(.pkgname == $pkgname).pkgbase)')
  [[ $pkgbase ]] || return

  printf '%s\n' "$pkgbase"
}


================================================
FILE: asp.in
================================================
#!/bin/bash

ASP_VERSION=@ASP_VERSION@
ARCH_GIT_REPOS=(packages community)

OPT_ARCH=$(uname -m)
: "${ASPROOT:=${XDG_CACHE_HOME:-$HOME/.cache}/asp}"
: "${ASPCACHE:=$ASPROOT/cache}"

m4_include(util.inc.sh)
m4_include(remote.inc.sh)
m4_include(package.inc.sh)
m4_include(archweb.inc.sh)

usage() {
  cat<<EOF
asp $ASP_VERSION [OPTIONS...] {COMMAND} ...

Manage build sources for Arch packages.

Options:
  -a           ARCH        Specify an architecture other than the host's
  -h                       Show this help
  -V                       Show package version

Package Commands:
  checkout           NAME...     Create a mutable git repository for packages
  difflog            NAME        Show revision history with diffs
  export             NAME...     Export packages
  list-all                       List all known packages
  list-arches        NAME...     List architectures for packages
  list-local                     List tracked packages
  list-repos         NAME...     List repos for packages
  log                NAME        Show revision history
  ls-files           NAME        List files for package
  shortlog           NAME        Show revision history in short form
  show               NAME [FILE] Show the PKGBUILD or other FILE
  untrack            NAME...     Remove a package from the local repository
  update             [NAME...]   Update packages (update all tracked if none specified)

Meta Commands:
  disk-usage                     Show amount of disk used by locally tracked packages
  gc                             Cleanup and optimize the local repository
  help                           Show this help
  set-git-protocol   PROTO       Change git protocol (one of: git, http, https)

EOF
}

__require_argc() {
  local min max argc=$2

  case $1 in
    *-)
      min=${1%-}
      ;;
    *-*)
      IFS=- read -r min max <<<"$1"
      ;;
    *)
      min=$1 max=$1
      ;;
  esac

  if (( min == max && argc != min )); then
    log_fatal '%s expects %d args, got %d' "${FUNCNAME[1]#action__}" "$min" "$argc"
  elif (( max && argc > max )); then
    log_fatal '%s expects at most %d args, got %d' "${FUNCNAME[1]#action__}" "$max" "$argc"
  elif (( argc < min )); then
    log_fatal '%s expects at least %d args, got %d' "${FUNCNAME[1]#action__}" "$min" "$argc"
  fi
}

version() {
  printf 'asp %s\n' "$ASP_VERSION"
}

update_all() {
  local r

  for r in "${ARCH_GIT_REPOS[@]}"; do
    log_info "updating remote '%s'" "$r"
    remote_update "$r"
  done
}

update_local_branches() {
  local r=0

  while read -r branchname; do
    git branch -qf "$branchname" "refs/remotes/$branchname" || r=1
  done < <(git branch --no-color)

  return "$r"
}

update_remote_branches() {
  local refspecs=() remote pkgname
  declare -A refspec_map

  if (( $# == 0 )); then
    update_all
    return
  fi

  # map packages to remotes
  for pkgname; do
    package_init -n "$pkgname" remote || return 1
    refspec_map["$remote"]+=" packages/$pkgname"
  done

  # update each remote all at once
  for remote in "${!refspec_map[@]}"; do
    read -ra refspecs <<<"${refspec_map["$remote"]}"
    remote_update_refs "$remote" "${refspecs[@]}"
  done
}

update_packages() {
  update_remote_branches "$@" && update_local_branches
}

initialize() {
  local remote url

  umask 0022

  export GIT_DIR=$ASPROOT/.git

  if [[ ! -f $ASPROOT/.asp ]]; then
    git init -q "$ASPROOT" || return 1
    for remote in "${ARCH_GIT_REPOS[@]}"; do
      git remote add "$remote" "https://github.com/archlinux/svntogit-$remote.git" || return 1
    done

    touch "$ASPROOT/.asp" || return 1
  else
    # migrate from git.archlinux.org to github.com
    for remote in "${ARCH_GIT_REPOS[@]}"; do
      url=$(git remote get-url "$remote")
      # https://github.blog/2021-09-01-improving-git-protocol-security-github/
      if [[ $url = *'git.archlinux.org'* ]] || [[ $url = *'git://github.com'* ]]; then
        git remote set-url "$remote" "https://github.com/archlinux/svntogit-$remote.git"
      fi
    done
  fi

  if [[ ! -d $ASPCACHE ]]; then
    mkdir -p "$ASPCACHE" || return 1
  fi

  return 0
}

dump_packages() {
  local remote refspecs dumpfn

  case $1 in
    all)
      dumpfn=remote_get_all_refs
      ;;
    local)
      dumpfn=remote_get_tracked_refs
      ;;
    *)
      log_fatal 'BUG: invalid dump type: "%s"' "$1"
      ;;
  esac

  for remote in "${ARCH_GIT_REPOS[@]}"; do
    "$dumpfn" "$remote" refspecs
    if [[ $refspecs ]]; then
      printf '%s\n' "${refspecs[@]##*/}"
    fi
  done | sort
}

list_local() {
  dump_packages 'local'
}

list_all() {
  dump_packages 'all'
}

shortlog() {
  package_log "$@" "${FUNCNAME[0]}"
}

log() {
  package_log "$@" "${FUNCNAME[0]}"
}

difflog() {
  package_log "$@" "${FUNCNAME[0]}"
}

gc() {
  git gc --prune=all
}

untrack() {
  local pkgname=$1 remote

  package_init -n "$pkgname" remote || return 1

  remote_untrack "$remote" "$pkgname"
  package_untrack "$pkgname" "$remote"
}

disk_usage() {
  local usage
  read -r usage _ < <(du -sh "$ASPROOT")

  log_info 'Using %s on disk.' "$usage"
}

action__checkout() {
  __require_argc 1- $#
  map package_checkout "$@"
}

action__difflog() {
  __require_argc 1 $#
  difflog "$1"
}

action__disk-usage() {
  __require_argc 0 $#
  disk_usage
}

action__export() {
  __require_argc 1- $#
  map package_export "$@"
}

action__gc() {
  __require_argc 0 $#
  gc
}

action__help() {
  __require_argc 0 $#
  usage
}

action__list-all() {
  __require_argc 0 $#
  list_all
}

action__list-arches() {
  __require_argc 1- $#
  map package_get_arches "$@"
}

action__list-local() {
  __require_argc 0 $#
  list_local
}

action__list-repos() {
  __require_argc 1- $#
  map package_get_repos "$@"
}

action__log() {
  __require_argc 1 $#
  log "$1"
}

action__shortlog() {
  __require_argc 1 $#
  shortlog "$1"
}

action__show() {
  __require_argc 1-2 $#
  package_show_file "$@"
}

action__untrack() {
  __require_argc 1- $#
  map untrack "$@"
}

action__update() {
  update_packages "$@"
}

action__ls-files() {
  __require_argc 1 $#

  package_list_files "$1"
}

action__set-git-protocol() {
  __require_argc 1 $#

  case $1 in
    git|http|https)
      ;;
    *)
      log_fatal 'invalid protocol: %s' "$1"
      ;;
  esac

  for remote in "${ARCH_GIT_REPOS[@]}"; do
    git remote set-url "$remote" "$1://github.com/archlinux/svntogit-$remote.git"
  done
}

dispatch_action() {
  local candidates

  [[ $1 ]] || log_fatal 'no action specified (use -h for help)'

  # exact match
  if declare -F "action__$1" &>/dev/null; then
    "action__$1" "${@:2}"
    return
  fi

  # prefix match
  mapfile -t candidates < <(compgen -A function "action__$1")
  case ${#candidates[*]} in
    0)
      log_fatal 'unknown action: %s' "$1"
      ;;
    1)
      "${candidates[0]}" "${@:2}"
      return
      ;;
    *)
      {
        printf "error: verb '%s' is ambiguous; possibilities:" "$1"
        printf " '%s'" "${candidates[@]#action__}"
        echo
      } >&2
      return 1
      ;;
  esac
}

initialize || log_fatal 'failed to initialize asp repository in %s' "$ASPROOT"

case $1 in
  --version)
    version
    exit 0
    ;;
  --help)
    usage
    exit 0
    ;;
esac

while getopts ':a:hV' flag; do
  case $flag in
    a)
      OPT_ARCH=$OPTARG
      ;;
    h)
      usage
      exit 0
      ;;
    V)
      version
      exit 0
      ;;
    \?)
      log_fatal "invalid option -- '%s'" "$OPTARG"
      ;;
    :)
      log_fatal "option '-%s' requires an argument" "$OPTARG"
      ;;
  esac
done
shift $(( OPTIND - 1 ))

dispatch_action "$@"


================================================
FILE: man/asp.1.txt
================================================
/////
vim:set ts=4 sw=4 syntax=asciidoc noet:
/////
asp(1)
======

Name
----
asp - Manage Arch Linux build sources

Synopsis
--------
asp [options] command [targets...]

Description
-----------
Manage the version-controlled sources for the build scripts used to create Arch
Linux packages. This program provides a thin wrapper over the svntogit
repositories hosted at https://github.com/archlinux. It aims to provide a
replacement for abs which favors a sparse checkout.

Commands
--------
The following commands are understood:

*checkout* 'TARGET'...::
	Create a new git repository containing the full source and history
	for each of the given targets. The new repository will pull from the
	repository in '$ASPROOT' and must be updated separately after using
	'asp update'. If a checkout occurs on the same filesystem as '$ASPROOT',
	most of the metadata can be hard linked, making this a relatively cheap
	copy.

*difflog* 'TARGET'::
	Show the full revision history of the target, with file diffs.

*disk-usage*::
	Report the approximate disk usage for locally tracked packages.

*export* 'TARGET'...::
	Dump the build source files for each target into a directory of the
	target's name in '$PWD'. Targets can be specified simply as 'package' to
	check out the source files at HEAD, or in 'repository/package' format
	to checkout the source files which were used to push the 'package' which
	exists in 'repository'.

*gc*::
	Perform housekeeping procedures on the local repo, optimizing and
	compacting the repo to free disk space.

*help*::
	Display the command line usage and exit.

*list-all*::
	List all known packages in the repositories.

*list-arches* 'TARGET'...::
	List the architectures the given targets are available for.

*list-local*::
	List all packages which are tracked locally.

*list-repos* 'TARGET'...::
	List the repositories the given targets exist in.

*log* 'TARGET'::
	Show the revision history of the target.

*ls-files* 'TARGET'::
	List source files for the given target.

*set-git-protocol* 'PROTOCOL'::
	Set the protocol used to communicate with the remote git repositories. Must
	be one of 'git', 'http', or 'https'.

*shortlog* 'TARGET'::
	Show a condensed revision history of the target.

*show* 'TARGET' ['FILE']::
	Show the file content of the target, which may be in the format 'package'
	or 'repository/package'. If an additional 'file' argument is provided, attempt
	to display that file rather than the PKGBUILD. If the repository is not
	specified, the file will be shown at the most recent revision (which may be
	newer than what is in the repositories).

*untrack* 'TARGET'...::
	Remove a remote tracking branch from the local repository. Disk usage for
	the removed package(s) may not be freed until garbage collection has taken
	place.

*update* ['TARGET'...]::
	For each target, if the package is not known to the local repository,
	attempt to track it. If the package is tracked, update the package
	to the newest version. If no targets are provided, all locally known
	packages will be updated.

Options
-------
*-a* 'architecture'::
	When relevant, specify an architecture other than that of the current host.

*-h*::
	Print a short help text and exit.

*-V*::
	Print a short version string and exit.

Environment
-----------
*ASPROOT*::
	Determines where the metadata is stored for locally tracked packages. Defaults
	to '`${XDG_CACHE_HOME:-$HOME/.cache}/asp`'.

*ASPCACHE*::
	Determines where cached data is stored. Defaults to '$ASPROOT/cache'. Data in
	this directory can always be safely deleted.

Authors
-------
Dave Reisner <d@falconindy.com>


================================================
FILE: package.inc.sh
================================================
package_resolve() {
  local pkgbase

  [[ $pkgname ]] || log_fatal 'BUG: package_resolve called without pkgname var set'

  if package_find_remote "$1" "$2"; then
    return 0
  fi

  if pkgbase=$(archweb_get_pkgbase "$1") && package_find_remote "$pkgbase" "$2"; then
    log_info '%s is part of package %s' "$1" "$pkgbase"
    pkgname=$pkgbase
    return 0
  fi

  log_error 'unknown package: %s' "$pkgname"
  return 1
}

package_init() {
  local do_update=1

  if [[ $1 = -n ]]; then
    do_update=0
    shift
  fi

  pkgname=$1

  package_resolve "$pkgname" "$2" || return

  (( do_update )) || return 0

  remote_is_tracking "${!2}" "$pkgname" ||
      remote_update_refs "${!2}" "packages/$pkgname"
}

package_find_remote() {
  pkgname=$1

  # fastpath, checks local caches only
  for r in "${ARCH_GIT_REPOS[@]}"; do
    if remote_is_tracking "$r" "$pkgname"; then
      printf -v "$2" %s "$r"
      return 0
    fi
  done

  # slowpath, needs to talk to the remote
  for r in "${ARCH_GIT_REPOS[@]}"; do
    if remote_has_package "$r" "$pkgname"; then
      printf -v "$2" %s "$r"
      return 0
    fi
  done

  return 1
}

package_log() {
  local method=$2 logargs remote
  pkgname=$1

  package_init "$pkgname" remote || return

  case $method in
    shortlog)
      logargs=('--pretty=oneline')
      ;;
    difflog)
      logargs=('-p')
      ;;
    log)
      logargs=()
      ;;
    *)
      log_fatal 'BUG: unknown log method: %s' "$method"
      ;;
  esac

  git log "${logargs[@]}" "$remote/packages/$pkgname" -- trunk/
}

package_show_file() {
  local file=${2:-PKGBUILD} remote repo subtree
  pkgname=$1

  if [[ $pkgname = */* ]]; then
    IFS=/ read -r repo pkgname <<<"$pkgname"
  fi

  package_init "$pkgname" remote || return

  if [[ $file != */* ]]; then
    if [[ $repo ]]; then
      subtree=repos/$repo-$OPT_ARCH/
    else
      subtree=trunk/
    fi
  fi

  git show "remotes/$remote/packages/$pkgname:$subtree$file"
}

package_list_files() {
  local remote subtree=trunk
  pkgname=$1

  if [[ $pkgname = */* ]]; then
    IFS=/ read -r repo pkgname <<<"$pkgname"
  fi

  package_init "$pkgname" remote || return

  if [[ $repo ]]; then
    subtree=repos/$repo-$OPT_ARCH
  fi


  git ls-tree -r --name-only "remotes/$remote/packages/$pkgname" "$subtree" |
      awk -v "prefix=$subtree/" 'sub(prefix, "")'
}

package_export() {
  local remote repo arch=$OPT_ARCH arches subtree=trunk
  pkgname=$1

  if [[ $pkgname = */* ]]; then
    IFS=/ read -r repo pkgname <<<"$pkgname"
  fi

  package_init "$pkgname" remote || return

  if [[ $repo ]]; then
    mapfile -t arches < <(package_get_arches "$pkgname")
    if (( ${#arches[*]} == 1 )) && [[ ${arches[0]} = any ]]; then
      arch=any
    fi
    subtree=repos/$repo-$arch
  fi

  if ! git show "remotes/$remote/packages/$pkgname:$subtree/" &>/dev/null; then
    if [[ $repo ]]; then
      log_error "package '%s' not found in repo '%s-%s'" "$pkgname" "$repo" "$OPT_ARCH"
      return 1
    else
      log_error "package '%s' has no trunk directory!" "$pkgname"
      return 1
    fi
  fi

  mkdir "$pkgname" || return

  log_info 'exporting %s:%s' "$pkgname" "$subtree"
  git archive --format=tar "remotes/$remote/packages/$pkgname" "$subtree/" |
      tar --transform "s,^$subtree,$pkgname," -xf - "$subtree/"
}

package_checkout() {
  local remote
  pkgname=$1

  package_init "$pkgname" remote || return

  git show-ref -q "refs/heads/$remote/packages/$pkgname" ||
      git branch -qf --no-track {,}"$remote/packages/$pkgname"

  quiet_git clone \
    --shared \
    --single-branch \
    --branch "$remote/packages/$pkgname" \
    --config "pull.rebase=true" \
    "$ASPROOT" "$pkgname" || return
}

package_get_repos_with_arch() {
  local remote=$2 path arch repo
  pkgname=$1

  while read -r path; do
    path=${path##*/}
    repo=${path%-*}
    arch=${path##*-}
    printf '%s %s\n' "$repo" "$arch"
  done < <(git ls-tree --name-only "remotes/$remote/packages/$pkgname" repos/)
}

package_get_arches() {
  local remote arch
  declare -A arches
  pkgname=$1

  package_init "$pkgname" remote || return

  while read -r _ arch; do
    arches["$arch"]=1
  done < <(package_get_repos_with_arch "$pkgname" "$remote")

  printf '%s\n' "${!arches[@]}"
}

package_get_repos() {
  local remote repo
  declare -A repos
  pkgname=$1

  package_init "$pkgname" remote || return

  while read -r repo _; do
    repos["$repo"]=1
  done < <(package_get_repos_with_arch "$pkgname" "$remote")

  printf '%s\n' "${!repos[@]}"
}

package_untrack() {
  local remote=$2
  pkgname=$1

  if git show-ref -q "refs/heads/$remote/packages/$pkgname"; then
    git branch -D "$remote/packages/$pkgname"
  fi
}


================================================
FILE: remote.inc.sh
================================================
__remote_refcache_update() {
  local remote=$1 cachefile=$ASPCACHE/remote-$remote refs

  refs=$(git ls-remote "$remote" 'refs/heads/packages/*') ||
      log_fatal "failed to update remote $remote"

  printf '%s' "$refs" |
      awk '{ sub(/refs\/heads\/packages\//, "", $2); print $2 }' >"$cachefile"
}

__remote_refcache_is_stale() {
  local now cachetime cachefile=$1 ttl=3600

  printf -v now '%(%s)T' -1

  # The cache is stale if we've exceeded the TTL.
  if ! cachetime=$(stat -c %Y "$cachefile" 2>/dev/null) ||
      (( now > (cachetime + ttl) )); then
    return 0
  fi

  # We also consider the cache to be stale when this script is newer than the
  # cache. This allows upgrades to asp to implicitly wipe the cache and not
  # make any guarantees about the file format.
  if (( $(stat -c %Y "${BASH_SOURCE[0]}" 2>/dev/null) > cachetime )); then
    return 0
  fi

  return 1
}

__remote_refcache_get() {
  local remote=$1 cachefile=$ASPCACHE/remote-$remote

  if __remote_refcache_is_stale "$cachefile"; then
    __remote_refcache_update "$remote"
  fi

  mapfile -t "$2" <"$cachefile"
}

remote_get_all_refs() {
  local remote=$1

  __remote_refcache_get "$remote" "$2"
}

remote_has_package() {
  local remote=$1 pkgname=$2 refs

  remote_get_all_refs "$remote" refs

  in_array "$pkgname" "${refs[@]}"
}

remote_is_tracking() {
  local repo=$1 pkgname=$2

  git show-ref -q "$repo/packages/$pkgname"
}

remote_get_tracked_refs() {
  local remote=$1

  mapfile -t "$2" < \
    <(git for-each-ref --format='%(refname:strip=3)' "refs/remotes/$remote")
}

remote_update_refs() {
  local remote=$1 refspecs=("${@:2}")

  quiet_git fetch "$remote" "${refspecs[@]}"
}

remote_update() {
  local remote=$1 refspecs

  remote_get_tracked_refs "$remote" refspecs

  # refuse to update everything
  [[ -z $refspecs ]] && return 0

  remote_update_refs "$remote" "${refspecs[@]}"
}

remote_untrack() {
  local remote=$1 pkgname=$2

  if git show-ref -q "refs/remotes/$remote/packages/$pkgname"; then
    git branch -dr "$remote/packages/$pkgname"
  fi
}


================================================
FILE: shell/bash-completion
================================================
#!/bin/bash

in_array() {
  for _ in "${@:2}"; do
    [[ $_ = "$1" ]] && return 0
  done
  return 1
}

_asp() {
  local verb='' i cur prev comps

  _get_comp_words_by_ref cur prev

  # top level commands
  local -A verbs=(
    [ALL_PACKAGES]='checkout difflog export list-arches list-repos log shortlog show ls-files'
    [LOCAL_PACKAGES]='untrack update'
    [NONE]='disk-usage gc help list-all list-local'
    [PROTO]='set-git-protocol'
  )

  # flags
  local -A opts=(
    [UNKNOWN]='-a'
    [NONE]='-h -V'
  )

  if in_array "$prev" ${opts[UNKNOWN]}; then
    return 0
  fi

  if [[ $cur = -* ]]; then
    COMPREPLY=( $(compgen -W '${opts[*]}' -- "$cur") )
    return 0
  fi

  # verb completion
  for (( i = 0; i < ${#COMP_WORDS[@]}; ++i )); do
    word=${COMP_WORDS[i]}
    if in_array "$word" ${verbs[ALL_PACKAGES]}; then
      verb=$word
      comps=$(ASP_GIT_QUIET=1 \asp list-all | sed 's,.*/,,')
      break
    elif in_array "$word" ${verbs[LOCAL_PACKAGES]}; then
      verb=$word
      comps=$(ASP_GIT_QUIET=1 \asp list-local | sed 's,.*/,,')
      break
    elif in_array "$word" ${verbs[PROTO]}; then
      verb=$word
      comps='git http https'
      break
    elif in_array "$word" ${verbs[NONE]}; then
      verb=$word
      break
    fi
  done

  # sub-verb completion
  case $verb in
    show)
      if (( i < ${#COMP_WORDS[@]} - 2 )); then
        comps=$(ASP_GIT_QUIET=1 \asp ls-files "${COMP_WORDS[i+1]}" 2>/dev/null)
      fi
      ;;
    '')
      comps=${verbs[*]}
      ;;
  esac

  if [[ $comps ]]; then
    COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
  fi
}

complete -F _asp asp


================================================
FILE: shell/zsh-completion
================================================
#compdef asp

_asp_command() {
  local -a _asp_cmds
  _asp_cmds=(
      'checkout'
      'difflog'
      'export'
      'gc'
      'disk-usage'
      'help'
      'list-all'
      'list-arches'
      'list-local'
      'list-repos'
      'ls-files'
      'log'
      'shortlog'
      'show'
      'set-git-protocol'
      'update'
      'untrack'
      )

  if (( CURRENT == 1 )); then
    _describe -t commands 'asp command' _asp_cmds || compadd "$@"
  else
    local curcontext="$curcontext"
    cmd="${${_asp_cmds[(r)$words[1]:*]%%:*}}"
    if (( $#cmd )); then
      if (( $+functions[_asp_$cmd] )); then
        _asp_$cmd
      else
        _message "no more options"
      fi
    else
      _message "unknown asp command: $words[1]"
    fi
  fi
}

_arguments \
  '-a[architecture]' \
  '-h[print help and exit]' \
  '-V[print version and exit]' \
  '*::asp command:_asp_command'

# vim: set et sw=2 ts=2 ft=zsh :


================================================
FILE: util.inc.sh
================================================
log_meta() {
  # shellcheck disable=SC2059
  printf "$1 $2\\n" "${@:3}"
}

log_error() {
  log_meta 'error:' "$@" >&2
}

log_fatal() {
  log_error "$@"
  exit 1
}

log_warning() {
  log_meta 'warning:' "$@" >&2
}

log_info() {
  log_meta '==>' "$@"
}

map() {
  local map_r=0
  for _ in "${@:2}"; do
    "$1" "$_" || map_r=1
  done
  return $map_r
}

in_array() {
  local item needle=$1

  for item in "${@:2}"; do
    [[ $item = "$needle" ]] && return 0
  done

  return 1
}

quiet_git() {
  [[ $ASP_GIT_QUIET ]] && set -- "$1" -q "${@:2}"

  command git "$@"
}
Download .txt
gitextract_1nhrilat/

├── .gitignore
├── LICENSE
├── Makefile
├── README.md
├── archweb.inc.sh
├── asp.in
├── man/
│   └── asp.1.txt
├── package.inc.sh
├── remote.inc.sh
├── shell/
│   ├── bash-completion
│   └── zsh-completion
└── util.inc.sh
Condensed preview — 12 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (27K chars).
[
  {
    "path": ".gitignore",
    "chars": 10,
    "preview": "asp\nasp.1\n"
  },
  {
    "path": "LICENSE",
    "chars": 1057,
    "preview": "Copyright (c) 2014 Dave Reisner\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this so"
  },
  {
    "path": "Makefile",
    "chars": 1301,
    "preview": "PACKAGE_NAME = asp\n\nVERSION := $(shell git describe --dirty 2>/dev/null)\n\nPREFIX = /usr/local\n\nBINPROGS = \\\n\tasp\n\nMANPAG"
  },
  {
    "path": "README.md",
    "chars": 1160,
    "preview": "> [!CAUTION]\n> **THIS REPO IS ARCHIVED**\n> \n> In the context of the [git migration](https://archlinux.org/news/git-migra"
  },
  {
    "path": "archweb.inc.sh",
    "chars": 286,
    "preview": "archweb_get_pkgbase() {\n  local pkgbase\n\n  pkgbase=$(curl -LGs 'https://archlinux.org/packages/search/json/' --data-urle"
  },
  {
    "path": "asp.in",
    "chars": 7554,
    "preview": "#!/bin/bash\n\nASP_VERSION=@ASP_VERSION@\nARCH_GIT_REPOS=(packages community)\n\nOPT_ARCH=$(uname -m)\n: \"${ASPROOT:=${XDG_CAC"
  },
  {
    "path": "man/asp.1.txt",
    "chars": 3602,
    "preview": "/////\nvim:set ts=4 sw=4 syntax=asciidoc noet:\n/////\nasp(1)\n======\n\nName\n----\nasp - Manage Arch Linux build sources\n\nSyno"
  },
  {
    "path": "package.inc.sh",
    "chars": 4669,
    "preview": "package_resolve() {\n  local pkgbase\n\n  [[ $pkgname ]] || log_fatal 'BUG: package_resolve called without pkgname var set'"
  },
  {
    "path": "remote.inc.sh",
    "chars": 2057,
    "preview": "__remote_refcache_update() {\n  local remote=$1 cachefile=$ASPCACHE/remote-$remote refs\n\n  refs=$(git ls-remote \"$remote\""
  },
  {
    "path": "shell/bash-completion",
    "chars": 1613,
    "preview": "#!/bin/bash\n\nin_array() {\n  for _ in \"${@:2}\"; do\n    [[ $_ = \"$1\" ]] && return 0\n  done\n  return 1\n}\n\n_asp() {\n  local "
  },
  {
    "path": "shell/zsh-completion",
    "chars": 919,
    "preview": "#compdef asp\n\n_asp_command() {\n  local -a _asp_cmds\n  _asp_cmds=(\n      'checkout'\n      'difflog'\n      'export'\n      "
  },
  {
    "path": "util.inc.sh",
    "chars": 563,
    "preview": "log_meta() {\n  # shellcheck disable=SC2059\n  printf \"$1 $2\\\\n\" \"${@:3}\"\n}\n\nlog_error() {\n  log_meta 'error:' \"$@\" >&2\n}\n"
  }
]

About this extraction

This page contains the full source code of the falconindy/asp GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 12 files (24.2 KB), approximately 7.6k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!