aboutsummaryrefslogtreecommitdiff
path: root/src/cpt-lib.in
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpt-lib.in')
-rw-r--r--src/cpt-lib.in126
1 files changed, 71 insertions, 55 deletions
diff --git a/src/cpt-lib.in b/src/cpt-lib.in
index 5690ebe..8c7989e 100644
--- a/src/cpt-lib.in
+++ b/src/cpt-lib.in
@@ -479,6 +479,69 @@ sh256() {
while read -r hash _; do printf '%s %s\n' "$hash" "$1"; done
}
+tar_extract() {
+ # Tarball extraction function that prefers pax(1) over tar(1). The reason we
+ # are preferring pax is that we can strip components without relying on
+ # ugly hacks such as the ones we are doing for 'tar'. Using 'tar' means that
+ # we either have to sacrifice speed or portability, and we are choosing to
+ # sacrifice speed. Fortunately, we don't have to make such a choice when
+ # using pax.
+ case "${extract##*/}" in
+ pax) decompress "$1" | pax -r -s '/[^\/]*\///' ;;
+ gtar|bsdtar) decompress "$1" | "$tar" xf - --strip-components 1 ;;
+ tar) decompress "$1" > .ktar
+
+ "$tar" xf .ktar || return
+
+ # We now list the contents of the tarball so we can do our
+ # version of 'strip-components'.
+ "$tar" tf .ktar |
+ while read -r file; do printf '%s\n' "${file%%/*}"; done |
+
+ # Do not repeat files.
+ uniq |
+
+ # For every directory in the base we move each file
+ # inside it to the upper directory.
+ while read -r dir ; do
+
+ # Skip if we are not dealing with a directory here.
+ # This way we don't remove files on the upper directory
+ # if a tar archive doesn't need directory stripping.
+ [ -d "${dir#.}" ] || continue
+
+ # Change into the directory in a subshell so we don't
+ # need to cd back to the upper directory.
+ (
+ cd "$dir"
+
+ # We use find because we want to move hidden files
+ # as well.
+ #
+ # Skip the file if it has the same name as the directory.
+ # We will deal with it later.
+ #
+ # Word splitting is intentional here.
+ # shellcheck disable=2046
+ find . \( ! -name . -prune \) ! -name "$dir" \
+ -exec mv -f {} .. \;
+
+ # If a file/directory with the same name as the directory
+ # exists, append a '.cptbak' to it and move it to the
+ # upper directory.
+ ! [ -e "$dir" ] || mv "$dir" "../${dir}.cptbak"
+ )
+ rmdir "$dir"
+
+ # If a backup file exists, move it into the original location.
+ ! [ -e "${dir}.cptbak" ] || mv "${dir}.cptbak" "$dir"
+ done
+
+ # Clean up the temporary tarball.
+ rm -f .ktar
+ esac
+}
+
pkg_owner() {
set +f
@@ -697,63 +760,10 @@ pkg_extract() {
# extraction. Other filetypes are simply copied to '$mak_dir'
# which allows for manual extraction.
*://*.tar|*://*.tar.??|*://*.tar.???|*://*.tar.????|*://*.tgz|*://*.txz)
-
- decompress "$src_dir/$1/${src##*/}" > .ktar
-
- "$tar" xf .ktar || die "$1" "Couldn't extract ${src##*/}"
-
- # We now list the contents of the tarball so we can do our
- # version of 'strip-components'.
- "$tar" tf .ktar |
- while read -r file; do printf '%s\n' "${file%%/*}"; done |
-
- # Do not repeat files.
- uniq |
-
- # For every directory in the base we move each file
- # inside it to the upper directory.
- while read -r dir ; do
-
- # Skip if we are not dealing with a directory here.
- # This way we don't remove files on the upper directory
- # if a tar archive doesn't need directory stripping.
- [ -d "${dir#.}" ] || continue
-
- # Change into the directory in a subshell so we don't
- # need to cd back to the upper directory.
- (
- cd "$dir"
-
- # We use find because we want to move hidden files
- # as well.
- #
- # Skip the file if it has the same name as the directory.
- # We will deal with it later.
- #
- # Word splitting is intentional here.
- # shellcheck disable=2046
- find . \( ! -name . -prune \) ! -name "$dir" \
- -exec mv -f {} .. \;
-
- # If a file/directory with the same name as the directory
- # exists, append a '.cptbak' to it and move it to the
- # upper directory.
- ! [ -e "$dir" ] || mv "$dir" "../${dir}.cptbak"
- )
- rmdir "$dir"
-
- # If a backup file exists, move it into the original location.
- ! [ -e "${dir}.cptbak" ] || mv "${dir}.cptbak" "$dir"
- done
-
- # Clean up the temporary tarball.
- rm -f .ktar
- ;;
+ tar_extract "$src_dir/$1/${src##*/}" ;;
*://*.cpio|*://*.cpio.??|*://*.cpio.???|*://*.cpio.????)
- decompress "$src_dir/$1/${src##*/}" | cpio -i
-
- ;;
+ decompress "$src_dir/$1/${src##*/}" | pax -r ;;
*://*.zip)
unzip "$src_dir/$1/${src##*/}" ||
@@ -1961,6 +1971,12 @@ create_cache() {
# you value performance.
tar=$(command -v bsdtar || command -v gtar) || tar=tar
+ # Prefer libarchive tar, GNU tar, or the POSIX defined pax for tarball
+ # extraction, as they can strip components, which is much much faster than
+ # our portability function. Our first preference is pax, because it is
+ # actually slightly faster than bsdtar and GNU tar.
+ extract=$(command -v pax || command -v "$tar")
+
# Figure out which 'sudo' command to use based on the user's choice or
# what is available on the system.
su=${CPT_SU:-$(command -v sls ||