7a95120a98ba0eec3854a67b68f1f8e077ef6e3d
[portage.git] / bin / ebuild-helpers / ecompressdir
1 #!/bin/bash
2 # Copyright 1999-2010 Gentoo Foundation
3 # Distributed under the terms of the GNU General Public License v2
4
5 source "${PORTAGE_BIN_PATH:-/usr/lib/portage/bin}"/isolated-functions.sh
6
7 if [[ -z $1 ]] ; then
8         helpers_die "${0##*/}: at least one argument needed"
9         exit 1
10 fi
11
12 case $1 in
13         --ignore)
14                 shift
15                 for skip in "$@" ; do
16                         [[ -d ${D}${skip} || -f ${D}${skip} ]] \
17                                 && >> "${D}${skip}.ecompress.skip"
18                 done
19                 exit 0
20                 ;;
21         --queue)
22                 shift
23                 set -- "${@/%/.ecompress.dir}"
24                 set -- "${@/#/${D}}"
25                 ret=0
26                 for x in "$@" ; do
27                         >> "$x"
28                         ((ret|=$?))
29                 done
30                 [[ $ret -ne 0 ]] && helpers_die "${0##*/} failed"
31                 exit $ret
32                 ;;
33         --dequeue)
34                 [[ -n $2 ]] && vecho "${0##*/}: --dequeue takes no additional arguments" 1>&2
35                 find "${D}" -name '*.ecompress.dir' -print0 \
36                         | sed -e 's:\.ecompress\.dir::g' -e "s:${D}:/:g" \
37                         | ${XARGS} -0 ecompressdir
38                 find "${D}" -name '*.ecompress.skip' -print0 | ${XARGS} -0 rm -f
39                 exit 0
40                 ;;
41         --*)
42                 helpers_die "${0##*/}: unknown arguments '$*'"
43                 exit 1
44                 ;;
45 esac
46
47 # figure out the new suffix
48 suffix=$(ecompress --suffix)
49
50 # funk_up_dir(action, suffix, binary)
51 #       - action: compress or decompress
52 #       - suffix: the compression suffix to work with
53 #       - binary: the program to execute that'll compress/decompress
54 # The directory we act on is implied in the ${dir} variable
55 funk_up_dir() {
56         local act=$1 suffix=$2 binary=$3
57
58         local negate=""
59         [[ ${act} == "compress" ]] && negate="!"
60
61         # first we act on all the files
62         find "${dir}" -type f ${negate} -iname '*'${suffix} -print0 | ${XARGS} -0 ${binary}
63         ((ret|=$?))
64
65         find "${dir}" -type l -print0 | \
66         while read -r -d $'\0' brokenlink ; do
67                 [[ -e ${brokenlink} ]] && continue
68                 olddest=$(readlink "${brokenlink}")
69                 [[ ${act} == "compress" ]] \
70                         && newdest="${olddest}${suffix}" \
71                         || newdest="${olddest%${suffix}}"
72                 rm -f "${brokenlink}"
73                 [[ ${act} == "compress" ]] \
74                         && ln -snf "${newdest}" "${brokenlink}${suffix}" \
75                         || ln -snf "${newdest}" "${brokenlink%${suffix}}"
76                 ((ret|=$?))
77         done
78 }
79
80 # _relocate_skip_dirs(srctree, dsttree)
81 # Move all files and directories we want to skip running compression
82 # on from srctree to dsttree.
83 _relocate_skip_dirs() {
84         local srctree="$1" dsttree="$2"
85
86         [[ -d ${srctree} ]] || return 0
87
88         find "${srctree}" -name '*.ecompress.skip' -print0 | \
89         while read -r -d $'\0' src ; do
90                 src=${src%.ecompress.skip}
91                 dst="${dsttree}${src#${srctree}}"
92                 parent=${dst%/*}
93                 mkdir -p "${parent}"
94                 mv "${src}" "${dst}"
95                 mv "${src}.ecompress.skip" "${dst}.ecompress.skip"
96         done
97 }
98 hide_skip_dirs()    { _relocate_skip_dirs "${D}" "${T}"/ecompress-skip/ ; }
99 restore_skip_dirs() { _relocate_skip_dirs "${T}"/ecompress-skip/ "${D}" ; }
100
101 ret=0
102
103 rm -rf "${T}"/ecompress-skip
104
105 for dir in "$@" ; do
106         dir=${dir#/}
107         dir="${D}${dir}"
108         if [[ ! -d ${dir} ]] ; then
109                 vecho "${0##*/}: /${dir#${D}} does not exist!"
110                 continue
111         fi
112         cd "${dir}"
113         actual_dir=${dir}
114         dir=. # use relative path to avoid 'Argument list too long' errors
115
116         # hide all the stuff we want to skip
117         hide_skip_dirs "${dir}"
118
119         # since we've been requested to compress the whole dir,
120         # delete any individual queued requests
121         rm -f "${actual_dir}.ecompress.dir"
122         find "${dir}" -type f -name '*.ecompress.file' -print0 | ${XARGS} -0 rm -f
123
124         # not uncommon for packages to compress doc files themselves
125         funk_up_dir "decompress" ".Z" "gunzip -f"
126         funk_up_dir "decompress" ".gz" "gunzip -f"
127         funk_up_dir "decompress" ".bz2" "bunzip2 -f"
128
129         # forcibly break all hard links as some compressors whine about it
130         find "${dir}" -type f -links +1 -exec env file="{}" sh -c \
131                 'cp -p "${file}" "${file}.ecompress.break" ; mv -f "${file}.ecompress.break" "${file}"' \;
132
133         # now lets do our work
134         [[ -z ${suffix} ]] && continue
135         vecho "${0##*/}: $(ecompress --bin) /${actual_dir#${D}}"
136         funk_up_dir "compress" "${suffix}" "ecompress"
137
138         # finally, restore the skipped stuff
139         restore_skip_dirs
140 done
141
142 [[ $ret -ne 0 ]] && helpers_die "${0##*/} failed"
143 exit ${ret}