From b710a249b2ce71faf98ec8d2855e005871759e0d Mon Sep 17 00:00:00 2001 From: Fabian Groffen Date: Sat, 13 Oct 2007 12:26:58 +0000 Subject: [PATCH] Use the new chpathtool. If we install on a system with a different prefix, unpack in the workdir, instead of the image dir. We "copy" from the workdir to the image using chpathtool, which behaves as a cp -a. chpathtool was changed to copy file by file, changing paths it finds in files to overcome the following problem. chpathtool was used in a piped fashion, like this: bzip2 -d file | chpathtool | tar -x in this way, chpathtool operated on the raw tar-stream, changing paths it saw over the stream. This has the following advantages: - not only rpaths, library locations, or hardcoded paths to conf files were changed, but also the location of the files in the filesystem themselves, as chpathtool also changed the tar envelope - just one run over the stream, simple, easy and cheap from an fork/exec perspective - no need to deal with file attributes, creation modes, etc, tar dealt with that, chpathtool only changed paths where appropriate However, when doing the path changements, chpathtool inserts padding bytes at the end of each string it sees, in order not to break offsets stored in e.g. programs to point in the TEXT or DATA spaces. Because text files are in the tar stream, chpathtool sees the end of string at the end of such text file, and inserts the padding null-bytes there. However, tar still has an administration for each file of its size, so as result, tar writes the padding null-bytes to the text files. In most cases this doesn't hurt, however, some applications, such as GHC get confused by it, because EOF isn't found, but null-bytes don't make sense for them. The only way to fix this, without interpreting the tar envelope, is to use chpathtool per file. chpathtool doesn't write padding bytes if it doesn't find an end of string, which in textfiles doesn't exist (instead you get the EOF). Running find -exec, or with xargs results in a serious performance problem due to numerous fork/exec calls. Instead, chpathtool was changed to recursively walk directories, and process all what is in there. Because chpathtool operates on files in this case, it needs to properly behave, such that it doesn't change the properties of each file it replicates. For this reason, chpathtool's implementation grew twice its original size in order to retain the original file's permissions, owners, and times. svn path=/main/branches/prefix/; revision=8105 --- pym/portage/__init__.py | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/pym/portage/__init__.py b/pym/portage/__init__.py index 9bda7bd6a..d0593e47b 100644 --- a/pym/portage/__init__.py +++ b/pym/portage/__init__.py @@ -5347,7 +5347,11 @@ def pkgmerge(mytbz2, myroot, mysettings, mydbapi=None, vartree=None, prev_mtimes builddir = os.path.join( mysettings["PORTAGE_TMPDIR"], "portage", mycat, mypkg) catdir = os.path.dirname(builddir) - pkgloc = os.path.join(builddir, "image") + # if the prefix differs, we copy it to the image after extraction + if (buildprefix != EPREFIX): + pkgloc = os.path.join(builddir, "work") + else + pkgloc = os.path.join(builddir, "image") infloc = os.path.join(builddir, "build-info") myebuild = os.path.join( infloc, os.path.basename(mytbz2)[:-4] + "ebuild") @@ -5392,7 +5396,7 @@ def pkgmerge(mytbz2, myroot, mysettings, mydbapi=None, vartree=None, prev_mtimes writemsg_stdout(">>> Extracting %s\n" % mypkg) retval = portage.process.spawn_bash( - "bzip2 -dqc -- '%s' | chpathtool - - '%s' '%s' | tar -xp -C '%s' -f -" % (mytbz2, buildprefix, EPREFIX, pkgloc), + "bzip2 -dqc -- '%s' | tar -xp -C '%s' -f -" % (mytbz2, pkgloc), env=mysettings.environ()) if retval != os.EX_OK: writemsg("!!! Error Extracting '%s'\n" % mytbz2, noiselevel=-1) @@ -5403,16 +5407,20 @@ def pkgmerge(mytbz2, myroot, mysettings, mydbapi=None, vartree=None, prev_mtimes # the extracted package put everything in buildprefix, so we # just have to move it to the right EPREFIX if buildprefix != EPREFIX: - try: - shutil.copytree(os.path.join(pkgloc, - buildprefix.lstrip(os.path.sep)), os.path.join(pkgloc, - EPREFIX_LSTRIP), symlinks=True) - except OSError: - if not os.path.exists(os.path.join(pkgloc, EPREFIX_LSTRIP)): - writemsg("!!! Package was was built in a wrong way, " + - "please rebuild the package with a recent " + - "Portage\n", noiselevel=-1) - return os.EX_OSERR + writemsg_stdout(">>> Adjusting Prefix to %s\n" % EPREFIX) + b = os.path.join(pkgloc, buildprefix.lstrip(os.path.sep)) + i = os.path.join(builddir, "image", EPREFIX_LSTRIP) + # make sure the directory structure for EPREFIX is set up in + # the image, but avoid the last directory being there, + # otherwise chpathtool will complain + portage.util.ensure_dirs(i) + os.rmdir(i) + retval = portage.process.spawn_bash( + "chpathtool '%s' '%s' '%s' '%s'" % (b, i, buildprefix, EPREFIX), + env=mysettings.environ()) + if retval != os.EX_OK: + writemsg("!!! Adjusing to Prefix failed!\n", noiselevel=-1) + return retval mylink = dblink(mycat, mypkg, myroot, mysettings, vartree=vartree, treetype="bintree") -- 2.26.2