In the original multibuild.eclass code I tried to somehow achieve very
fast merging via avoiding actually copying anything. I used the 'cp -al'
call that used hardlinks to avoid copying data but that actually made
copying non-clobbering and less portable (BSD used a tar fallback, for
example, due to some bugs at the time).

While the original solution worked and was quite good for its initial
use, the fact that it is non-clobbering is a bit confusing and resulted
in late breakage in llvm ebuild (where I assumed it will clobber). I
think it's time to replace it with something simpler, more portable (no
more userland checks) and fully clobbering.

For this reason, the patch replaces the old code with a plain 'cp -a'
or 'cp -PpR' that should be POSIX-compliant. It also tries to use
'--reflink=auto' if available to make use of btrfs CoW support.

I'd appreciate very much of someone could put the code into thorough
testing. The consumers include all distutils-r1 ebuilds, multilib
ebuilds, PyQt4 and the reverted version of llvm :).
---
 eclass/multibuild.eclass | 28 +++++++++++++---------------
 1 file changed, 13 insertions(+), 15 deletions(-)

diff --git a/eclass/multibuild.eclass b/eclass/multibuild.eclass
index 0a2771e..be3ecf3 100644
--- a/eclass/multibuild.eclass
+++ b/eclass/multibuild.eclass
@@ -265,24 +265,22 @@ multibuild_merge_root() {
        done
        rm "${lockfile_l}" || die
 
-       if use userland_BSD; then
-               # 'cp -a -n' is broken:
-               # http://www.freebsd.org/cgi/query-pr.cgi?pr=174489
-               # using tar instead which is universal but terribly slow.
-
-               tar -C "${src}" -f - -c . \
-                       | tar -x -f - -C "${dest}"
-               [[ ${PIPESTATUS[*]} == '0 0' ]]
-               ret=${?}
-       elif use userland_GNU; then
-               # cp works with '-a -n'.
-
-               cp -a -l -n "${src}"/. "${dest}"/
-               ret=${?}
+       local cp_args=()
+
+       if cp -a --version &>/dev/null; then
+               cp_args+=( -a )
        else
-               die "Unsupported userland (${USERLAND}), please report."
+               cp_args+=( -P -R -p )
+       fi
+
+       if cp --reflink=auto --version &>/dev/null; then
+               # enable reflinking if possible to make this faster
+               cp_args+=( --reflink=auto )
        fi
 
+       cp "${cp_args[@]}" "${src}"/. "${dest}"/
+       ret=${?}
+
        # Remove the lock.
        rm "${lockfile}" || die
 
-- 
1.9.1


Reply via email to