diff --git a/please.sh b/please.sh index 8d7807505b..a0543b8acd 100755 --- a/please.sh +++ b/please.sh @@ -3333,7 +3333,7 @@ create_sdk_artifact () { # [--out=] [--git-sdk=] [--bitnes case "$1" in minimal|git-sdk-minimal) mode=minimal-sdk;; full) mode=full-sdk;; - minimal-sdk|makepkg-git|build-installers|full-sdk) mode=$1;; + minimal-sdk|makepkg-git|build-installers|pacman|pacman-full|full-sdk) mode=$1;; *) die "Unhandled artifact: '%s'\n" "$1";; esac @@ -3489,6 +3489,100 @@ create_sdk_artifact () { # [--out=] [--git-sdk=] [--bitnes mkdir -p "$output_path/.sparse" && cp "$sparse_checkout_file" "$output_path/.sparse/build-installers" ;; + pacman|pacman-full) + # In partial clones, preemptively fetch /var/lib/pacman/local/* + if test true = "$(git -C "$git_sdk_path" config remote.origin.promisor)" + then + # "abuse" the fact that `diff --numstat` prefetches the objects + git -C "$git_sdk_path" diff --quiet --numstat \ + HEAD:usr/share/makepkg HEAD:var/lib/pacman/local || + test $? = 1 # we expect the trees to differ + fi && + + sparse_checkout_exclude= && + pkgs_exclude= + if test pacman-full != "$mode" + then + # skip documentation + sparse_checkout_exclude='/usr/share/\(doc\|gtc-doc\|info\|man\)/' + # skip headers, terminfo and locales + sparse_checkout_exclude="$sparse_checkout_exclude\|/\(include\|terminfo\|locale\)/" + # skip C++/Fortran libraries (unused) + sparse_checkout_exclude="$sparse_checkout_exclude\|/msys-\(gmpxx\|gnutlsxx\|ncurses++\|stdc++\|gfortran\)[^/]*$" + # skip Cygwin's core dumper (unused) + sparse_checkout_exclude="$sparse_checkout_exclude\|^/usr/bin/dumper\.exe$" + pkgs_exclude='info tcl libasprintf' + fi && + + pkg_map=" $(git -C "$git_sdk_path" ls-tree HEAD:var/lib/pacman/local | + sed -n 's/^.* \([0-9a-f]*\)\t\(.*\)/\2:\1/p' | + # remove the package version + sed 's/-[0-9][^:]*//g' | + tr '\n' ' ')" && + pkg_tree_oid () { + tree="${pkg_map##* $1:}" && + test "z$tree" != "z$pkg_map" && + tree=${tree%% *} && + test -n "$tree" && + echo "$tree" || + die "Could not get tree for $1" + } && + pkg_blob_oid () { + git -C "$git_sdk_path" rev-parse --verify "$(pkg_tree_oid "$1")":$2 || + die "Could not get oid for $1:$2" + } && + pkg_files () { + git -C "$git_sdk_path" cat-file blob "$(pkg_blob_oid "$1" files)" | + sed -n '/^%FILES%$/,/^$/{/^%FILES%$/d;/^$/d;/\/$/d;p}' + } && + pkg_deps () { + git -C "$git_sdk_path" cat-file blob "$(pkg_blob_oid "$1" desc)" | + sed -n '/^%DEPENDS%$/,/^$/{/^%DEPENDS%$/d;/^$/d;s/[>=].*//;p}' + } && + pkgs_deps () { + deps_tree=' ' + args_remaining="$* " + while test -n "$args_remaining" + do + arg="${args_remaining%% *}" + args_remaining="${args_remaining#$arg }" + case " $pkgs_exclude " in *" $arg "*) continue;; esac + test sh != "$arg" || arg=bash + case " $deps_tree" in *" $arg "*) continue;; esac # already handled + deps_tree="$deps_tree$arg " + for dep in $(pkg_deps $arg) + do + case " $deps_tree" in *" $dep "*) continue;; esac # already handled + args_remaining="$args_remaining$dep " + done + done && + echo "${deps_tree% }" + } && + pkgs_sparse_checkout () { + printf '# Sparse checkout file for %s\n\n%s\n%s\n%s\n%s\n' "$*" \ + '# Pacman local state' \ + '/etc/pacman.d/gnupg/' \ + '/var/lib/pacman/local/ALPM_DB_VERSION' \ + '/var/lib/pacman/sync/' && + echo "Generating dependency tree for $*" >&2 && + for pkg in $(pkgs_deps "$@") + do + printf '\n# %s\n/var/lib/pacman/local/%s-[0-9]*/\n' "$pkg" "$pkg" + echo "Generating file list for $pkg" >&2 + files="$(pkg_files $pkg)" && + echo "$files" | sed 's/^/\//' | + grep -v "${sparse_checkout_exclude:-.^}" || + die "Could not enumerate files for $pkg" + done + } && + pkgs_sparse_checkout pacman bsdtar msys2-runtime >"$sparse_checkout_file" && + + mkdir -p "$output_path/tmp" && + mkdir -p "$output_path/etc" && + printf 'export MSYSTEM=MINGW%s\nexport PATH=/mingw%s/bin:/usr/bin/:/c/WINDOWS/system32:/c/WINDOWS:/c/WINDOWS/System32/Wbem\n' "$bitness" "$bitness" >"$output_path/etc/profile" && + mkdir -p "$output_path/.sparse" && + cp "$sparse_checkout_file" "$output_path/.sparse/build-installers" + ;; *) git -C "$git_sdk_path" show HEAD:.sparse/minimal-sdk >"$sparse_checkout_file" && if test makepkg-git = $mode