mirror of
				https://gitlab.archlinux.org/archlinux/devtools.git
				synced 2025-10-30 15:24:44 +01:00 
			
		
		
		
	Compare commits
	
		
			19 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 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 | zsh_completion | ||||||
| find-libdeps | find-libdeps | ||||||
| crossrepomove | crossrepomove | ||||||
|  | arch-nspawn | ||||||
|   | |||||||
							
								
								
									
										14
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								Makefile
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| V=20130406 | V=20130525 | ||||||
|  |  | ||||||
| PREFIX = /usr/local | PREFIX = /usr/local | ||||||
|  |  | ||||||
| @@ -13,9 +13,8 @@ BINPROGS = \ | |||||||
| 	finddeps \ | 	finddeps \ | ||||||
| 	rebuildpkgs \ | 	rebuildpkgs \ | ||||||
| 	find-libdeps \ | 	find-libdeps \ | ||||||
| 	crossrepomove | 	crossrepomove\ | ||||||
|  | 	arch-nspawn \ | ||||||
| SBINPROGS = \ |  | ||||||
| 	mkarchroot \ | 	mkarchroot \ | ||||||
| 	makechrootpkg | 	makechrootpkg | ||||||
|  |  | ||||||
| @@ -68,7 +67,7 @@ BASHCOMPLETION_LINKS = \ | |||||||
| 	archco \ | 	archco \ | ||||||
| 	communityco | 	communityco | ||||||
|  |  | ||||||
| all: $(BINPROGS) $(SBINPROGS) bash_completion zsh_completion | all: $(BINPROGS) bash_completion zsh_completion | ||||||
|  |  | ||||||
| edit = sed -e "s|@pkgdatadir[@]|$(DESTDIR)$(PREFIX)/share/devtools|g" | edit = sed -e "s|@pkgdatadir[@]|$(DESTDIR)$(PREFIX)/share/devtools|g" | ||||||
|  |  | ||||||
| @@ -80,14 +79,12 @@ edit = sed -e "s|@pkgdatadir[@]|$(DESTDIR)$(PREFIX)/share/devtools|g" | |||||||
| 	@chmod +x "$@" | 	@chmod +x "$@" | ||||||
|  |  | ||||||
| clean: | clean: | ||||||
| 	rm -f $(BINPROGS) $(SBINPROGS) bash_completion zsh_completion | 	rm -f $(BINPROGS) bash_completion zsh_completion | ||||||
|  |  | ||||||
| install: | install: | ||||||
| 	install -dm0755 $(DESTDIR)$(PREFIX)/bin | 	install -dm0755 $(DESTDIR)$(PREFIX)/bin | ||||||
| 	install -dm0755 $(DESTDIR)$(PREFIX)/sbin |  | ||||||
| 	install -dm0755 $(DESTDIR)$(PREFIX)/share/devtools | 	install -dm0755 $(DESTDIR)$(PREFIX)/share/devtools | ||||||
| 	install -m0755 ${BINPROGS} $(DESTDIR)$(PREFIX)/bin | 	install -m0755 ${BINPROGS} $(DESTDIR)$(PREFIX)/bin | ||||||
| 	install -m0755 ${SBINPROGS} $(DESTDIR)$(PREFIX)/sbin |  | ||||||
| 	install -m0644 ${CONFIGFILES} $(DESTDIR)$(PREFIX)/share/devtools | 	install -m0644 ${CONFIGFILES} $(DESTDIR)$(PREFIX)/share/devtools | ||||||
| 	for l in ${COMMITPKG_LINKS}; do ln -sf commitpkg $(DESTDIR)$(PREFIX)/bin/$$l; done | 	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 | 	for l in ${ARCHBUILD_LINKS}; do ln -sf archbuild $(DESTDIR)$(PREFIX)/bin/$$l; done | ||||||
| @@ -100,7 +97,6 @@ install: | |||||||
|  |  | ||||||
| uninstall: | uninstall: | ||||||
| 	for f in ${BINPROGS}; do rm -f $(DESTDIR)$(PREFIX)/bin/$$f; done | 	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 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 ${COMMITPKG_LINKS}; do rm -f $(DESTDIR)$(PREFIX)/bin/$$l; done | ||||||
| 	for l in ${ARCHBUILD_LINKS}; do rm -f $(DESTDIR)$(PREFIX)/bin/$$l; done | 	for l in ${ARCHBUILD_LINKS}; do rm -f $(DESTDIR)$(PREFIX)/bin/$$l; done | ||||||
|   | |||||||
							
								
								
									
										105
									
								
								arch-nspawn.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								arch-nspawn.in
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,105 @@ | |||||||
|  | #!/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 "'$working_dir' does not appear to be a Arch chroot." | ||||||
|  | elif [[ $(cat "$working_dir/.arch-chroot") != $CHROOT_VERSION ]]; then | ||||||
|  | 	die "chroot '$working_dir' is not at version $CHROOT_VERSION. Please rebuild." | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | build_mount_args | ||||||
|  | copy_hostconf | ||||||
|  |  | ||||||
|  | eval $(grep '^CARCH=' "$working_dir/etc/makepkg.conf") | ||||||
|  |  | ||||||
|  | exec ${CARCH:+setarch "$CARCH"} systemd-nspawn 2>/dev/null \ | ||||||
|  | 	-D "$working_dir" \ | ||||||
|  | 	--machine "${working_dir//\//-}" \ | ||||||
|  | 	"${mount_args[@]}" \ | ||||||
|  | 	"$@" | ||||||
							
								
								
									
										16
									
								
								archbuild.in
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								archbuild.in
									
									
									
									
									
								
							| @@ -51,12 +51,7 @@ if ${clean_first} || [[ ! -d "${chroots}/${repo}-${arch}" ]]; then | |||||||
| 		[[ -d $copy ]] || continue | 		[[ -d $copy ]] || continue | ||||||
| 		msg2 "Deleting chroot copy '$(basename "${copy}")'..." | 		msg2 "Deleting chroot copy '$(basename "${copy}")'..." | ||||||
|  |  | ||||||
| 		exec 9>"$copydir.lock" | 		lock 9 "$copydir.lock" "Locking chroot copy '$copy'" | ||||||
| 		if ! flock -n 9; then |  | ||||||
| 			stat_busy "Locking chroot copy '$copy'" |  | ||||||
| 			flock 9 |  | ||||||
| 			stat_done |  | ||||||
| 		fi |  | ||||||
|  |  | ||||||
| 		if [[ "$(stat -f -c %T "${copy}")" == btrfs ]]; then | 		if [[ "$(stat -f -c %T "${copy}")" == btrfs ]]; then | ||||||
| 			{ type -P btrfs && btrfs subvolume delete "${copy}"; } &>/dev/null | 			{ 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" \ | 		"${chroots}/${repo}-${arch}/root" \ | ||||||
| 		"${base_packages[@]}" || abort | 		"${base_packages[@]}" || abort | ||||||
| else | else | ||||||
| 	setarch ${arch} mkarchroot \ | 	lock 9 "${chroots}/${repo}-${arch}/root.lock" "Locking clean chroot" | ||||||
| 		-u \ | 	arch-nspawn \ | ||||||
| 		-C "@pkgdatadir@/pacman-${repo}.conf" \ | 		-C "@pkgdatadir@/pacman-${repo}.conf" \ | ||||||
| 		-M "@pkgdatadir@/makepkg-${arch}.conf" \ | 		-M "@pkgdatadir@/makepkg-${arch}.conf" \ | ||||||
| 		"${chroots}/${repo}-${arch}/root" || abort | 		"${chroots}/${repo}-${arch}/root" \ | ||||||
|  |                 pacman -Syu --noconfirm || abort | ||||||
| fi | fi | ||||||
|  |  | ||||||
| msg "Building in chroot for [${repo}] (${arch})..." | 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[@]}" | ||||||
|   | |||||||
| @@ -34,7 +34,7 @@ _makechrootpkg() { | |||||||
|  |  | ||||||
|   case $cur in |   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 |       _filedir | ||||||
| @@ -53,7 +53,7 @@ _mkarchroot() { | |||||||
|  |  | ||||||
|   case $cur in |   case $cur in | ||||||
|     -*) |     -*) | ||||||
|        COMPREPLY=( $( compgen -W '-C -M -c -f -h -n -r -u' -- "$cur" ) ) |        COMPREPLY=( $( compgen -W '-C -M -c -h' -- "$cur" ) ) | ||||||
|        ;; |        ;; | ||||||
|     *) |     *) | ||||||
|       _filedir |       _filedir | ||||||
| @@ -65,5 +65,22 @@ _mkarchroot() { | |||||||
| } && | } && | ||||||
| complete -F _mkarchroot 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 | # ex:et ts=2 sw=2 ft=sh | ||||||
|   | |||||||
| @@ -30,7 +30,6 @@ case $scriptname in | |||||||
| esac | esac | ||||||
|  |  | ||||||
| server='nymeria.archlinux.org' | server='nymeria.archlinux.org' | ||||||
| mirror="http://${server}" |  | ||||||
| source_svn="svn+ssh://svn-${source_name}@${server}/srv/repos/svn-${source_name}/svn" | 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" | target_svn="svn+ssh://svn-${target_name}@${server}/srv/repos/svn-${target_name}/svn" | ||||||
| source_dbscripts="/srv/repos/svn-${source_name}/dbscripts" | source_dbscripts="/srv/repos/svn-${source_name}/dbscripts" | ||||||
| @@ -55,10 +54,8 @@ for _arch in ${arch[@]}; do | |||||||
| 	fi | 	fi | ||||||
| 	for _pkgname in ${pkgname[@]}; do | 	for _pkgname in ${pkgname[@]}; do | ||||||
| 		fullver=$(get_full_version $_pkgname) | 		fullver=$(get_full_version $_pkgname) | ||||||
| 		# FIXME: this only works with .xz packages | 		pkgpath="/srv/ftp/$source_repo/os/$repo_arch/$_pkgname-$fullver-${_arch}.pkg.tar.*" | ||||||
| 		ssh "${server}" "cd staging/${target_repo} | 		ssh "$server" "cp $pkgpath staging/$target_repo" || die | ||||||
| 			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 |  | ||||||
| 	done | 	done | ||||||
| done | done | ||||||
|  |  | ||||||
|   | |||||||
| @@ -130,3 +130,27 @@ get_full_version() { | |||||||
| 		fi | 		fi | ||||||
| 	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 | shopt -s nullglob | ||||||
|  |  | ||||||
| makepkg_args='-s --noconfirm -L' | makepkg_args='-s --noconfirm -L --holdver' | ||||||
| repack=false | repack=false | ||||||
| update_first=false | update_first=false | ||||||
| clean_first=false | clean_first=false | ||||||
| install_pkg= | install_pkg= | ||||||
| add_to_db=false |  | ||||||
| run_namcap=false | run_namcap=false | ||||||
|  | temp_chroot=false | ||||||
| chrootdir= | chrootdir= | ||||||
| passeddir= | passeddir= | ||||||
| declare -a install_pkgs | declare -a install_pkgs | ||||||
| declare -i ret=0 | declare -i ret=0 | ||||||
|  |  | ||||||
| default_copy=$USER | copy=$USER | ||||||
| [[ -n $SUDO_USER ]] && default_copy=$SUDO_USER | [[ -n $SUDO_USER ]] && copy=$SUDO_USER | ||||||
| [[ -z $default_copy || $default_copy = root ]] && default_copy=copy | [[ -z "$copy" || $copy = root ]] && copy=copy | ||||||
| src_owner=${SUDO_USER:-$USER} | src_owner=${SUDO_USER:-$USER} | ||||||
|  |  | ||||||
| usage() { | usage() { | ||||||
| @@ -51,37 +51,45 @@ usage() { | |||||||
| 	echo '-u         Update the working copy of the chroot before building' | 	echo '-u         Update the working copy of the chroot before building' | ||||||
| 	echo '           This is useful for rebuilds without dirtying the pristine' | 	echo '           This is useful for rebuilds without dirtying the pristine' | ||||||
| 	echo '           chroot' | 	echo '           chroot' | ||||||
| 	echo '-d         Add the package to a local db at /repo after building' |  | ||||||
| 	echo '-r <dir>   The chroot dir to use' | 	echo '-r <dir>   The chroot dir to use' | ||||||
| 	echo '-I <pkg>   Install a package into the working copy of the chroot' | 	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 '-l <copy>  The directory to use as the working copy of the chroot' | ||||||
| 	echo '           Useful for maintaining multiple copies.' | 	echo '           Useful for maintaining multiple copies' | ||||||
| 	echo "           Default: $default_copy" | 	echo "           Default: $copy" | ||||||
| 	echo '-n         Run namcap on the package' | 	echo '-n         Run namcap on the package' | ||||||
|  | 	echo '-T         Build in a temporary directory' | ||||||
| 	exit 1 | 	exit 1 | ||||||
| } | } | ||||||
|  |  | ||||||
| while getopts 'hcudr:I:l:n' arg; do | while getopts 'hcur:I:l:nT' arg; do | ||||||
| 	case "$arg" in | 	case "$arg" in | ||||||
| 		h) usage ;; | 		h) usage ;; | ||||||
| 		c) clean_first=true ;; | 		c) clean_first=true ;; | ||||||
| 		u) update_first=true ;; | 		u) update_first=true ;; | ||||||
| 		d) add_to_db=true ;; |  | ||||||
| 		r) passeddir="$OPTARG" ;; | 		r) passeddir="$OPTARG" ;; | ||||||
| 		I) install_pkgs+=("$OPTARG") ;; | 		I) install_pkgs+=("$OPTARG") ;; | ||||||
| 		l) copy="$OPTARG" ;; | 		l) copy="$OPTARG" ;; | ||||||
| 		n) run_namcap=true; makepkg_args="$makepkg_args -i" ;; | 		n) run_namcap=true; makepkg_args="$makepkg_args -i" ;; | ||||||
|  | 		T) temp_chroot=true; copy+="-$$" ;; | ||||||
| 		*) makepkg_args="$makepkg_args -$arg $OPTARG" ;; | 		*) makepkg_args="$makepkg_args -$arg $OPTARG" ;; | ||||||
| 	esac | 	esac | ||||||
| done | 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 / | # Canonicalize chrootdir, getting rid of trailing / | ||||||
| chrootdir=$(readlink -e "$passeddir") | chrootdir=$(readlink -e "$passeddir") | ||||||
|  | [[ ! -d $chrootdir ]] && die "No chroot dir defined, or invalid path '$passeddir'" | ||||||
|  | [[ ! -d $chrootdir/root ]] && die "Missing chroot dir root directory. Try using: mkarchroot $chrootdir/root base-devel" | ||||||
|  |  | ||||||
|  | # Detect chrootdir filesystem type | ||||||
|  | chroottype=$(stat -f -c %T "$chrootdir") | ||||||
|  |  | ||||||
| if [[ ${copy:0:1} = / ]]; then | if [[ ${copy:0:1} = / ]]; then | ||||||
| 	copydir=$copy | 	copydir=$copy | ||||||
| else | else | ||||||
| 	[[ -z $copy ]] && copy=$default_copy |  | ||||||
| 	copydir="$chrootdir/$copy" | 	copydir="$chrootdir/$copy" | ||||||
| fi | fi | ||||||
|  |  | ||||||
| @@ -96,224 +104,266 @@ for arg in ${*:$OPTIND}; do | |||||||
| 	fi | 	fi | ||||||
| done | done | ||||||
|  |  | ||||||
| if (( EUID )); then | if [[ -n $SUDO_USER ]]; then | ||||||
| 	die 'This script must be run as root.' | 	USER_HOME=$(eval echo ~$SUDO_USER) | ||||||
|  | else | ||||||
|  | 	USER_HOME=$HOME | ||||||
| fi | fi | ||||||
|  |  | ||||||
| if [[ ! -f PKGBUILD && -z "${install_pkgs[*]}" ]]; then | # {{{ functions | ||||||
| 	die 'This must be run in a directory containing a PKGBUILD.' | load_vars() { | ||||||
| fi | 	local makepkg_conf="$1" var | ||||||
|  |  | ||||||
| if [[ ! -d $chrootdir ]]; then | 	[[ -f $makepkg_conf ]] || return 1 | ||||||
| 	die "No chroot dir defined, or invalid path '$passeddir'" |  | ||||||
| fi |  | ||||||
|  |  | ||||||
| if [[ ! -d $chrootdir/root ]]; then | 	for var in {SRC,PKG,LOG}DEST MAKEFLAGS PACKAGER; do | ||||||
| 	die "Missing chroot dir root directory. Try using: mkarchroot $chrootdir/root base-devel" | 		[[ -z ${!var} ]] && eval $(grep "^${var}=" "$makepkg_conf") | ||||||
| fi | 	done | ||||||
|  |  | ||||||
| umask 0022 | 	return 0 | ||||||
|  | } | ||||||
|  |  | ||||||
| # Detect chrootdir filesystem type | create_chroot() { | ||||||
| chroottype=$(stat -f -c %T "$chrootdir") | 	# 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. | 	if [[ ! -d $copydir ]] || $clean_first; then | ||||||
| # Note this is the same FD number as in mkarchroot | 		# Get a read lock on the root chroot to make | ||||||
| exec 9>"$copydir.lock" | 		# sure we don't clone a half-updated chroot | ||||||
| if ! flock -n 9; then | 		slock 8 "$chrootdir/root.lock" "Locking clean chroot" | ||||||
| 	stat_busy "Locking chroot copy [$copy]" |  | ||||||
| 	flock 9 |  | ||||||
| 	stat_done |  | ||||||
| fi |  | ||||||
|  |  | ||||||
| if [[ ! -d $copydir ]] || $clean_first; then | 		stat_busy "Creating clean working copy [$copy]" | ||||||
| 	# Get a read lock on the root chroot to make | 		if [[ "$chroottype" == btrfs ]]; then | ||||||
| 	# sure we don't clone a half-updated chroot | 			if [[ -d $copydir ]]; then | ||||||
| 	exec 8>"$chrootdir/root.lock" | 				btrfs subvolume delete "$copydir" >/dev/null || | ||||||
|  | 					die "Unable to delete subvolume $copydir" | ||||||
| 	if ! flock -sn 8; then | 			fi | ||||||
| 		stat_busy "Locking clean chroot" | 			btrfs subvolume snapshot "$chrootdir/root" "$copydir" >/dev/null || | ||||||
| 		flock -s 8 | 				die "Unable to create subvolume $copydir" | ||||||
| 		stat_done | 		else | ||||||
| 	fi | 			mkdir -p "$copydir" | ||||||
|  | 			rsync -a --delete -q -W -x "$chrootdir/root/" "$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 $copydir" |  | ||||||
| 		fi | 		fi | ||||||
| 		btrfs subvolume snapshot "$chrootdir/root" "$copydir" >/dev/null || | 		stat_done | ||||||
| 			die "Unable to create subvolume $copydir" |  | ||||||
| 	else | 		# Drop the read lock again | ||||||
| 		mkdir -p "$copydir" | 		exec 8>&- | ||||||
| 		rsync -a --delete -q -W -x "$chrootdir/root/" "$copydir" |  | ||||||
| 	fi | 	fi | ||||||
|  | } | ||||||
|  |  | ||||||
|  | clean_temporary() { | ||||||
|  | 	stat_busy "Removing temporary copy [$copy]" | ||||||
|  | 	if [[ "$chroottype" == btrfs ]]; then | ||||||
|  | 		btrfs subvolume delete "$copydir" >/dev/null || | ||||||
|  | 			die "Unable to delete subvolume $copydir" | ||||||
|  | 	else | ||||||
|  | 		# avoid change of filesystem in case of an umount failure | ||||||
|  | 		rm --recursive --force --one-file-system "$copydir" || | ||||||
|  | 			die "Unable to delete $copydir" | ||||||
|  | 	fi | ||||||
|  |  | ||||||
|  | 	# remove lock file | ||||||
|  | 	rm -f "$copydir.lock" | ||||||
| 	stat_done | 	stat_done | ||||||
|  | } | ||||||
|  |  | ||||||
| 	# Drop the read lock again | install_packages() { | ||||||
| 	exec 8>&- | 	local pkgname | ||||||
| fi |  | ||||||
|  |  | ||||||
| if [[ -n "${install_pkgs[*]}" ]]; then |  | ||||||
| 	for install_pkg in "${install_pkgs[@]}"; do | 	for install_pkg in "${install_pkgs[@]}"; do | ||||||
| 		pkgname="${install_pkg##*/}" | 		pkgname="${install_pkg##*/}" | ||||||
| 		cp "$install_pkg" "$copydir/$pkgname" | 		cp "$install_pkg" "$copydir/$pkgname" | ||||||
|  |  | ||||||
| 		mkarchroot -r "pacman -U /$pkgname --noconfirm" "$copydir" | 		arch-nspawn "$copydir" pacman -U /$pkgname --noconfirm | ||||||
| 		(( ret += !! $? )) | 		(( ret += !! $? )) | ||||||
|  |  | ||||||
| 		rm "$copydir/$pkgname" | 		rm "$copydir/$pkgname" | ||||||
| 	done | 	done | ||||||
|  |  | ||||||
| 	# If there is no PKGBUILD we have done | 	# If there is no PKGBUILD we are done | ||||||
| 	[[ -f PKGBUILD ]] || exit $ret | 	[[ -f PKGBUILD ]] || exit $ret | ||||||
| fi | } | ||||||
|  |  | ||||||
| $update_first && mkarchroot -u "$copydir" | prepare_chroot() { | ||||||
|  | 	$repack || rm -rf "$copydir/build" | ||||||
|  |  | ||||||
| mkdir -p "$copydir/build" | 	mkdir -p "$copydir/build" | ||||||
|  | 	if ! grep -q 'BUILDDIR="/build"' "$copydir/etc/makepkg.conf"; then | ||||||
| # Remove anything in there UNLESS -R (repack) was passed to makepkg | 		echo 'BUILDDIR="/build"' >> "$copydir/etc/makepkg.conf" | ||||||
| $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" |  | ||||||
| 	fi | 	fi | ||||||
| else |  | ||||||
| 	makepkg_conf="$HOME/.makepkg.conf" | 	# Read .makepkg.conf and .gnupg/pubring.gpg even if called via sudo | ||||||
| 	if [[ -r "$HOME/.gnupg/pubring.gpg" ]]; then | 	if [[ -r "$USER_HOME/.gnupg/pubring.gpg" ]]; then | ||||||
| 		install -D "$HOME/.gnupg/pubring.gpg" "$copydir/build/.gnupg/pubring.gpg" | 		install -D "$USER_HOME/.gnupg/pubring.gpg" \ | ||||||
|  | 			   "$copydir/build/.gnupg/pubring.gpg" | ||||||
| 	fi | 	fi | ||||||
| fi |  | ||||||
|  |  | ||||||
| # Get SRC/PKGDEST from makepkg.conf | 	mkdir -p "$copydir/pkgdest" | ||||||
| if [[ -f $makepkg_conf ]]; then | 	if ! grep -q 'PKGDEST="/pkgdest"' "$copydir/etc/makepkg.conf"; then | ||||||
| 	eval $(grep '^SRCDEST=' "$makepkg_conf") | 		echo 'PKGDEST="/pkgdest"' >> "$copydir/etc/makepkg.conf" | ||||||
| 	eval $(grep '^PKGDEST=' "$makepkg_conf") | 	fi | ||||||
| 	eval $(grep '^MAKEFLAGS=' "$makepkg_conf") |  | ||||||
| 	eval $(grep '^PACKAGER=' "$makepkg_conf") |  | ||||||
| fi |  | ||||||
|  |  | ||||||
| [[ -z $SRCDEST ]] && eval $(grep '^SRCDEST=' /etc/makepkg.conf) | 	mkdir -p "$copydir/logdest" | ||||||
| [[ -z $PKGDEST ]] && eval $(grep '^PKGDEST=' /etc/makepkg.conf) | 	if ! grep -q 'LOGDEST="/logdest"' "$copydir/etc/makepkg.conf"; then | ||||||
| [[ -z $MAKEFLAGS ]] && eval $(grep '^MAKEFLAGS=' /etc/makepkg.conf) | 		echo 'LOGDEST="/logdest"' >> "$copydir/etc/makepkg.conf" | ||||||
| [[ -z $PACKAGER ]] && eval $(grep '^PACKAGER=' /etc/makepkg.conf) | 	fi | ||||||
|  |  | ||||||
| # Use PKGBUILD directory if PKGDEST or SRCDEST don't exist | 	# These two get bind-mounted read-only | ||||||
| [[ -d $PKGDEST ]] || PKGDEST=. | 	# XXX: makepkg dislikes having these dirs read-only, so separate them | ||||||
| [[ -d $SRCDEST ]] || SRCDEST=. | 	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" | 	chown -R nobody "$copydir"/{build,pkgdest,logdest,srcdest,startdir} | ||||||
| if ! grep -q 'PKGDEST="/pkgdest"' "$copydir/etc/makepkg.conf"; then |  | ||||||
| 	echo 'PKGDEST="/pkgdest"' >> "$copydir/etc/makepkg.conf" |  | ||||||
| fi |  | ||||||
|  |  | ||||||
| mkdir -p "$copydir/srcdest" | 	if [[ -n $MAKEFLAGS ]]; then | ||||||
| if ! grep -q 'SRCDEST="/srcdest"' "$copydir/etc/makepkg.conf"; then | 		sed -i '/^MAKEFLAGS=/d' "$copydir/etc/makepkg.conf" | ||||||
| 	echo 'SRCDEST="/srcdest"' >> "$copydir/etc/makepkg.conf" | 		echo "MAKEFLAGS='${MAKEFLAGS}'" >> "$copydir/etc/makepkg.conf" | ||||||
| fi | 	fi | ||||||
|  |  | ||||||
| if [[ -n $MAKEFLAGS ]]; then | 	if [[ -n $PACKAGER ]]; then | ||||||
| 	sed -i '/^MAKEFLAGS=/d' "$copydir/etc/makepkg.conf" | 		sed -i '/^PACKAGER=/d' "$copydir/etc/makepkg.conf" | ||||||
| 	echo "MAKEFLAGS='${MAKEFLAGS}'" >> "$copydir/etc/makepkg.conf" | 		echo "PACKAGER='${PACKAGER}'" >> "$copydir/etc/makepkg.conf" | ||||||
| fi | 	fi | ||||||
|  |  | ||||||
| if [[ -n $PACKAGER ]]; then | 	if [[ ! -f $copydir/etc/sudoers.d/nobody-pacman ]]; then | ||||||
| 	sed -i '/^PACKAGER=/d' "$copydir/etc/makepkg.conf" | 		cat > "$copydir/etc/sudoers.d/nobody-pacman" <<EOF | ||||||
| 	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 |  | ||||||
| Defaults env_keep += "HOME" | Defaults env_keep += "HOME" | ||||||
| nobody ALL = NOPASSWD: /usr/bin/pacman | nobody ALL = NOPASSWD: /usr/bin/pacman | ||||||
| EOF | 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 | 	# This is a little gross, but this way the script is recreated every time in the | ||||||
| # working copy | 	# working copy | ||||||
| cat >"$copydir/chrootbuild" <<EOF | 	printf $'#!/bin/bash\n%s\n_chrootbuild %q %q' "$(declare -f _chrootbuild)" \ | ||||||
| #!/bin/bash | 		"$makepkg_args" "$run_namcap" >"$copydir/chrootbuild" | ||||||
| . /etc/profile | 	chmod +x "$copydir/chrootbuild" | ||||||
| export HOME=/build | } | ||||||
|  |  | ||||||
| cd /build | download_sources() { | ||||||
| sudo -u nobody makepkg $makepkg_args || exit 1 | 	local builddir="$(mktemp -d)" | ||||||
|  | 	chmod 1777 "$builddir" | ||||||
|  |  | ||||||
| if $run_namcap; then | 	# Ensure sources are downloaded | ||||||
| 	pacman -S --needed --noconfirm namcap | 	if [[ -n $SUDO_USER ]]; then | ||||||
| 	for pkgfile in /build/PKGBUILD /pkgdest/*.pkg.tar.?z; do | 		sudo -u $SUDO_USER env SRCDEST="$SRCDEST" BUILDDIR="$builddir" \ | ||||||
| 		echo "Checking \${pkgfile##*/}" | 			makepkg --config="$copydir/etc/makepkg.conf" --verifysource -o | ||||||
| 		sudo -u nobody namcap "\$pkgfile" 2>&1 | tee "/build/\${pkgfile##*/}-namcap.log" | 	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 | 	done | ||||||
| fi |  | ||||||
|  |  | ||||||
| exit 0 | 	cd /startdir | ||||||
| EOF |  | ||||||
| chmod +x "$copydir/chrootbuild" |  | ||||||
|  |  | ||||||
| if mkarchroot -r "/chrootbuild" "$copydir"; then | 	# XXX: Keep PKGBUILD writable for pkgver() | ||||||
| 	for pkgfile in "$copydir"/pkgdest/*.pkg.tar.?z; do | 	rm PKGBUILD* | ||||||
| 		if $add_to_db; then | 	cp /startdir_host/PKGBUILD* . | ||||||
| 			mkdir -p "$copydir/repo" | 	chown nobody PKGBUILD* | ||||||
| 			pushd "$copydir/repo" >/dev/null |  | ||||||
| 			cp "$pkgfile" . |  | ||||||
| 			repo-add repo.db.tar.gz "${pkgfile##*/}" |  | ||||||
| 			popd >/dev/null |  | ||||||
| 		fi |  | ||||||
|  |  | ||||||
|  | 	# 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" | 		chown "$src_owner" "$pkgfile" | ||||||
| 		mv "$pkgfile" "$PKGDEST" | 		mv "$pkgfile" "$PKGDEST" | ||||||
| 	done | 	done | ||||||
|  |  | ||||||
| 	for l in "$copydir"/build/*-{build,check,namcap,package,package_*}.log; do | 	for l in "$copydir"/logdest/*; do | ||||||
| 		chown "$src_owner" "$l" | 		chown "$src_owner" "$l" | ||||||
| 		[[ -f $l ]] && mv "$l" . | 		mv "$l" "$LOGDEST" | ||||||
| 	done | 	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 | else | ||||||
| 	# Just in case. We returned 1, make sure we fail | 	(( ret += 1 )) | ||||||
| 	ret=1 |  | ||||||
| fi | fi | ||||||
|  |  | ||||||
| for f in "$copydir"/srcdest/*; do | $temp_chroot && clean_temporary | ||||||
| 	chown "$src_owner" "$f" |  | ||||||
| 	mv "$f" "$SRCDEST" |  | ||||||
| done |  | ||||||
|  |  | ||||||
| if (( ret != 0 )); then | if (( ret != 0 )); then | ||||||
| 	die "Build failed, check $copydir/build" | 	if $temp_chroot; then | ||||||
|  | 		die "Build failed" | ||||||
|  | 	else | ||||||
|  | 		die "Build failed, check $copydir/build" | ||||||
|  | 	fi | ||||||
|  | else | ||||||
|  | 	true | ||||||
| fi | fi | ||||||
|   | |||||||
							
								
								
									
										176
									
								
								mkarchroot.in
									
									
									
									
									
								
							
							
						
						
									
										176
									
								
								mkarchroot.in
									
									
									
									
									
								
							| @@ -12,56 +12,33 @@ m4_include(lib/common.sh) | |||||||
|  |  | ||||||
| CHROOT_VERSION='v3' | CHROOT_VERSION='v3' | ||||||
|  |  | ||||||
| FORCE='n' |  | ||||||
| RUN='' |  | ||||||
| NOCOPY='n' |  | ||||||
|  |  | ||||||
| working_dir='' | working_dir='' | ||||||
|  |  | ||||||
| APPNAME=$(basename "${0}") |  | ||||||
|  |  | ||||||
| # usage: usage <exitvalue> |  | ||||||
| usage() { | usage() { | ||||||
| 	echo "Usage: ${APPNAME} [options] working-dir [package-list | app]" | 	echo "Usage: ${0##*/} [options] working-dir [package-list | app]" | ||||||
| 	echo ' options:' | 	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 '    -C <file>     Location of a pacman config file' | ||||||
| 	echo '    -M <file>     Location of a makepkg 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 '    -c <dir>      Set pacman cache' | ||||||
| 	echo '    -h            This message' | 	echo '    -h            This message' | ||||||
| 	exit 1 | 	exit 1 | ||||||
| } | } | ||||||
|  |  | ||||||
| while getopts 'r:ufnhC:M:c:' arg; do | while getopts 'hC:M:c:' arg; do | ||||||
| 	case "${arg}" in | 	case "$arg" in | ||||||
| 		r) RUN="$OPTARG" ;; |  | ||||||
| 		u) RUN='pacman -Syu --noconfirm' ;; |  | ||||||
| 		f) FORCE='y' ;; |  | ||||||
| 		C) pac_conf="$OPTARG" ;; | 		C) pac_conf="$OPTARG" ;; | ||||||
| 		M) makepkg_conf="$OPTARG" ;; | 		M) makepkg_conf="$OPTARG" ;; | ||||||
| 		n) NOCOPY='y' ;; |  | ||||||
| 		c) cache_dir="$OPTARG" ;; | 		c) cache_dir="$OPTARG" ;; | ||||||
| 		h|?) usage ;; | 		h|?) usage ;; | ||||||
| 		*) error "invalid argument '${arg}'"; usage ;; | 		*) error "invalid argument '$arg'"; usage ;; | ||||||
| 	esac | 	esac | ||||||
| done | done | ||||||
|  |  | ||||||
| if (( $EUID != 0 )); then |  | ||||||
| 	die 'This script must be run as root.' |  | ||||||
| fi |  | ||||||
|  |  | ||||||
| shift $(($OPTIND - 1)) | shift $(($OPTIND - 1)) | ||||||
|  |  | ||||||
| if [[ -z $RUN ]] && (( $# < 2 )); then | (( $EUID != 0 )) && die 'This script must be run as root.' | ||||||
| 	die 'You must specify a directory and one or more packages.' | (( $# < 2 )) && die 'You must specify a directory and one or more packages.' | ||||||
| elif (( $# < 1 )); then |  | ||||||
| 	die 'You must specify a directory.' |  | ||||||
| fi |  | ||||||
|  |  | ||||||
| working_dir="$(readlink -f ${1})" | working_dir="$(readlink -f $1)" | ||||||
| shift 1 | shift 1 | ||||||
|  |  | ||||||
| [[ -z $working_dir ]] && die 'Please specify a working directory.' | [[ -z $working_dir ]] && die 'Please specify a working directory.' | ||||||
| @@ -72,120 +49,31 @@ else | |||||||
| 	cache_dirs=(${cache_dir}) | 	cache_dirs=(${cache_dir}) | ||||||
| fi | 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 | umask 0022 | ||||||
| if [[ -n $RUN ]]; then |  | ||||||
| 	# run chroot {{{ | [[ -e $working_dir ]] && die "Working directory '$working_dir' already exists" | ||||||
| 	#Sanity check |  | ||||||
| 	if [[ ! -f "${working_dir}/.arch-chroot" ]]; then | mkdir -p "$working_dir" | ||||||
| 		die "'${working_dir}' does not appear to be a Arch chroot." |  | ||||||
| 	elif [[ $(cat "${working_dir}/.arch-chroot") != ${CHROOT_VERSION} ]]; then | lock 9 "${working_dir}.lock" "Locking chroot" | ||||||
| 		die "'${working_dir}' is not compatible with ${APPNAME} version ${CHROOT_VERSION}. Please rebuild." |  | ||||||
|  | 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 '$working_dir'" | ||||||
| 	fi | 	fi | ||||||
|  | 	chmod 0755 "$working_dir" | ||||||
| 	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" |  | ||||||
| 	# }}} |  | ||||||
| fi | 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) | m4_include(lib/valid-tags.sh) | ||||||
|  |  | ||||||
| @@ -11,6 +11,13 @@ _archco_args=( | |||||||
| 	'*:packages:_devtools_completions_all_packages' | 	'*: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=( | _archrelease_args=( | ||||||
| 	"*:arch:($_tags[*])" | 	"*:arch:($_tags[*])" | ||||||
| ) | ) | ||||||
| @@ -32,7 +39,6 @@ _finddeps_args=( | |||||||
| _makechrootpkg_args=( | _makechrootpkg_args=( | ||||||
| 	'-I[Install a package into the working copy]:target:_files -g "*.pkg.tar.*(.)"' | 	'-I[Install a package into the working copy]:target:_files -g "*.pkg.tar.*(.)"' | ||||||
| 	'-c[Clean the chroot before building]' | 	'-c[Clean the chroot before building]' | ||||||
| 	'-d[Add the package to a local db at /repo after building]' |  | ||||||
| 	'-h[Display usage]' | 	'-h[Display usage]' | ||||||
| 	'-l[The directory to use as the working copy]:copy_dir:_files -/' | 	'-l[The directory to use as the working copy]:copy_dir:_files -/' | ||||||
| 	'-r[The chroot dir to use]:chroot_dir:_files -/' | 	'-r[The chroot dir to use]:chroot_dir:_files -/' | ||||||
| @@ -40,12 +46,8 @@ _makechrootpkg_args=( | |||||||
| ) | ) | ||||||
|  |  | ||||||
| _mkarchroot_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' | 	'-C[Location of a pacman config file]:pacman_config:_files' | ||||||
| 	'-M[Location of a makepkg config file]:makepkg_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 -/' | 	'-c[Set pacman cache]:pacman_cache:_files -/' | ||||||
| 	'-h[Display usage]' | 	'-h[Display usage]' | ||||||
| ) | ) | ||||||
| @@ -62,7 +64,7 @@ _devtools_completions_all_packages() { | |||||||
| } | } | ||||||
|  |  | ||||||
| _devtools() { | _devtools() { | ||||||
| 	local argname="_${service}_args[@]" | 	local argname="_${service//-/_}_args[@]" | ||||||
| 	_arguments -s "${(P)argname}" | 	_arguments -s "${(P)argname}" | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user