c3af28905921f79bf074a77a548480e289a92f3f
[portage.git] / bin / ebuild-helpers / doins
1 #!/bin/bash
2 # Copyright 1999-2011 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 [[ ${0##*/} == dodoc ]] ; then
8         if [ $# -eq 0 ] ; then
9                 # default_src_install may call dodoc with no arguments
10                 # when DOC is defined but empty, so simply return
11                 # sucessfully in this case.
12                 exit 0
13         fi
14         export INSOPTIONS=-m0644
15         export INSDESTTREE=usr/share/doc/${PF}/${_E_DOCDESTTREE_}
16 fi
17
18 if [ $# -lt 1 ] ; then
19         helpers_die "${0##*/}: at least one argument needed"
20         exit 1
21 fi
22
23 if [[ "$1" == "-r" ]] ; then
24         DOINSRECUR=y
25         shift
26 else
27         DOINSRECUR=n
28 fi
29
30 [[ " ${USE} " == *" prefix "* ]] || \
31         case "$EAPI" in 0|1|2) export ED="${D}" ;; esac
32
33 if [[ ${INSDESTTREE#${ED}} != "${INSDESTTREE}" ]]; then
34         vecho "-------------------------------------------------------" 1>&2
35         vecho "You should not use \${D} or \${ED} with helpers." 1>&2
36         vecho "  --> ${INSDESTTREE}" 1>&2
37         vecho "-------------------------------------------------------" 1>&2
38         helpers_die "${0##*/} used with \${D} or \${ED}"
39         exit 1
40 fi
41
42 case "$EAPI" in
43         0|1|2|3|3_pre2)
44                 PRESERVE_SYMLINKS=n
45                 ;;
46         *)
47                 PRESERVE_SYMLINKS=y
48                 ;;
49 esac
50
51 export TMP=$T/.doins_tmp
52 # Use separate directories to avoid potential name collisions.
53 mkdir -p "$TMP"/{1,2}
54
55 [[ ! -d ${ED}${INSDESTTREE} ]] && dodir "${INSDESTTREE}"
56
57 _doins() {
58         local mysrc="$1" mydir="$2" cleanup="" rval
59
60         if [ -L "$mysrc" ] ; then
61                 # Our fake $DISTDIR contains symlinks that should
62                 # not be reproduced inside $D. In order to ensure
63                 # that things like dodoc "$DISTDIR"/foo.pdf work
64                 # as expected, we dereference symlinked files that
65                 # refer to absolute paths inside
66                 # $PORTAGE_ACTUAL_DISTDIR/.
67                 if [ $PRESERVE_SYMLINKS = y ] && \
68                         ! [[ $(readlink "$mysrc") == "$PORTAGE_ACTUAL_DISTDIR"/* ]] ; then
69                         rm -rf "${ED}$INSDESTTREE/$mydir/${mysrc##*/}" || return $?
70                         cp -P "$mysrc" "${ED}$INSDESTTREE/$mydir/${mysrc##*/}"
71                         return $?
72                 else
73                         cp "$mysrc" "$TMP/2/${mysrc##*/}" || return $?
74                         mysrc="$TMP/2/${mysrc##*/}"
75                         cleanup=$mysrc
76                 fi
77         fi
78
79         install ${INSOPTIONS} "${mysrc}" "${ED}${INSDESTTREE}/${mydir}"
80         rval=$?
81         [[ -n ${cleanup} ]] && rm -f "${cleanup}"
82         [ $rval -ne 0 ] && echo "!!! ${0##*/}: $mysrc does not exist" 1>&2
83         return $rval
84 }
85
86 _xdoins() {
87         local -i failed=0
88         while read -r -d $'\0' x ; do
89                 _doins "$x" "${x%/*}"
90                 ((failed|=$?))
91         done
92         return $failed
93 }
94
95 success=0
96 failed=0
97
98 for x in "$@" ; do
99         if [[ $PRESERVE_SYMLINKS = n && -d $x ]] || \
100                 [[ $PRESERVE_SYMLINKS = y && -d $x && ! -L $x ]] ; then
101                 if [ "${DOINSRECUR}" == "n" ] ; then
102                         if [[ ${0##*/} == dodoc ]] ; then
103                                 echo "!!! ${0##*/}: $x is a directory" 1>&2
104                                 ((failed|=1))
105                         fi
106                         continue
107                 fi
108
109                 while [ "$x" != "${x%/}" ] ; do
110                         x=${x%/}
111                 done
112                 if [ "$x" = "${x%/*}" ] ; then
113                         pushd "$PWD" >/dev/null
114                 else
115                         pushd "${x%/*}" >/dev/null
116                 fi
117                 x=${x##*/}
118                 x_orig=$x
119                 # Follow any symlinks recursively until we've got
120                 # a normal directory for 'find' to traverse. The
121                 # name of the symlink will be used for the name
122                 # of the installed directory, as discussed in
123                 # bug #239529.
124                 while [ -L "$x" ] ; do
125                         pushd "$(readlink "$x")" >/dev/null
126                         x=${PWD##*/}
127                         pushd "${PWD%/*}" >/dev/null
128                 done
129                 if [[ $x != $x_orig ]] ; then
130                         mv "$x" "$TMP/1/$x_orig"
131                         pushd "$TMP/1" >/dev/null
132                 fi
133                 find "$x_orig" -type d -exec dodir "${INSDESTTREE}/{}" \;
134                 find "$x_orig" \( -type f -or -type l \) -print0 | _xdoins
135                 if [[ ${PIPESTATUS[1]} -eq 0 ]] ; then
136                         # NOTE: Even if only an empty directory is installed here, it
137                         # still counts as success, since an empty directory given as
138                         # an argument to doins -r should not trigger failure.
139                         ((success|=1))
140                 else
141                         ((failed|=1))
142                 fi
143                 if [[ $x != $x_orig ]] ; then
144                         popd >/dev/null
145                         mv "$TMP/1/$x_orig" "$x"
146                 fi
147                 while popd >/dev/null 2>&1 ; do true ; done
148         else
149                 _doins "${x}"
150                 if [[ $? -eq 0 ]] ; then
151                         ((success|=1))
152                 else
153                         ((failed|=1))
154                 fi
155         fi
156 done
157 rm -rf "$TMP"
158 [[ $failed -ne 0 || $success -eq 0 ]] && { helpers_die "${0##*/} failed"; exit 1; } || exit 0