mirror of
				https://gitlab.archlinux.org/archlinux/devtools.git
				synced 2025-10-30 23:34:43 +01:00 
			
		
		
		
	Compare commits
	
		
			25 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 8dbb02de4f | ||
|   | b12d5eaf85 | ||
|   | 0fa2536957 | ||
|   | be3c71fa81 | ||
|   | fb30cabe61 | ||
|   | 29e62278a7 | ||
|   | 8c4553f68c | ||
|   | 6006783cbc | ||
|   | e26fddb608 | ||
|   | c3bb10046b | ||
|   | 7a3f524201 | ||
|   | fc71be3479 | ||
|   | 38692e8d74 | ||
|   | a5bc6acf32 | ||
|   | 4937422fcf | ||
|   | 4dcdbcaf1e | ||
|   | 1489f75419 | ||
|   | 7ca4eb82dd | ||
|   | abba9f07a6 | ||
|   | a7a05deb37 | ||
|   | 0e98bd8c48 | ||
|   | 453558c4bb | ||
|   | 6e086f0e70 | ||
|   | 93d735981b | ||
|   | 97a2d2414a | 
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -15,3 +15,4 @@ rebuildpkgs | ||||
| zsh_completion | ||||
| find-libdeps | ||||
| crossrepomove | ||||
| arch-nspawn | ||||
|   | ||||
							
								
								
									
										15
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								Makefile
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| V=20130406 | ||||
| V=20130808 | ||||
|  | ||||
| PREFIX = /usr/local | ||||
|  | ||||
| @@ -13,9 +13,8 @@ BINPROGS = \ | ||||
| 	finddeps \ | ||||
| 	rebuildpkgs \ | ||||
| 	find-libdeps \ | ||||
| 	crossrepomove | ||||
|  | ||||
| SBINPROGS = \ | ||||
| 	crossrepomove\ | ||||
| 	arch-nspawn \ | ||||
| 	mkarchroot \ | ||||
| 	makechrootpkg | ||||
|  | ||||
| @@ -68,7 +67,7 @@ BASHCOMPLETION_LINKS = \ | ||||
| 	archco \ | ||||
| 	communityco | ||||
|  | ||||
| all: $(BINPROGS) $(SBINPROGS) bash_completion zsh_completion | ||||
| all: $(BINPROGS) bash_completion zsh_completion | ||||
|  | ||||
| edit = sed -e "s|@pkgdatadir[@]|$(DESTDIR)$(PREFIX)/share/devtools|g" | ||||
|  | ||||
| @@ -78,16 +77,15 @@ edit = sed -e "s|@pkgdatadir[@]|$(DESTDIR)$(PREFIX)/share/devtools|g" | ||||
| 	@m4 -P $@.in | $(edit) >$@ | ||||
| 	@chmod a-w "$@" | ||||
| 	@chmod +x "$@" | ||||
| 	@bash -O extglob -n "$@" | ||||
|  | ||||
| clean: | ||||
| 	rm -f $(BINPROGS) $(SBINPROGS) bash_completion zsh_completion | ||||
| 	rm -f $(BINPROGS) bash_completion zsh_completion | ||||
|  | ||||
| install: | ||||
| 	install -dm0755 $(DESTDIR)$(PREFIX)/bin | ||||
| 	install -dm0755 $(DESTDIR)$(PREFIX)/sbin | ||||
| 	install -dm0755 $(DESTDIR)$(PREFIX)/share/devtools | ||||
| 	install -m0755 ${BINPROGS} $(DESTDIR)$(PREFIX)/bin | ||||
| 	install -m0755 ${SBINPROGS} $(DESTDIR)$(PREFIX)/sbin | ||||
| 	install -m0644 ${CONFIGFILES} $(DESTDIR)$(PREFIX)/share/devtools | ||||
| 	for l in ${COMMITPKG_LINKS}; do ln -sf commitpkg $(DESTDIR)$(PREFIX)/bin/$$l; done | ||||
| 	for l in ${ARCHBUILD_LINKS}; do ln -sf archbuild $(DESTDIR)$(PREFIX)/bin/$$l; done | ||||
| @@ -100,7 +98,6 @@ install: | ||||
|  | ||||
| uninstall: | ||||
| 	for f in ${BINPROGS}; do rm -f $(DESTDIR)$(PREFIX)/bin/$$f; done | ||||
| 	for f in ${SBINPROGS}; do rm -f $(DESTDIR)$(PREFIX)/sbin/$$f; done | ||||
| 	for f in ${CONFIGFILES}; do rm -f $(DESTDIR)$(PREFIX)/share/devtools/$$f; done | ||||
| 	for l in ${COMMITPKG_LINKS}; do rm -f $(DESTDIR)$(PREFIX)/bin/$$l; done | ||||
| 	for l in ${ARCHBUILD_LINKS}; do rm -f $(DESTDIR)$(PREFIX)/bin/$$l; done | ||||
|   | ||||
							
								
								
									
										108
									
								
								arch-nspawn.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								arch-nspawn.in
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,108 @@ | ||||
| #!/bin/bash | ||||
| # 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; version 2 of the License. | ||||
| # | ||||
| # 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. | ||||
|  | ||||
| m4_include(lib/common.sh) | ||||
|  | ||||
| CHROOT_VERSION='v3' | ||||
|  | ||||
| working_dir='' | ||||
|  | ||||
| usage() { | ||||
| 	echo "Usage: ${0##*/} [options] working-dir [systemd-nspawn arguments]" | ||||
| 	echo "A wrapper around systemd-nspawn. Provides support for pacman." | ||||
| 	echo | ||||
| 	echo ' options:' | ||||
| 	echo '    -C <file>     Location of a pacman config file' | ||||
| 	echo '    -M <file>     Location of a makepkg config file' | ||||
| 	echo '    -c <dir>      Set pacman cache' | ||||
| 	echo '    -h            This message' | ||||
| 	exit 1 | ||||
| } | ||||
|  | ||||
| while getopts 'hC:M:c:' arg; do | ||||
| 	case "$arg" in | ||||
| 		C) pac_conf="$OPTARG" ;; | ||||
| 		M) makepkg_conf="$OPTARG" ;; | ||||
| 		c) cache_dir="$OPTARG" ;; | ||||
| 		h|?) usage ;; | ||||
| 		*) error "invalid argument '$arg'"; usage ;; | ||||
| 	esac | ||||
| done | ||||
| shift $(($OPTIND - 1)) | ||||
|  | ||||
| (( $EUID != 0 )) && die 'This script must be run as root.' | ||||
| (( $# < 1 )) && die 'You must specify a directory.' | ||||
|  | ||||
| working_dir="$(readlink -f $1)" | ||||
| shift 1 | ||||
|  | ||||
| [[ -z $working_dir ]] && die 'Please specify a working directory.' | ||||
|  | ||||
| if [[ -z $cache_dir ]]; then | ||||
| 	cache_dirs=($(pacman -v $cache_conf 2>&1 | grep '^Cache Dirs:' | sed 's/Cache Dirs:\s*//g')) | ||||
| else | ||||
| 	cache_dirs=(${cache_dir}) | ||||
| fi | ||||
|  | ||||
| host_mirror=$(pacman -Sddp extra/devtools 2>/dev/null | sed -r 's#(.*/)extra/os/.*#\1$repo/os/$arch#') | ||||
| [[ $host_mirror == *file://* ]] && host_mirror_path=$(echo "$host_mirror" | sed -r 's#file://(/.*)/\$repo/os/\$arch#\1#g') | ||||
|  | ||||
| # {{{ functions | ||||
| build_mount_args() { | ||||
| 	local p | ||||
| 	declare -g mount_args=() | ||||
|  | ||||
| 	if [[ -n $host_mirror_path ]]; then | ||||
| 		printf -v p '%q' "$host_mirror_path" | ||||
| 		mount_args+=(--bind-ro="$p") | ||||
| 	fi | ||||
|  | ||||
| 	printf -v p '%q' "${cache_dirs[0]}" | ||||
| 	mount_args+=(--bind="$p") | ||||
|  | ||||
| 	for cache_dir in ${cache_dirs[@]:1}; do | ||||
| 		printf -v p '%q' "$cache_dir" | ||||
| 		mount_args+=(--bind-ro="$p") | ||||
| 	done | ||||
| } | ||||
|  | ||||
| copy_hostconf () { | ||||
| 	cp -a /etc/pacman.d/gnupg "$working_dir/etc/pacman.d" | ||||
| 	echo "Server = $host_mirror" > $working_dir/etc/pacman.d/mirrorlist | ||||
|  | ||||
| 	[[ -n $pac_conf ]] && cp $pac_conf $working_dir/etc/pacman.conf | ||||
| 	[[ -n $makepkg_conf ]] && cp $makepkg_conf $working_dir/etc/makepkg.conf | ||||
|  | ||||
| 	sed -r "s|^#?\\s*CacheDir.+|CacheDir = $(echo -n ${cache_dirs[@]})|g" -i $working_dir/etc/pacman.conf | ||||
| } | ||||
| # }}} | ||||
|  | ||||
| umask 0022 | ||||
|  | ||||
| # Sanity check | ||||
| if [[ ! -f "$working_dir/.arch-chroot" ]]; then | ||||
| 	die "'%s' does not appear to be a Arch chroot." "$working_dir" | ||||
| elif [[ $(cat "$working_dir/.arch-chroot") != $CHROOT_VERSION ]]; then | ||||
| 	die "chroot '%s' is not at version %s. Please rebuild." "$working_dir" "$CHROOT_VERSION" | ||||
| fi | ||||
|  | ||||
| build_mount_args | ||||
| copy_hostconf | ||||
|  | ||||
| eval $(grep '^CARCH=' "$working_dir/etc/makepkg.conf") | ||||
|  | ||||
| machine_name="${working_dir//\//-}" | ||||
| machine_name="${machine_name#-}" | ||||
|  | ||||
| exec ${CARCH:+setarch "$CARCH"} systemd-nspawn 2>/dev/null \ | ||||
| 	-D "$working_dir" \ | ||||
| 	--machine "$machine_name" \ | ||||
| 	"${mount_args[@]}" \ | ||||
| 	"$@" | ||||
							
								
								
									
										16
									
								
								archbuild.in
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								archbuild.in
									
									
									
									
									
								
							| @@ -51,12 +51,7 @@ if ${clean_first} || [[ ! -d "${chroots}/${repo}-${arch}" ]]; then | ||||
| 		[[ -d $copy ]] || continue | ||||
| 		msg2 "Deleting chroot copy '$(basename "${copy}")'..." | ||||
|  | ||||
| 		exec 9>"$copydir.lock" | ||||
| 		if ! flock -n 9; then | ||||
| 			stat_busy "Locking chroot copy '$copy'" | ||||
| 			flock 9 | ||||
| 			stat_done | ||||
| 		fi | ||||
| 		lock 9 "$copydir.lock" "Locking chroot copy '$copy'" | ||||
|  | ||||
| 		if [[ "$(stat -f -c %T "${copy}")" == btrfs ]]; then | ||||
| 			{ type -P btrfs && btrfs subvolume delete "${copy}"; } &>/dev/null | ||||
| @@ -73,12 +68,13 @@ if ${clean_first} || [[ ! -d "${chroots}/${repo}-${arch}" ]]; then | ||||
| 		"${chroots}/${repo}-${arch}/root" \ | ||||
| 		"${base_packages[@]}" || abort | ||||
| else | ||||
| 	setarch ${arch} mkarchroot \ | ||||
| 		-u \ | ||||
| 	lock 9 "${chroots}/${repo}-${arch}/root.lock" "Locking clean chroot" | ||||
| 	arch-nspawn \ | ||||
| 		-C "@pkgdatadir@/pacman-${repo}.conf" \ | ||||
| 		-M "@pkgdatadir@/makepkg-${arch}.conf" \ | ||||
| 		"${chroots}/${repo}-${arch}/root" || abort | ||||
| 		"${chroots}/${repo}-${arch}/root" \ | ||||
|                 pacman -Syu --noconfirm || abort | ||||
| fi | ||||
|  | ||||
| msg "Building in chroot for [${repo}] (${arch})..." | ||||
| exec setarch "${arch}" makechrootpkg "${makechrootpkg_args[@]}" -r "${chroots}/${repo}-${arch}" | ||||
| exec makechrootpkg -r "${chroots}/${repo}-${arch}" "${makechrootpkg_args[@]}" | ||||
|   | ||||
| @@ -15,7 +15,7 @@ case $scriptname in | ||||
| 	communityco) | ||||
| 		SVNURL="svn+ssh://svn-community@nymeria.archlinux.org/srv/repos/svn-community/svn";; | ||||
| 	*) | ||||
| 		die "Couldn't find svn url for $scriptname" | ||||
| 		die "Couldn't find svn url for %s" "$scriptname" | ||||
| 		;; | ||||
| esac | ||||
|  | ||||
|   | ||||
| @@ -8,8 +8,8 @@ FORCE= | ||||
| while getopts ':f' flag; do | ||||
| 	case $flag in | ||||
| 		f) FORCE=1 ;; | ||||
| 		:) die "Option requires an argument -- '$OPTARG'" ;; | ||||
| 		\?) die "Invalid option -- '$OPTARG'" ;; | ||||
| 		:) die "Option requires an argument -- '%s'" "$OPTARG" ;; | ||||
| 		\?) die "Invalid option -- '%s'" "$OPTARG" ;; | ||||
| 	esac | ||||
| done | ||||
| shift $(( OPTIND - 1 )) | ||||
| @@ -23,7 +23,7 @@ fi | ||||
| if [[ -z $FORCE ]]; then | ||||
| 	for tag in "$@"; do | ||||
| 		if ! in_array "$tag" "${_tags[@]}"; then | ||||
| 			die 'archrelease: Invalid tag: "'$tag'" (use -f to force release)' | ||||
| 			die "archrelease: Invalid tag: '%s' (use -f to force release)" "$tag" | ||||
| 		fi | ||||
| 	done | ||||
| fi | ||||
|   | ||||
| @@ -34,7 +34,7 @@ _makechrootpkg() { | ||||
|  | ||||
|   case $cur in | ||||
|     -*) | ||||
|        COMPREPLY=( $( compgen -W '-I -c -d -h -l -r -u' -- "$cur" ) ) | ||||
|        COMPREPLY=( $( compgen -W '-I -c -h -l -r -u' -- "$cur" ) ) | ||||
|        ;; | ||||
|     *) | ||||
|       _filedir | ||||
| @@ -53,7 +53,7 @@ _mkarchroot() { | ||||
|  | ||||
|   case $cur in | ||||
|     -*) | ||||
|        COMPREPLY=( $( compgen -W '-C -M -c -f -h -n -r -u' -- "$cur" ) ) | ||||
|        COMPREPLY=( $( compgen -W '-C -M -c -h' -- "$cur" ) ) | ||||
|        ;; | ||||
|     *) | ||||
|       _filedir | ||||
| @@ -65,5 +65,22 @@ _mkarchroot() { | ||||
| } && | ||||
| complete -F _mkarchroot mkarchroot | ||||
|  | ||||
| _arch-nspawn() { | ||||
|   local cur | ||||
|   COMPREPLY=() | ||||
|   _get_comp_words_by_ref cur | ||||
|  | ||||
|   case $cur in | ||||
|     -*) | ||||
|        COMPREPLY=( $( compgen -W '-C -M -c -h' -- "$cur" ) ) | ||||
|        ;; | ||||
|     *) | ||||
|       _filedir | ||||
|       return 0 | ||||
|       ;; | ||||
|   esac | ||||
|  | ||||
|   true | ||||
| } && | ||||
| complete -F _arch-nspawn arch-nspawn | ||||
| # ex:et ts=2 sw=2 ft=sh | ||||
|   | ||||
| @@ -41,13 +41,13 @@ for _pkgname in "${pkgname[@]}"; do | ||||
| 	pkgurl=$(pacman -Spdd --print-format '%l' --noconfirm "$_pkgname") | ||||
|  | ||||
| 	if [[ $? -ne 0 ]]; then | ||||
| 		die "Couldn't download previous package for $_pkgname." | ||||
| 		die "Couldn't download previous package for %s." "$_pkgname" | ||||
| 	fi | ||||
|  | ||||
| 	oldpkg=${pkgurl##*://*/} | ||||
|  | ||||
| 	if [[ ${oldpkg##*/} = ${pkgfile##*/} ]]; then | ||||
| 		die "The built package ($_pkgname) is the one in the repo right now!" | ||||
| 		die "The built package (%s) is the one in the repo right now!" "$_pkgname" | ||||
| 	fi | ||||
|  | ||||
| 	if [[ ! -f $oldpkg ]]; then | ||||
|   | ||||
							
								
								
									
										10
									
								
								commitpkg.in
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								commitpkg.in
									
									
									
									
									
								
							| @@ -58,7 +58,7 @@ esac | ||||
| # check if all local source files are under version control | ||||
| for s in "${source[@]}"; do | ||||
| 	if [[ $s != *://* ]] && ! svn status -v "$s@" | grep -q '^[ AMRX~]'; then | ||||
| 		die "$s is not under version control" | ||||
| 		die "%s is not under version control" "$s" | ||||
| 	fi | ||||
| done | ||||
|  | ||||
| @@ -68,7 +68,7 @@ for i in 'changelog' 'install'; do | ||||
| 		# evaluate any bash variables used | ||||
| 		eval file=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "$file")\" | ||||
| 		if ! svn status -v "${file}" | grep -q '^[ AMRX~]'; then | ||||
| 			die "${file} is not under version control" | ||||
| 			die "%s is not under version control" "$file" | ||||
| 		fi | ||||
| 	done < <(sed -n "s/^[[:space:]]*$i=//p" PKGBUILD) | ||||
| done | ||||
| @@ -81,8 +81,8 @@ while getopts ':l:a:s:f' flag; do | ||||
| 		s) server=$OPTARG ;; | ||||
| 		l) rsyncopts+=("--bwlimit=$OPTARG") ;; | ||||
| 		a) commit_arch=$OPTARG ;; | ||||
| 		:) die "Option requires an argument -- '$OPTARG'" ;; | ||||
| 		\?) die "Invalid option -- '$OPTARG'" ;; | ||||
| 		:) die "Option requires an argument -- '%s'" "$OPTARG" ;; | ||||
| 		\?) die "Invalid option -- '%s'" "$OPTARG" ;; | ||||
| 	esac | ||||
| done | ||||
| shift $(( OPTIND - 1 )) | ||||
| @@ -164,7 +164,7 @@ for _arch in ${arch[@]}; do | ||||
| 			gpg --detach-sign --use-agent ${SIGNWITHKEY} "${pkgfile}" || die | ||||
| 		fi | ||||
| 		if ! gpg --verify "$sigfile" >/dev/null 2>&1; then | ||||
| 			die "Signature ${pkgfile}.sig is incorrect!" | ||||
| 			die "Signature %s.sig is incorrect!" "$pkgfile" | ||||
| 		fi | ||||
| 		uploads+=("$sigfile") | ||||
| 	done | ||||
|   | ||||
| @@ -25,12 +25,11 @@ case $scriptname in | ||||
| 		target_repo='extra' | ||||
| 		;; | ||||
| 	*) | ||||
| 		die "Couldn't find configuration for $scriptname" | ||||
| 		die "Couldn't find configuration for %s" "$scriptname" | ||||
| 		;; | ||||
| esac | ||||
|  | ||||
| server='nymeria.archlinux.org' | ||||
| mirror="http://${server}" | ||||
| source_svn="svn+ssh://svn-${source_name}@${server}/srv/repos/svn-${source_name}/svn" | ||||
| target_svn="svn+ssh://svn-${target_name}@${server}/srv/repos/svn-${target_name}/svn" | ||||
| source_dbscripts="/srv/repos/svn-${source_name}/dbscripts" | ||||
| @@ -55,10 +54,8 @@ for _arch in ${arch[@]}; do | ||||
| 	fi | ||||
| 	for _pkgname in ${pkgname[@]}; do | ||||
| 		fullver=$(get_full_version $_pkgname) | ||||
| 		# FIXME: this only works with .xz packages | ||||
| 		ssh "${server}" "cd staging/${target_repo} | ||||
| 			curl -O ${mirror}/${source_repo}/os/${repo_arch}/$_pkgname-$fullver-${_arch}.pkg.tar.xz | ||||
| 			curl -O ${mirror}/${source_repo}/os/${repo_arch}/$_pkgname-$fullver-${_arch}.pkg.tar.xz.sig" || die | ||||
| 		pkgpath="/srv/ftp/$source_repo/os/$repo_arch/$_pkgname-$fullver-${_arch}.pkg.tar.*" | ||||
| 		ssh "$server" "cp $pkgpath staging/$target_repo" || die | ||||
| 	done | ||||
| done | ||||
|  | ||||
|   | ||||
| @@ -16,7 +16,7 @@ script_mode=${0##*/find-lib} | ||||
|  | ||||
| case $script_mode in | ||||
| 	deps|provides) true;; | ||||
| 	*) die "Unknown mode $script_mode" ;; | ||||
| 	*) die "Unknown mode %s" "$script_mode" ;; | ||||
| esac | ||||
|  | ||||
| if [[ -z $1 ]]; then | ||||
|   | ||||
| @@ -82,7 +82,7 @@ trap_exit() { | ||||
| } | ||||
|  | ||||
| die() { | ||||
| 	error "$*" | ||||
| 	(( $# )) && error "$@" | ||||
| 	cleanup 1 | ||||
| } | ||||
|  | ||||
| @@ -130,3 +130,27 @@ get_full_version() { | ||||
| 		fi | ||||
| 	fi | ||||
| } | ||||
|  | ||||
| ## | ||||
| #  usage : lock( $fd, $file, $message ) | ||||
| ## | ||||
| lock() { | ||||
| 	eval "exec $1>"'"$2"' | ||||
| 	if ! flock -n $1; then | ||||
| 		stat_busy "$3" | ||||
| 		flock $1 | ||||
| 		stat_done | ||||
| 	fi | ||||
| } | ||||
|  | ||||
| ## | ||||
| #  usage : slock( $fd, $file, $message ) | ||||
| ## | ||||
| slock() { | ||||
| 	eval "exec $1>"'"$2"' | ||||
| 	if ! flock -sn $1; then | ||||
| 		stat_busy "$3" | ||||
| 		flock -s $1 | ||||
| 		stat_done | ||||
| 	fi | ||||
| } | ||||
|   | ||||
							
								
								
									
										402
									
								
								makechrootpkg.in
									
									
									
									
									
								
							
							
						
						
									
										402
									
								
								makechrootpkg.in
									
									
									
									
									
								
							| @@ -12,21 +12,21 @@ m4_include(lib/common.sh) | ||||
|  | ||||
| shopt -s nullglob | ||||
|  | ||||
| makepkg_args='-s --noconfirm -L' | ||||
| makepkg_args='-s --noconfirm -L --holdver' | ||||
| repack=false | ||||
| update_first=false | ||||
| clean_first=false | ||||
| install_pkg= | ||||
| add_to_db=false | ||||
| run_namcap=false | ||||
| temp_chroot=false | ||||
| chrootdir= | ||||
| passeddir= | ||||
| declare -a install_pkgs | ||||
| declare -i ret=0 | ||||
|  | ||||
| default_copy=$USER | ||||
| [[ -n $SUDO_USER ]] && default_copy=$SUDO_USER | ||||
| [[ -z $default_copy || $default_copy = root ]] && default_copy=copy | ||||
| copy=$USER | ||||
| [[ -n $SUDO_USER ]] && copy=$SUDO_USER | ||||
| [[ -z "$copy" || $copy = root ]] && copy=copy | ||||
| src_owner=${SUDO_USER:-$USER} | ||||
|  | ||||
| usage() { | ||||
| @@ -51,37 +51,45 @@ usage() { | ||||
| 	echo '-u         Update the working copy of the chroot before building' | ||||
| 	echo '           This is useful for rebuilds without dirtying the pristine' | ||||
| 	echo '           chroot' | ||||
| 	echo '-d         Add the package to a local db at /repo after building' | ||||
| 	echo '-r <dir>   The chroot dir to use' | ||||
| 	echo '-I <pkg>   Install a package into the working copy of the chroot' | ||||
| 	echo '-l <copy>  The directory to use as the working copy of the chroot' | ||||
| 	echo '           Useful for maintaining multiple copies.' | ||||
| 	echo "           Default: $default_copy" | ||||
| 	echo '           Useful for maintaining multiple copies' | ||||
| 	echo "           Default: $copy" | ||||
| 	echo '-n         Run namcap on the package' | ||||
| 	echo '-T         Build in a temporary directory' | ||||
| 	exit 1 | ||||
| } | ||||
|  | ||||
| while getopts 'hcudr:I:l:n' arg; do | ||||
| while getopts 'hcur:I:l:nT' arg; do | ||||
| 	case "$arg" in | ||||
| 		h) usage ;; | ||||
| 		c) clean_first=true ;; | ||||
| 		u) update_first=true ;; | ||||
| 		d) add_to_db=true ;; | ||||
| 		r) passeddir="$OPTARG" ;; | ||||
| 		I) install_pkgs+=("$OPTARG") ;; | ||||
| 		l) copy="$OPTARG" ;; | ||||
| 		n) run_namcap=true; makepkg_args="$makepkg_args -i" ;; | ||||
| 		T) temp_chroot=true; copy+="-$$" ;; | ||||
| 		*) makepkg_args="$makepkg_args -$arg $OPTARG" ;; | ||||
| 	esac | ||||
| done | ||||
|  | ||||
| (( EUID != 0 )) && die 'This script must be run as root.' | ||||
|  | ||||
| [[ ! -f PKGBUILD && -z "${install_pkgs[*]}" ]] && die 'This must be run in a directory containing a PKGBUILD.' | ||||
|  | ||||
| # Canonicalize chrootdir, getting rid of trailing / | ||||
| chrootdir=$(readlink -e "$passeddir") | ||||
| [[ ! -d $chrootdir ]] && die "No chroot dir defined, or invalid path '%s'" "$passeddir" | ||||
| [[ ! -d $chrootdir/root ]] && die "Missing chroot dir root directory. Try using: mkarchroot %s/root base-devel" "$chrootdir" | ||||
|  | ||||
| # Detect chrootdir filesystem type | ||||
| chroottype=$(stat -f -c %T "$chrootdir") | ||||
|  | ||||
| if [[ ${copy:0:1} = / ]]; then | ||||
| 	copydir=$copy | ||||
| else | ||||
| 	[[ -z $copy ]] && copy=$default_copy | ||||
| 	copydir="$chrootdir/$copy" | ||||
| fi | ||||
|  | ||||
| @@ -96,224 +104,266 @@ for arg in ${*:$OPTIND}; do | ||||
| 	fi | ||||
| done | ||||
|  | ||||
| if (( EUID )); then | ||||
| 	die 'This script must be run as root.' | ||||
| if [[ -n $SUDO_USER ]]; then | ||||
| 	USER_HOME=$(eval echo ~$SUDO_USER) | ||||
| else | ||||
| 	USER_HOME=$HOME | ||||
| fi | ||||
|  | ||||
| if [[ ! -f PKGBUILD && -z "${install_pkgs[*]}" ]]; then | ||||
| 	die 'This must be run in a directory containing a PKGBUILD.' | ||||
| fi | ||||
| # {{{ functions | ||||
| load_vars() { | ||||
| 	local makepkg_conf="$1" var | ||||
|  | ||||
| if [[ ! -d $chrootdir ]]; then | ||||
| 	die "No chroot dir defined, or invalid path '$passeddir'" | ||||
| fi | ||||
| 	[[ -f $makepkg_conf ]] || return 1 | ||||
|  | ||||
| if [[ ! -d $chrootdir/root ]]; then | ||||
| 	die "Missing chroot dir root directory. Try using: mkarchroot $chrootdir/root base-devel" | ||||
| fi | ||||
| 	for var in {SRC,PKG,LOG}DEST MAKEFLAGS PACKAGER; do | ||||
| 		[[ -z ${!var} ]] && eval $(grep "^${var}=" "$makepkg_conf") | ||||
| 	done | ||||
|  | ||||
| umask 0022 | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| # Detect chrootdir filesystem type | ||||
| chroottype=$(stat -f -c %T "$chrootdir") | ||||
| create_chroot() { | ||||
| 	# Lock the chroot we want to use. We'll keep this lock until we exit. | ||||
| 	lock 9 "$copydir.lock" "Locking chroot copy [$copy]" | ||||
|  | ||||
| # Lock the chroot we want to use. We'll keep this lock until we exit. | ||||
| # Note this is the same FD number as in mkarchroot | ||||
| exec 9>"$copydir.lock" | ||||
| if ! flock -n 9; then | ||||
| 	stat_busy "Locking chroot copy [$copy]" | ||||
| 	flock 9 | ||||
| 	stat_done | ||||
| fi | ||||
| 	if [[ ! -d $copydir ]] || $clean_first; then | ||||
| 		# Get a read lock on the root chroot to make | ||||
| 		# sure we don't clone a half-updated chroot | ||||
| 		slock 8 "$chrootdir/root.lock" "Locking clean chroot" | ||||
|  | ||||
| if [[ ! -d $copydir ]] || $clean_first; then | ||||
| 	# Get a read lock on the root chroot to make | ||||
| 	# sure we don't clone a half-updated chroot | ||||
| 	exec 8>"$chrootdir/root.lock" | ||||
|  | ||||
| 	if ! flock -sn 8; then | ||||
| 		stat_busy "Locking clean chroot" | ||||
| 		flock -s 8 | ||||
| 		stat_done | ||||
| 	fi | ||||
|  | ||||
| 	stat_busy "Creating clean working copy [$copy]" | ||||
| 	if [[ "$chroottype" == btrfs ]]; then | ||||
| 		if [[ -d $copydir ]]; then | ||||
| 			btrfs subvolume delete "$copydir" >/dev/null || | ||||
| 				die "Unable to delete subvolume $copydir" | ||||
| 		stat_busy "Creating clean working copy [$copy]" | ||||
| 		if [[ "$chroottype" == btrfs ]]; then | ||||
| 			if [[ -d $copydir ]]; then | ||||
| 				btrfs subvolume delete "$copydir" >/dev/null || | ||||
| 					die "Unable to delete subvolume %s" "$copydir" | ||||
| 			fi | ||||
| 			btrfs subvolume snapshot "$chrootdir/root" "$copydir" >/dev/null || | ||||
| 				die "Unable to create subvolume %s" "$copydir" | ||||
| 		else | ||||
| 			mkdir -p "$copydir" | ||||
| 			rsync -a --delete -q -W -x "$chrootdir/root/" "$copydir" | ||||
| 		fi | ||||
| 		btrfs subvolume snapshot "$chrootdir/root" "$copydir" >/dev/null || | ||||
| 			die "Unable to create subvolume $copydir" | ||||
| 	else | ||||
| 		mkdir -p "$copydir" | ||||
| 		rsync -a --delete -q -W -x "$chrootdir/root/" "$copydir" | ||||
| 		stat_done | ||||
|  | ||||
| 		# Drop the read lock again | ||||
| 		exec 8>&- | ||||
| 	fi | ||||
| } | ||||
|  | ||||
| clean_temporary() { | ||||
| 	stat_busy "Removing temporary copy [$copy]" | ||||
| 	if [[ "$chroottype" == btrfs ]]; then | ||||
| 		btrfs subvolume delete "$copydir" >/dev/null || | ||||
| 			die "Unable to delete subvolume %s" "$copydir" | ||||
| 	else | ||||
| 		# avoid change of filesystem in case of an umount failure | ||||
| 		rm --recursive --force --one-file-system "$copydir" || | ||||
| 			die "Unable to delete %s" "$copydir" | ||||
| 	fi | ||||
|  | ||||
| 	# remove lock file | ||||
| 	rm -f "$copydir.lock" | ||||
| 	stat_done | ||||
| } | ||||
|  | ||||
| 	# Drop the read lock again | ||||
| 	exec 8>&- | ||||
| fi | ||||
| install_packages() { | ||||
| 	local pkgname | ||||
|  | ||||
| if [[ -n "${install_pkgs[*]}" ]]; then | ||||
| 	for install_pkg in "${install_pkgs[@]}"; do | ||||
| 		pkgname="${install_pkg##*/}" | ||||
| 		cp "$install_pkg" "$copydir/$pkgname" | ||||
|  | ||||
| 		mkarchroot -r "pacman -U /$pkgname --noconfirm" "$copydir" | ||||
| 		arch-nspawn "$copydir" pacman -U /$pkgname --noconfirm | ||||
| 		(( ret += !! $? )) | ||||
|  | ||||
| 		rm "$copydir/$pkgname" | ||||
| 	done | ||||
|  | ||||
| 	# If there is no PKGBUILD we have done | ||||
| 	# If there is no PKGBUILD we are done | ||||
| 	[[ -f PKGBUILD ]] || exit $ret | ||||
| fi | ||||
| } | ||||
|  | ||||
| $update_first && mkarchroot -u "$copydir" | ||||
| prepare_chroot() { | ||||
| 	$repack || rm -rf "$copydir/build" | ||||
|  | ||||
| mkdir -p "$copydir/build" | ||||
|  | ||||
| # Remove anything in there UNLESS -R (repack) was passed to makepkg | ||||
| $repack || rm -rf "$copydir"/build/* | ||||
|  | ||||
| # Read .makepkg.conf and .gnupg/pubring.gpg even if called via sudo | ||||
| if [[ -n $SUDO_USER ]]; then | ||||
| 	SUDO_HOME="$(eval echo ~$SUDO_USER)" | ||||
| 	makepkg_conf="$SUDO_HOME/.makepkg.conf" | ||||
| 	if [[ -r "$SUDO_HOME/.gnupg/pubring.gpg" ]]; then | ||||
| 		install -D "$SUDO_HOME/.gnupg/pubring.gpg" "$copydir/build/.gnupg/pubring.gpg" | ||||
| 	mkdir -p "$copydir/build" | ||||
| 	if ! grep -q 'BUILDDIR="/build"' "$copydir/etc/makepkg.conf"; then | ||||
| 		echo 'BUILDDIR="/build"' >> "$copydir/etc/makepkg.conf" | ||||
| 	fi | ||||
| else | ||||
| 	makepkg_conf="$HOME/.makepkg.conf" | ||||
| 	if [[ -r "$HOME/.gnupg/pubring.gpg" ]]; then | ||||
| 		install -D "$HOME/.gnupg/pubring.gpg" "$copydir/build/.gnupg/pubring.gpg" | ||||
|  | ||||
| 	# Read .makepkg.conf and .gnupg/pubring.gpg even if called via sudo | ||||
| 	if [[ -r "$USER_HOME/.gnupg/pubring.gpg" ]]; then | ||||
| 		install -D "$USER_HOME/.gnupg/pubring.gpg" \ | ||||
| 			   "$copydir/build/.gnupg/pubring.gpg" | ||||
| 	fi | ||||
| fi | ||||
|  | ||||
| # Get SRC/PKGDEST from makepkg.conf | ||||
| if [[ -f $makepkg_conf ]]; then | ||||
| 	eval $(grep '^SRCDEST=' "$makepkg_conf") | ||||
| 	eval $(grep '^PKGDEST=' "$makepkg_conf") | ||||
| 	eval $(grep '^MAKEFLAGS=' "$makepkg_conf") | ||||
| 	eval $(grep '^PACKAGER=' "$makepkg_conf") | ||||
| fi | ||||
| 	mkdir -p "$copydir/pkgdest" | ||||
| 	if ! grep -q 'PKGDEST="/pkgdest"' "$copydir/etc/makepkg.conf"; then | ||||
| 		echo 'PKGDEST="/pkgdest"' >> "$copydir/etc/makepkg.conf" | ||||
| 	fi | ||||
|  | ||||
| [[ -z $SRCDEST ]] && eval $(grep '^SRCDEST=' /etc/makepkg.conf) | ||||
| [[ -z $PKGDEST ]] && eval $(grep '^PKGDEST=' /etc/makepkg.conf) | ||||
| [[ -z $MAKEFLAGS ]] && eval $(grep '^MAKEFLAGS=' /etc/makepkg.conf) | ||||
| [[ -z $PACKAGER ]] && eval $(grep '^PACKAGER=' /etc/makepkg.conf) | ||||
| 	mkdir -p "$copydir/logdest" | ||||
| 	if ! grep -q 'LOGDEST="/logdest"' "$copydir/etc/makepkg.conf"; then | ||||
| 		echo 'LOGDEST="/logdest"' >> "$copydir/etc/makepkg.conf" | ||||
| 	fi | ||||
|  | ||||
| # Use PKGBUILD directory if PKGDEST or SRCDEST don't exist | ||||
| [[ -d $PKGDEST ]] || PKGDEST=. | ||||
| [[ -d $SRCDEST ]] || SRCDEST=. | ||||
| 	# These two get bind-mounted read-only | ||||
| 	# XXX: makepkg dislikes having these dirs read-only, so separate them | ||||
| 	mkdir -p "$copydir/startdir" "$copydir/startdir_host" | ||||
| 	mkdir -p "$copydir/srcdest" "$copydir/srcdest_host" | ||||
| 	if ! grep -q 'SRCDEST="/srcdest"' "$copydir/etc/makepkg.conf"; then | ||||
| 		echo 'SRCDEST="/srcdest"' >> "$copydir/etc/makepkg.conf" | ||||
| 	fi | ||||
|  | ||||
| mkdir -p "$copydir/pkgdest" | ||||
| if ! grep -q 'PKGDEST="/pkgdest"' "$copydir/etc/makepkg.conf"; then | ||||
| 	echo 'PKGDEST="/pkgdest"' >> "$copydir/etc/makepkg.conf" | ||||
| fi | ||||
| 	chown -R nobody "$copydir"/{build,pkgdest,logdest,srcdest,startdir} | ||||
|  | ||||
| mkdir -p "$copydir/srcdest" | ||||
| if ! grep -q 'SRCDEST="/srcdest"' "$copydir/etc/makepkg.conf"; then | ||||
| 	echo 'SRCDEST="/srcdest"' >> "$copydir/etc/makepkg.conf" | ||||
| fi | ||||
| 	if [[ -n $MAKEFLAGS ]]; then | ||||
| 		sed -i '/^MAKEFLAGS=/d' "$copydir/etc/makepkg.conf" | ||||
| 		echo "MAKEFLAGS='${MAKEFLAGS}'" >> "$copydir/etc/makepkg.conf" | ||||
| 	fi | ||||
|  | ||||
| if [[ -n $MAKEFLAGS ]]; then | ||||
| 	sed -i '/^MAKEFLAGS=/d' "$copydir/etc/makepkg.conf" | ||||
| 	echo "MAKEFLAGS='${MAKEFLAGS}'" >> "$copydir/etc/makepkg.conf" | ||||
| fi | ||||
| 	if [[ -n $PACKAGER ]]; then | ||||
| 		sed -i '/^PACKAGER=/d' "$copydir/etc/makepkg.conf" | ||||
| 		echo "PACKAGER='${PACKAGER}'" >> "$copydir/etc/makepkg.conf" | ||||
| 	fi | ||||
|  | ||||
| if [[ -n $PACKAGER ]]; then | ||||
| 	sed -i '/^PACKAGER=/d' "$copydir/etc/makepkg.conf" | ||||
| 	echo "PACKAGER='${PACKAGER}'" >> "$copydir/etc/makepkg.conf" | ||||
| fi | ||||
|  | ||||
| # Set target CARCH as it might be used within the PKGBUILD to select correct sources | ||||
| eval $(grep '^CARCH=' "$copydir/etc/makepkg.conf") | ||||
| export CARCH | ||||
|  | ||||
| # Copy PKGBUILD and sources | ||||
| cp PKGBUILD "$copydir/build/" | ||||
| ( | ||||
| 	source PKGBUILD | ||||
| 	for file in "${source[@]}"; do | ||||
| 		file="${file%%::*}" | ||||
| 		file="${file##*://*/}" | ||||
| 		if [[ -f $file ]]; then | ||||
| 			cp "$file" "$copydir/srcdest/" | ||||
| 		elif [[ -f $SRCDEST/$file ]]; then | ||||
| 			cp "$SRCDEST/$file" "$copydir/srcdest/" | ||||
| 		fi | ||||
| 	done | ||||
|  | ||||
| 	# Find all changelog and install files, even inside functions | ||||
| 	for i in 'changelog' 'install'; do | ||||
| 		while read -r file; do | ||||
| 			# evaluate any bash variables used | ||||
| 			eval file=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "$file")\" | ||||
| 			[[ -f $file ]] && cp "$file" "$copydir/build/" | ||||
| 		done < <(sed -n "s/^[[:space:]]*$i=//p" PKGBUILD) | ||||
| 	done | ||||
| ) | ||||
|  | ||||
| chown -R nobody "$copydir"/{build,pkgdest,srcdest} | ||||
|  | ||||
| cat > "$copydir/etc/sudoers.d/nobody-pacman" <<EOF | ||||
| 	if [[ ! -f $copydir/etc/sudoers.d/nobody-pacman ]]; then | ||||
| 		cat > "$copydir/etc/sudoers.d/nobody-pacman" <<EOF | ||||
| Defaults env_keep += "HOME" | ||||
| nobody ALL = NOPASSWD: /usr/bin/pacman | ||||
| EOF | ||||
| chmod 440 "$copydir/etc/sudoers.d/nobody-pacman" | ||||
| 		chmod 440 "$copydir/etc/sudoers.d/nobody-pacman" | ||||
| 	fi | ||||
|  | ||||
| # This is a little gross, but this way the script is recreated every time in the | ||||
| # working copy | ||||
| cat >"$copydir/chrootbuild" <<EOF | ||||
| #!/bin/bash | ||||
| . /etc/profile | ||||
| export HOME=/build | ||||
| 	# This is a little gross, but this way the script is recreated every time in the | ||||
| 	# working copy | ||||
| 	printf $'#!/bin/bash\n%s\n_chrootbuild %q %q' "$(declare -f _chrootbuild)" \ | ||||
| 		"$makepkg_args" "$run_namcap" >"$copydir/chrootbuild" | ||||
| 	chmod +x "$copydir/chrootbuild" | ||||
| } | ||||
|  | ||||
| cd /build | ||||
| sudo -u nobody makepkg $makepkg_args || exit 1 | ||||
| download_sources() { | ||||
| 	local builddir="$(mktemp -d)" | ||||
| 	chmod 1777 "$builddir" | ||||
|  | ||||
| if $run_namcap; then | ||||
| 	pacman -S --needed --noconfirm namcap | ||||
| 	for pkgfile in /build/PKGBUILD /pkgdest/*.pkg.tar.?z; do | ||||
| 		echo "Checking \${pkgfile##*/}" | ||||
| 		sudo -u nobody namcap "\$pkgfile" 2>&1 | tee "/build/\${pkgfile##*/}-namcap.log" | ||||
| 	# Ensure sources are downloaded | ||||
| 	if [[ -n $SUDO_USER ]]; then | ||||
| 		sudo -u $SUDO_USER env SRCDEST="$SRCDEST" BUILDDIR="$builddir" \ | ||||
| 			makepkg --config="$copydir/etc/makepkg.conf" --verifysource -o | ||||
| 	else | ||||
| 		( export SRCDEST BUILDDIR="$builddir" | ||||
| 			makepkg --asroot --config="$copydir/etc/makepkg.conf" --verifysource -o | ||||
| 		) | ||||
| 	fi | ||||
| 	(( $? != 0 )) && die "Could not download sources." | ||||
|  | ||||
| 	# Clean up garbage from verifysource | ||||
| 	rm -rf $builddir | ||||
| } | ||||
|  | ||||
| _chrootbuild() { | ||||
| 	# This function isn't run in makechrootpkg, | ||||
| 	# so no global variables | ||||
| 	local makepkg_args="$1" | ||||
| 	local run_namcap="$2" | ||||
|  | ||||
| 	. /etc/profile | ||||
| 	export HOME=/build | ||||
| 	shopt -s nullglob | ||||
|  | ||||
| 	# XXX: Workaround makepkg disliking read-only dirs | ||||
| 	ln -sft /srcdest /srcdest_host/* | ||||
| 	ln -sft /startdir /startdir_host/* | ||||
|  | ||||
| 	# XXX: Keep svn sources writable | ||||
| 	# Since makepkg 4.1.1 they get checked out via cp -a, copying the symlink | ||||
| 	for dir in /srcdest /startdir; do | ||||
| 		cd $dir | ||||
| 		for svndir in */.svn; do | ||||
| 			rm ${svndir%/.svn} | ||||
| 			cp -a ${dir}_host/${svndir%/.svn} . | ||||
| 			chown -R nobody ${svndir%/.svn} | ||||
| 		done | ||||
| 	done | ||||
| fi | ||||
|  | ||||
| exit 0 | ||||
| EOF | ||||
| chmod +x "$copydir/chrootbuild" | ||||
| 	cd /startdir | ||||
|  | ||||
| if mkarchroot -r "/chrootbuild" "$copydir"; then | ||||
| 	for pkgfile in "$copydir"/pkgdest/*.pkg.tar.?z; do | ||||
| 		if $add_to_db; then | ||||
| 			mkdir -p "$copydir/repo" | ||||
| 			pushd "$copydir/repo" >/dev/null | ||||
| 			cp "$pkgfile" . | ||||
| 			repo-add repo.db.tar.gz "${pkgfile##*/}" | ||||
| 			popd >/dev/null | ||||
| 		fi | ||||
| 	# XXX: Keep PKGBUILD writable for pkgver() | ||||
| 	rm PKGBUILD* | ||||
| 	cp /startdir_host/PKGBUILD* . | ||||
| 	chown nobody PKGBUILD* | ||||
|  | ||||
| 	# Safety check | ||||
| 	if [[ ! -w PKGBUILD ]]; then | ||||
| 		echo "Can't write to PKGBUILD!" | ||||
| 		exit 1 | ||||
| 	fi | ||||
|  | ||||
| 	sudo -u nobody makepkg $makepkg_args || exit 1 | ||||
|  | ||||
| 	if $run_namcap; then | ||||
| 		pacman -S --needed --noconfirm namcap | ||||
| 		for pkgfile in /startdir/PKGBUILD /pkgdest/*; do | ||||
| 			echo "Checking ${pkgfile##*/}" | ||||
| 			sudo -u nobody namcap "$pkgfile" 2>&1 | tee "/logdest/${pkgfile##*/}-namcap.log" | ||||
| 		done | ||||
| 	fi | ||||
|  | ||||
| 	exit 0 | ||||
| } | ||||
|  | ||||
| move_products() { | ||||
| 	for pkgfile in "$copydir"/pkgdest/*; do | ||||
| 		chown "$src_owner" "$pkgfile" | ||||
| 		mv "$pkgfile" "$PKGDEST" | ||||
| 	done | ||||
|  | ||||
| 	for l in "$copydir"/build/*-{build,check,namcap,package,package_*}.log; do | ||||
| 	for l in "$copydir"/logdest/*; do | ||||
| 		chown "$src_owner" "$l" | ||||
| 		[[ -f $l ]] && mv "$l" . | ||||
| 		mv "$l" "$LOGDEST" | ||||
| 	done | ||||
| } | ||||
| # }}} | ||||
|  | ||||
| umask 0022 | ||||
|  | ||||
| load_vars "$USER_HOME/.makepkg.conf" | ||||
| load_vars /etc/makepkg.conf | ||||
|  | ||||
| # Use PKGBUILD directory if these don't exist | ||||
| [[ -d $PKGDEST ]] || PKGDEST=$PWD | ||||
| [[ -d $SRCDEST ]] || SRCDEST=$PWD | ||||
| [[ -d $LOGDEST ]] || LOGDEST=$PWD | ||||
|  | ||||
| create_chroot | ||||
|  | ||||
| $update_first && arch-nspawn "$copydir" pacman -Syu --noconfirm | ||||
|  | ||||
| [[ -n ${install_pkgs[*]} ]] && install_packages | ||||
|  | ||||
| prepare_chroot | ||||
|  | ||||
| download_sources | ||||
|  | ||||
| if arch-nspawn "$copydir" \ | ||||
| 	--bind-ro="$PWD:/startdir_host" \ | ||||
| 	--bind-ro="$SRCDEST:/srcdest_host" \ | ||||
| 	/chrootbuild | ||||
| then | ||||
| 	move_products | ||||
| else | ||||
| 	# Just in case. We returned 1, make sure we fail | ||||
| 	ret=1 | ||||
| 	(( ret += 1 )) | ||||
| fi | ||||
|  | ||||
| for f in "$copydir"/srcdest/*; do | ||||
| 	chown "$src_owner" "$f" | ||||
| 	mv "$f" "$SRCDEST" | ||||
| done | ||||
| $temp_chroot && clean_temporary | ||||
|  | ||||
| if (( ret != 0 )); then | ||||
| 	die "Build failed, check $copydir/build" | ||||
| 	if $temp_chroot; then | ||||
| 		die "Build failed" | ||||
| 	else | ||||
| 		die "Build failed, check %s/build" "$copydir" | ||||
| 	fi | ||||
| else | ||||
| 	true | ||||
| fi | ||||
|   | ||||
| @@ -109,6 +109,8 @@ PURGE_TARGETS=(usr/{,share}/info/dir .packlist *.pod) | ||||
| #SRCDEST=/home/sources | ||||
| #-- Source packages: specify a fixed directory where all src packages will be placed | ||||
| #SRCPKGDEST=/home/srcpackages | ||||
| #-- Log files: specify a fixed directory where all log files will be placed | ||||
| #LOGDEST=/home/makepkglogs | ||||
| #-- Packager: name/email of the person or organization building packages | ||||
| #PACKAGER="John Doe <john@doe.com>" | ||||
| #-- Specify a key to use for package signing | ||||
|   | ||||
| @@ -109,6 +109,8 @@ PURGE_TARGETS=(usr/{,share}/info/dir .packlist *.pod) | ||||
| #SRCDEST=/home/sources | ||||
| #-- Source packages: specify a fixed directory where all src packages will be placed | ||||
| #SRCPKGDEST=/home/srcpackages | ||||
| #-- Log files: specify a fixed directory where all log files will be placed | ||||
| #LOGDEST=/home/makepkglogs | ||||
| #-- Packager: name/email of the person or organization building packages | ||||
| #PACKAGER="John Doe <john@doe.com>" | ||||
| #-- Specify a key to use for package signing | ||||
|   | ||||
							
								
								
									
										176
									
								
								mkarchroot.in
									
									
									
									
									
								
							
							
						
						
									
										176
									
								
								mkarchroot.in
									
									
									
									
									
								
							| @@ -12,56 +12,33 @@ m4_include(lib/common.sh) | ||||
|  | ||||
| CHROOT_VERSION='v3' | ||||
|  | ||||
| FORCE='n' | ||||
| RUN='' | ||||
| NOCOPY='n' | ||||
|  | ||||
| working_dir='' | ||||
|  | ||||
| APPNAME=$(basename "${0}") | ||||
|  | ||||
| # usage: usage <exitvalue> | ||||
| usage() { | ||||
| 	echo "Usage: ${APPNAME} [options] working-dir [package-list | app]" | ||||
| 	echo "Usage: ${0##*/} [options] working-dir [package-list | app]" | ||||
| 	echo ' options:' | ||||
| 	echo '    -r <app>      Run "app" within the context of the chroot' | ||||
| 	echo '    -u            Update the chroot via pacman' | ||||
| 	echo '    -f            Force overwrite of files in the working-dir' | ||||
| 	echo '    -C <file>     Location of a pacman config file' | ||||
| 	echo '    -M <file>     Location of a makepkg config file' | ||||
| 	echo '    -n            Do not copy config files into the chroot' | ||||
| 	echo '    -c <dir>      Set pacman cache' | ||||
| 	echo '    -h            This message' | ||||
| 	exit 1 | ||||
| } | ||||
|  | ||||
| while getopts 'r:ufnhC:M:c:' arg; do | ||||
| 	case "${arg}" in | ||||
| 		r) RUN="$OPTARG" ;; | ||||
| 		u) RUN='pacman -Syu --noconfirm' ;; | ||||
| 		f) FORCE='y' ;; | ||||
| while getopts 'hC:M:c:' arg; do | ||||
| 	case "$arg" in | ||||
| 		C) pac_conf="$OPTARG" ;; | ||||
| 		M) makepkg_conf="$OPTARG" ;; | ||||
| 		n) NOCOPY='y' ;; | ||||
| 		c) cache_dir="$OPTARG" ;; | ||||
| 		h|?) usage ;; | ||||
| 		*) error "invalid argument '${arg}'"; usage ;; | ||||
| 		*) error "invalid argument '$arg'"; usage ;; | ||||
| 	esac | ||||
| done | ||||
|  | ||||
| if (( $EUID != 0 )); then | ||||
| 	die 'This script must be run as root.' | ||||
| fi | ||||
|  | ||||
| shift $(($OPTIND - 1)) | ||||
|  | ||||
| if [[ -z $RUN ]] && (( $# < 2 )); then | ||||
| 	die 'You must specify a directory and one or more packages.' | ||||
| elif (( $# < 1 )); then | ||||
| 	die 'You must specify a directory.' | ||||
| fi | ||||
| (( $EUID != 0 )) && die 'This script must be run as root.' | ||||
| (( $# < 2 )) && die 'You must specify a directory and one or more packages.' | ||||
|  | ||||
| working_dir="$(readlink -f ${1})" | ||||
| working_dir="$(readlink -f $1)" | ||||
| shift 1 | ||||
|  | ||||
| [[ -z $working_dir ]] && die 'Please specify a working directory.' | ||||
| @@ -72,120 +49,31 @@ else | ||||
| 	cache_dirs=(${cache_dir}) | ||||
| fi | ||||
|  | ||||
| host_mirror=$(pacman -Sddp extra/devtools 2>/dev/null | sed -E 's#(.*/)extra/os/.*#\1$repo/os/$arch#') | ||||
| if echo "${host_mirror}" | grep -q 'file://'; then | ||||
| 	host_mirror_path=$(echo "${host_mirror}" | sed -E 's#file://(/.*)/\$repo/os/\$arch#\1#g') | ||||
| fi | ||||
|  | ||||
| # {{{ functions | ||||
| build_mount_args() { | ||||
| 	local p | ||||
| 	declare -g mount_args=() | ||||
|  | ||||
| 	if [[ -n $host_mirror_path ]]; then | ||||
| 		printf -v p '%q' "$host_mirror_path" | ||||
| 		mount_args+=(--bind-ro="$p") | ||||
| 	fi | ||||
|  | ||||
| 	printf -v p '%q' "${cache_dirs[0]}" | ||||
| 	mount_args+=(--bind="$p") | ||||
|  | ||||
| 	for cache_dir in ${cache_dirs[@]:1}; do | ||||
| 		printf -v p '%q' "$cache_dir" | ||||
| 		mount_args+=(--bind-ro="$p") | ||||
| 	done | ||||
| } | ||||
|  | ||||
| copy_hostconf () { | ||||
| 	cp -a /etc/pacman.d/gnupg "${working_dir}/etc/pacman.d" | ||||
| 	echo "Server = ${host_mirror}" > ${working_dir}/etc/pacman.d/mirrorlist | ||||
|  | ||||
| 	if [[ -n $pac_conf && $NOCOPY = 'n' ]]; then | ||||
| 		cp ${pac_conf} ${working_dir}/etc/pacman.conf | ||||
| 	fi | ||||
|  | ||||
| 	if [[ -n $makepkg_conf && $NOCOPY = 'n' ]]; then | ||||
| 		cp ${makepkg_conf} ${working_dir}/etc/makepkg.conf | ||||
| 	fi | ||||
|  | ||||
| 	sed -r "s|^#?\\s*CacheDir.+|CacheDir = $(echo -n ${cache_dirs[@]})|g" -i ${working_dir}/etc/pacman.conf | ||||
| } | ||||
|  | ||||
| chroot_lock () { | ||||
| 	# Only reopen the FD if it wasn't handed to us | ||||
| 	if [[ $(readlink -f /dev/fd/9) != "${working_dir}.lock" ]]; then | ||||
| 	  exec 9>"${working_dir}.lock" | ||||
| 	fi | ||||
|  | ||||
| 	# Lock the chroot. Take note of the FD number. | ||||
| 	if ! flock -n 9; then | ||||
| 		stat_busy "Locking chroot" | ||||
| 		flock 9 | ||||
| 		stat_done | ||||
| 	fi | ||||
| } | ||||
|  | ||||
| chroot_run() { | ||||
| 	local dir=$1 | ||||
| 	shift | ||||
| 	systemd-nspawn -D "${dir}" "${mount_args[@]}" -- ${@} 2>/dev/null | ||||
| } | ||||
|  | ||||
| # }}} | ||||
|  | ||||
| umask 0022 | ||||
| if [[ -n $RUN ]]; then | ||||
| 	# run chroot {{{ | ||||
| 	#Sanity check | ||||
| 	if [[ ! -f "${working_dir}/.arch-chroot" ]]; then | ||||
| 		die "'${working_dir}' does not appear to be a Arch chroot." | ||||
| 	elif [[ $(cat "${working_dir}/.arch-chroot") != ${CHROOT_VERSION} ]]; then | ||||
| 		die "'${working_dir}' is not compatible with ${APPNAME} version ${CHROOT_VERSION}. Please rebuild." | ||||
|  | ||||
| [[ -e $working_dir ]] && die "Working directory '%s' already exists" "$working_dir" | ||||
|  | ||||
| mkdir -p "$working_dir" | ||||
|  | ||||
| lock 9 "${working_dir}.lock" "Locking chroot" | ||||
|  | ||||
| if [[ $(stat -f -c %T "$working_dir") == btrfs ]]; then | ||||
| 	rmdir "$working_dir" | ||||
| 	if ! btrfs subvolume create "$working_dir"; then | ||||
| 		die "Couldn't create subvolume for '%s'" "$working_dir" | ||||
| 	fi | ||||
|  | ||||
| 	chroot_lock | ||||
| 	build_mount_args | ||||
| 	copy_hostconf | ||||
|  | ||||
| 	chroot_run "${working_dir}" ${RUN} | ||||
|  | ||||
| 	# }}} | ||||
| else | ||||
| 	# {{{ build chroot | ||||
| 	if [[ -e $working_dir && $FORCE = 'n' ]]; then | ||||
| 		die "Working directory '${working_dir}' already exists - try using -f" | ||||
| 	fi | ||||
|  | ||||
| 	if [[ ! -d "${working_dir}" ]]; then | ||||
| 		mkdir -p "${working_dir}" | ||||
| 	fi | ||||
|  | ||||
| 	if [[ "$(stat -f -c %T "${working_dir}")" == btrfs ]]; then | ||||
| 		if { type -P btrfs && btrfs subvolume create "${working_dir}"; } &>/dev/null; then | ||||
| 			chmod 0755 "${working_dir}" | ||||
| 		fi | ||||
| 	fi | ||||
|  | ||||
| 	chroot_lock | ||||
|  | ||||
| 	pacargs=("${cache_dirs[@]/#/--cachedir=}") | ||||
| 	if [[ -n $pac_conf ]]; then | ||||
| 		pacargs+=("--config=${pac_conf}") | ||||
| 	fi | ||||
|  | ||||
| 	if [[ $FORCE = 'y' ]]; then | ||||
| 		pacargs+=("--force") | ||||
| 	fi | ||||
| 	if ! pacstrap -GMcd "${working_dir}" "${pacargs[@]}" "$@"; then | ||||
| 		die 'Failed to install all packages' | ||||
| 	fi | ||||
|  | ||||
| 	printf '%s.UTF-8 UTF-8\n' en_US de_DE > "${working_dir}/etc/locale.gen" | ||||
| 	chroot_run "${working_dir}" locale-gen | ||||
| 	echo 'LANG=C' > "${working_dir}/etc/locale.conf" | ||||
|  | ||||
| 	copy_hostconf | ||||
|  | ||||
| 	echo "${CHROOT_VERSION}" > "${working_dir}/.arch-chroot" | ||||
| 	# }}} | ||||
| 	chmod 0755 "$working_dir" | ||||
| fi | ||||
|  | ||||
| pacstrap -GMcd ${pac_conf:+-C "$pac_conf"} "$working_dir" \ | ||||
|   "${cache_dirs[@]/#/--cachedir=}" "$@" || die 'Failed to install all packages' | ||||
|  | ||||
| printf '%s.UTF-8 UTF-8\n' en_US de_DE > "$working_dir/etc/locale.gen" | ||||
| echo 'LANG=C' > "$working_dir/etc/locale.conf" | ||||
| echo "$CHROOT_VERSION" > "$working_dir/.arch-chroot" | ||||
|  | ||||
| exec arch-nspawn \ | ||||
| 	${pac_conf:+-C "$pac_conf"} \ | ||||
| 	${makepkg_conf:+-M "$makepkg_conf"} \ | ||||
| 	${cache_dir:+-c "$cache_dir"} \ | ||||
| 	"$working_dir" locale-gen | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| #compdef archbuild archco archrelease archrm commitpkg finddeps makechrootpkg mkarchroot rebuildpkgs extrapkg=commitpkg corepkg=commitpkg testingpkg=commitpkg stagingpkg=commitpkg communitypkg=commitpkg community-testingpkg=commitpkg community-stagingpkg=commitpkg multilibpkg=commitpkg multilib-testingpkg=commitpkg extra-i686-build=archbuild extra-x86_64-build=archbuild testing-i686-build=archbuild testing-x86_64-build=archbuild staging-i686-build=archbuild staging-x86_64-build=archbuild multilib-build=archbuild multilib-testing-build=archbuild multilib-staging-build=archbuild kde-unstable-i686-build=archbuild kde-unstable-x86_64-build=archbuild gnome-unstable-i686-build=archbuild gnome-unstable-x86_64-build=archbuild communityco=archco | ||||
| #compdef archbuild archco arch-nspawn archrelease archrm commitpkg finddeps makechrootpkg mkarchroot rebuildpkgs extrapkg=commitpkg corepkg=commitpkg testingpkg=commitpkg stagingpkg=commitpkg communitypkg=commitpkg community-testingpkg=commitpkg community-stagingpkg=commitpkg multilibpkg=commitpkg multilib-testingpkg=commitpkg extra-i686-build=archbuild extra-x86_64-build=archbuild testing-i686-build=archbuild testing-x86_64-build=archbuild staging-i686-build=archbuild staging-x86_64-build=archbuild multilib-build=archbuild multilib-testing-build=archbuild multilib-staging-build=archbuild kde-unstable-i686-build=archbuild kde-unstable-x86_64-build=archbuild gnome-unstable-i686-build=archbuild gnome-unstable-x86_64-build=archbuild communityco=archco | ||||
|  | ||||
| m4_include(lib/valid-tags.sh) | ||||
|  | ||||
| @@ -11,6 +11,13 @@ _archco_args=( | ||||
| 	'*:packages:_devtools_completions_all_packages' | ||||
| ) | ||||
|  | ||||
| _arch_nspawn_args=( | ||||
| 	'-C[Location of a pacman config file]:pacman_config:_files' | ||||
| 	'-M[Location of a makepkg config file]:makepkg_config:_files' | ||||
| 	'-c[Set pacman cache]:pacman_cache:_files -/' | ||||
| 	'-h[Display usage]' | ||||
| ) | ||||
|  | ||||
| _archrelease_args=( | ||||
| 	"*:arch:($_tags[*])" | ||||
| ) | ||||
| @@ -32,7 +39,6 @@ _finddeps_args=( | ||||
| _makechrootpkg_args=( | ||||
| 	'-I[Install a package into the working copy]:target:_files -g "*.pkg.tar.*(.)"' | ||||
| 	'-c[Clean the chroot before building]' | ||||
| 	'-d[Add the package to a local db at /repo after building]' | ||||
| 	'-h[Display usage]' | ||||
| 	'-l[The directory to use as the working copy]:copy_dir:_files -/' | ||||
| 	'-r[The chroot dir to use]:chroot_dir:_files -/' | ||||
| @@ -40,12 +46,8 @@ _makechrootpkg_args=( | ||||
| ) | ||||
|  | ||||
| _mkarchroot_args=( | ||||
| 	'-r[Run a program within the context of the chroot]:app' | ||||
| 	'-u[Update the chroot via pacman]' | ||||
| 	'-f[Force overwrite of files in the working-dir]' | ||||
| 	'-C[Location of a pacman config file]:pacman_config:_files' | ||||
| 	'-M[Location of a makepkg config file]:makepkg_config:_files' | ||||
| 	'-n[Do not copy config files into the chroot]' | ||||
| 	'-c[Set pacman cache]:pacman_cache:_files -/' | ||||
| 	'-h[Display usage]' | ||||
| ) | ||||
| @@ -62,7 +64,7 @@ _devtools_completions_all_packages() { | ||||
| } | ||||
|  | ||||
| _devtools() { | ||||
| 	local argname="_${service}_args[@]" | ||||
| 	local argname="_${service//-/_}_args[@]" | ||||
| 	_arguments -s "${(P)argname}" | ||||
| } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user