Skip to content

Instantly share code, notes, and snippets.

@user202729
Last active January 1, 2026 10:45
Show Gist options
  • Select an option

  • Save user202729/3f2ae39ca8467a7829aeecf51d0e01ad to your computer and use it in GitHub Desktop.

Select an option

Save user202729/3f2ae39ca8467a7829aeecf51d0e01ad to your computer and use it in GitHub Desktop.
Thought on archlinux aur shallow clone

In arch linux - How to modify a PKGBUILD which uses git sources to pull only a shallow clone? - Unix & Linux Stack Exchange, the questioner asks how to make makepkg clone only the relevant commit needed to build the package, instead of the whole git history.

Starting from git 2.49.0, it is technically possible to git clone a single commit. However, there is an additional difficulty.

In summary, some package's PKGBUILD contains git describe command. For this to work, you need to fetch until the nearest tag.


Originally, /usr/share/makepkg/source/git.sh contains download_git and extract_git shell functions.

Details
#!/usr/bin/bash
#
#   git.sh - function for handling the download and "extraction" of Git sources
#
#   Copyright (c) 2015-2024 Pacman Development Team <pacman-dev@lists.archlinux.org>
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 2 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

[[ -n "$LIBMAKEPKG_SOURCE_GIT_SH" ]] && return
LIBMAKEPKG_SOURCE_GIT_SH=1


MAKEPKG_LIBRARY=${MAKEPKG_LIBRARY:-'/usr/share/makepkg'}

source "$MAKEPKG_LIBRARY/util/error.sh"
source "$MAKEPKG_LIBRARY/util/message.sh"
source "$MAKEPKG_LIBRARY/util/pkgbuild.sh"


download_git() {
	# abort early if parent says not to fetch
	if declare -p get_vcs > /dev/null 2>&1; then
		(( get_vcs )) || return
	fi

	local netfile=$1

	local dir=$(get_filepath "$netfile")
	[[ -z "$dir" ]] && dir="$SRCDEST/$(get_filename "$netfile")"

	local repo=$(get_filename "$netfile")

	local url=$(get_url "$netfile")
	url=${url#git+}
	url=${url%%#*}
	url=${url%%\?*}

	if [[ ! -d "$dir" ]] || dir_is_empty "$dir" ; then
		msg2 "$(gettext "Cloning %s %s repo...")" "${repo}" "git"
		if ! git clone --origin=origin --mirror "$url" "$dir"; then
			error "$(gettext "Failure while downloading %s %s repo")" "${repo}" "git"
			plainerr "$(gettext "Aborting...")"
			exit 1
		fi
	elif (( ! HOLDVER )); then
		cd_safe "$dir"
		# When invoking git on a potentially bare repository, we should pass -c safe.bareRepository=all
		# to avoid breaking when the option is globally set to explicit

		# Make sure we are fetching the right repo
		local remote_url="$(git -c safe.bareRepository=all config --get remote.origin.url)"
		if [[ "${url%%.git}" != "${remote_url%%.git}" ]] ; then
			error "$(gettext "%s is not a clone of %s")" "$dir" "$url"
			plainerr "$(gettext "Aborting...")"
			exit $E_NOT_A_CLONE_OF
		fi
		msg2 "$(gettext "Updating %s %s repo...")" "${repo}" "git"
		if ! git -c safe.bareRepository=all fetch --all -p; then
			# only warn on failure to allow offline builds
			warning "$(gettext "Failure while updating %s %s repo")" "${repo}" "git"
		fi
	fi

	# Sanitize the cloned repo
	# $GIT_DIR/info/attributes overrides .gitattributes, and thus no files in the repository
	# can be altered by git features like export-subst or export-ignore
	local MAKEPKG_GIT_DIR="$(git -c safe.bareRepository=all -C "$dir" rev-parse --absolute-git-dir)"
	mkdir -p "$MAKEPKG_GIT_DIR/info"
	echo "* -export-subst -export-ignore" > "$MAKEPKG_GIT_DIR/info/attributes"
}

extract_git() {
	local netfile=$1 tagname

	local fragment=$(get_uri_fragment "$netfile")
	local repo=$(get_filename "$netfile")

	local dir=$(get_filepath "$netfile")
	[[ -z "$dir" ]] && dir="$SRCDEST/$(get_filename "$netfile")"

	msg2 "$(gettext "Creating working copy of %s %s repo...")" "${repo}" "git"
	pushd "$srcdir" &>/dev/null

	local updating=0
	if [[ -d "${dir##*/}" ]]; then
		updating=1
		cd_safe "${dir##*/}"
		if ! git fetch; then
			error "$(gettext "Failure while updating working copy of %s %s repo")" "${repo}" "git"
			plainerr "$(gettext "Aborting...")"
			exit 1
		fi
		cd_safe "$srcdir"
	elif ! git clone --origin=origin -s "$dir" "${dir##*/}"; then
		error "$(gettext "Failure while creating working copy of %s %s repo")" "${repo}" "git"
		plainerr "$(gettext "Aborting...")"
		exit 1
	fi

	cd_safe "${dir##*/}"

	local ref=origin/HEAD
	if [[ -n $fragment ]]; then
		case ${fragment%%=*} in
			commit|tag)
				ref=${fragment##*=}
				;;
			branch)
				ref=origin/${fragment##*=}
				;;
			*)
				error "$(gettext "Unrecognized reference: %s")" "${fragment}"
				plainerr "$(gettext "Aborting...")"
				exit 1
		esac
	fi

	if [[ ${fragment%%=*} = tag ]]; then
		tagname="$(git tag -l --format='%(tag)' "$ref")"
		if [[ -n $tagname && $tagname != "$ref" ]]; then
			error "$(gettext "Failure while checking out version %s, the git tag has been forged")" "$ref"
			plainerr "$(gettext "Aborting...")"
			exit 1
		fi
	fi

	if [[ $ref != "origin/HEAD" ]] || (( updating )) ; then
		if ! git checkout --force --no-track -B makepkg "$ref" --; then
			error "$(gettext "Failure while creating working copy of %s %s repo")" "${repo}" "git"
			plainerr "$(gettext "Aborting...")"
			exit 1
		fi
	fi

	popd &>/dev/null
}

calc_checksum_git() {
	local netfile=$1 integ=$2 ret=0 shellopts dir url fragment sum

	# this function requires pipefail - save current status to restore later
	shellopts=$(shopt -p -o pipefail)
	shopt -s -o pipefail

	dir=$(get_filepath "$netfile")
	url=$(get_url "$netfile")
	fragment=$(get_uri_fragment "$url")

	case ${fragment%%=*} in
		tag|commit)
			fragval=${fragment##*=}
			sum=$(GIT_CONFIG_GLOBAL=/dev/null GIT_CONFIG_SYSTEM=/dev/null git -c core.abbrev=no -C "$dir" archive --format tar "$fragval" | "${integ}sum" 2>&1) || ret=1
			sum="${sum%% *}"
			;;
		*)
			sum="SKIP"
			;;
	esac

	eval "$shellopts"
	printf '%s' "$sum"
	return $ret
}

You can change it to

Details
#!/usr/bin/bash
#
#   git.sh - function for handling the download and "extraction" of Git sources
#
#   Copyright (c) 2015-2024 Pacman Development Team <pacman-dev@lists.archlinux.org>
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 2 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

[[ -n "$LIBMAKEPKG_SOURCE_GIT_SH" ]] && return
LIBMAKEPKG_SOURCE_GIT_SH=1


MAKEPKG_LIBRARY=${MAKEPKG_LIBRARY:-'/usr/share/makepkg'}

source "$MAKEPKG_LIBRARY/util/error.sh"
source "$MAKEPKG_LIBRARY/util/message.sh"
source "$MAKEPKG_LIBRARY/util/pkgbuild.sh"

get_ref_from_fragment() {
	local fragment=$1
	local ref=origin/HEAD
	if [[ -n $fragment ]]; then
		case ${fragment%%=*} in
			commit|tag)
				ref=${fragment##*=}
				;;
			branch)
				ref=origin/${fragment##*=}
				;;
			*)
				error "$(gettext "Unrecognized reference: %s")" "${fragment}"
				plainerr "$(gettext "Aborting...")"
				exit 1
		esac
	fi
	printf "%s\n" "$ref"
}

download_git() {
	# abort early if parent says not to fetch
	if declare -p get_vcs > /dev/null 2>&1; then
		(( get_vcs )) || return
	fi

	local netfile=$1

	local dir=$(get_filepath "$netfile")
	[[ -z "$dir" ]] && dir="$SRCDEST/$(get_filename "$netfile")"

	local repo=$(get_filename "$netfile")

	local url=$(get_url "$netfile")
	url=${url#git+}
	url=${url%%#*}
	url=${url%%\?*}

	if [[ ! -d "$dir" ]] || dir_is_empty "$dir" ; then
		msg2 "$(gettext "Cloning %s %s repo...")" "${repo}" "git"
		local fragment=$(get_uri_fragment "$netfile")
		local ref=$(get_ref_from_fragment "$fragment")
		if ! git clone --origin=origin --bare --revision "${ref/origin\//}" --depth 1 "$url" "$dir"; then
			error "$(gettext "Failure while downloading %s %s repo")" "${repo}" "git"
			plainerr "$(gettext "Aborting...")"
			exit 1
		fi
	elif (( ! HOLDVER )); then
		cd_safe "$dir"
		# When invoking git on a potentially bare repository, we should pass -c safe.bareRepository=all
		# to avoid breaking when the option is globally set to explicit

		# Make sure we are fetching the right repo
		local remote_url="$(git -c safe.bareRepository=all config --get remote.origin.url)"
		if [[ "${url%%.git}" != "${remote_url%%.git}" ]] ; then
			error "$(gettext "%s is not a clone of %s")" "$dir" "$url"
			plainerr "$(gettext "Aborting...")"
			exit $E_NOT_A_CLONE_OF
		fi
		msg2 "$(gettext "Updating %s %s repo...")" "${repo}" "git"
		if ! git -c safe.bareRepository=all fetch --all -p; then
			# only warn on failure to allow offline builds
			warning "$(gettext "Failure while updating %s %s repo")" "${repo}" "git"
		fi
	fi

	# Sanitize the cloned repo
	# $GIT_DIR/info/attributes overrides .gitattributes, and thus no files in the repository
	# can be altered by git features like export-subst or export-ignore
	local MAKEPKG_GIT_DIR="$(git -c safe.bareRepository=all -C "$dir" rev-parse --absolute-git-dir)"
	mkdir -p "$MAKEPKG_GIT_DIR/info"
	echo "* -export-subst -export-ignore" > "$MAKEPKG_GIT_DIR/info/attributes"
}

extract_git() {
	local netfile=$1 tagname

	local fragment=$(get_uri_fragment "$netfile")
	local repo=$(get_filename "$netfile")

	local dir=$(get_filepath "$netfile")
	[[ -z "$dir" ]] && dir="$SRCDEST/$(get_filename "$netfile")"

	msg2 "$(gettext "Creating working copy of %s %s repo...")" "${repo}" "git"
	pushd "$srcdir" &>/dev/null

	local updating=0
	if [[ -d "${dir##*/}" ]]; then
		updating=1
		cd_safe "${dir##*/}"
		if ! git fetch; then
			error "$(gettext "Failure while updating working copy of %s %s repo")" "${repo}" "git"
			plainerr "$(gettext "Aborting...")"
			exit 1
		fi
		cd_safe "$srcdir"
	elif ! git clone --origin=origin -s "$dir" "${dir##*/}"; then
		error "$(gettext "Failure while creating working copy of %s %s repo")" "${repo}" "git"
		plainerr "$(gettext "Aborting...")"
		exit 1
	fi

	cd_safe "${dir##*/}"

	local ref=$(get_ref_from_fragment "$fragment")

	if [[ ${fragment%%=*} = tag ]]; then
		tagname="$(git tag -l --format='%(tag)' "$ref")"
		if [[ -n $tagname && $tagname != "$ref" ]]; then
			error "$(gettext "Failure while checking out version %s, the git tag has been forged")" "$ref"
			plainerr "$(gettext "Aborting...")"
			exit 1
		fi
	fi

	if [[ $ref != "origin/HEAD" ]] || (( updating )) ; then
		if ! git checkout --force --no-track -B makepkg "$ref" --; then
			error "$(gettext "Failure while creating working copy of %s %s repo")" "${repo}" "git"
			plainerr "$(gettext "Aborting...")"
			exit 1
		fi
	fi

	popd &>/dev/null
}

calc_checksum_git() {
	local netfile=$1 integ=$2 ret=0 shellopts dir url fragment sum

	# this function requires pipefail - save current status to restore later
	shellopts=$(shopt -p -o pipefail)
	shopt -s -o pipefail

	dir=$(get_filepath "$netfile")
	url=$(get_url "$netfile")
	fragment=$(get_uri_fragment "$url")

	case ${fragment%%=*} in
		tag|commit)
			fragval=${fragment##*=}
			sum=$(GIT_CONFIG_GLOBAL=/dev/null GIT_CONFIG_SYSTEM=/dev/null git -c core.abbrev=no -C "$dir" archive --format tar "$fragval" | "${integ}sum" 2>&1) || ret=1
			sum="${sum%% *}"
			;;
		*)
			sum="SKIP"
			;;
	esac

	eval "$shellopts"
	printf '%s' "$sum"
	return $ret
}

The diff:

Details
@@ -29,6 +29,25 @@
 source "$MAKEPKG_LIBRARY/util/message.sh"
 source "$MAKEPKG_LIBRARY/util/pkgbuild.sh"
 
+get_ref_from_fragment() {
+	local fragment=$1
+	local ref=origin/HEAD
+	if [[ -n $fragment ]]; then
+		case ${fragment%%=*} in
+			commit|tag)
+				ref=${fragment##*=}
+				;;
+			branch)
+				ref=origin/${fragment##*=}
+				;;
+			*)
+				error "$(gettext "Unrecognized reference: %s")" "${fragment}"
+				plainerr "$(gettext "Aborting...")"
+				exit 1
+		esac
+	fi
+	printf "%s\n" "$ref"
+}
 
 download_git() {
 	# abort early if parent says not to fetch
@@ -50,7 +69,9 @@
 
 	if [[ ! -d "$dir" ]] || dir_is_empty "$dir" ; then
 		msg2 "$(gettext "Cloning %s %s repo...")" "${repo}" "git"
-		if ! git clone --origin=origin --mirror "$url" "$dir"; then
+		local fragment=$(get_uri_fragment "$netfile")
+		local ref=$(get_ref_from_fragment "$fragment")
+		if ! git clone --origin=origin --bare --revision "${ref/origin\//}" --depth 1 "$url" "$dir"; then
 			error "$(gettext "Failure while downloading %s %s repo")" "${repo}" "git"
 			plainerr "$(gettext "Aborting...")"
 			exit 1
@@ -112,21 +133,7 @@
 
 	cd_safe "${dir##*/}"
 
-	local ref=origin/HEAD
-	if [[ -n $fragment ]]; then
-		case ${fragment%%=*} in
-			commit|tag)
-				ref=${fragment##*=}
-				;;
-			branch)
-				ref=origin/${fragment##*=}
-				;;
-			*)
-				error "$(gettext "Unrecognized reference: %s")" "${fragment}"
-				plainerr "$(gettext "Aborting...")"
-				exit 1
-		esac
-	fi
+	local ref=$(get_ref_from_fragment "$fragment")
 
 	if [[ ${fragment%%=*} = tag ]]; then
 		tagname="$(git tag -l --format='%(tag)' "$ref")"

Which will somewhat work, but some package's pkgver function has git describe command. Such as

pkgver() {
	cd "$pkgname"
	git describe --long | sed -E 's/creduce-([^-]*)-([^-]*)-g/\1-r\2-/; s/-/./g'
}

For this to work, you need to know the nearest tag.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment