public inbox for gentoo-portage-dev@lists.gentoo.org
 help / color / mirror / Atom feed
From: "Michał Górny" <mgorny@gentoo.org>
To: gentoo-portage-dev@lists.gentoo.org
Cc: "Michał Górny" <mgorny@gentoo.org>
Subject: [gentoo-portage-dev] [PATCH 2/3] portage.dbapi.vartree: Move INSTALL_MASK handling into merging
Date: Thu, 15 Mar 2018 20:22:10 +0100	[thread overview]
Message-ID: <20180315192212.13454-3-mgorny@gentoo.org> (raw)
In-Reply-To: <20180315192212.13454-1-mgorny@gentoo.org>

Introduce a new logic for INSTALL_MASK handling in merging code,
replacing the old code that removed matching files and directories
from imagedir in bash. The new code actually ignores matching files
on-the-fly while testing for file collisions and merging files.
The files are still written to CONTENTS, and output using "###" zing
to indicate being masked, yet are not actually merged to the filesystem.
---
 bin/misc-functions.sh                |  17 ------
 pym/portage/dbapi/vartree.py         | 102 ++++++++++++++++++++++-------------
 pym/portage/package/ebuild/config.py |   3 +-
 3 files changed, 66 insertions(+), 56 deletions(-)

diff --git a/bin/misc-functions.sh b/bin/misc-functions.sh
index 6a5c2ea05..59391816b 100755
--- a/bin/misc-functions.sh
+++ b/bin/misc-functions.sh
@@ -361,23 +361,6 @@ install_mask() {
 	set -${shopts}
 }
 
-preinst_mask() {
-	if [ -z "${D}" ]; then
-		 eerror "${FUNCNAME}: D is unset"
-		 return 1
-	fi
-
-	if ! ___eapi_has_prefix_variables; then
-		local ED=${D}
-	fi
-
-	# Make sure $PWD is not ${D} so that we don't leave gmon.out files
-	# in there in case any tools were built with -pg in CFLAGS.
-	cd "${T}"
-
-	install_mask "${ED}" "${INSTALL_MASK}"
-}
-
 preinst_sfperms() {
 	if [ -z "${D}" ]; then
 		 eerror "${FUNCNAME}: D is unset"
diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py
index 8b1b77f7d..21904edca 100644
--- a/pym/portage/dbapi/vartree.py
+++ b/pym/portage/dbapi/vartree.py
@@ -2491,7 +2491,7 @@ class dblink(object):
 								(statobj.st_dev, statobj.st_ino),
 								[]).append(relative_path)
 
-					if is_owned:
+					if is_owned and not self._is_install_masked(relative_path[1:]):
 						show_unmerge("---", unmerge_desc["replaced"], file_type, obj)
 						continue
 					elif relative_path in cfgfiledict:
@@ -3689,6 +3689,24 @@ class dblink(object):
 	def _emerge_log(self, msg):
 		emergelog(False, msg)
 
+	def _is_install_masked(self, relative_path):
+		ret = False
+		for pattern in self.settings.install_mask:
+			# absolute path pattern
+			if pattern.startswith('/'):
+				# match either exact path or one of parent dirs
+				# the latter is done via matching pattern/*
+				if (fnmatch.fnmatch(relative_path, pattern[1:])
+						or fnmatch.fnmatch(relative_path, pattern[1:] + '/*')):
+					ret = True
+					break
+			# filename
+			else:
+				if fnmatch.fnmatch(os.path.basename(relative_path), pattern):
+					ret = True
+					break
+		return ret
+
 	def treewalk(self, srcroot, destroot, inforoot, myebuild, cleanup=0,
 		mydbapi=None, prev_mtimes=None, counter=None):
 		"""
@@ -3848,16 +3866,6 @@ class dblink(object):
 					max_dblnk = dblnk
 			self._installed_instance = max_dblnk
 
-		# Apply INSTALL_MASK before collision-protect, since it may
-		# be useful to avoid collisions in some scenarios.
-		# We cannot detect if this is needed or not here as INSTALL_MASK can be
-		# modified by bashrc files.
-		phase = MiscFunctionsProcess(background=False,
-			commands=["preinst_mask"], phase="preinst",
-			scheduler=self._scheduler, settings=self.settings)
-		phase.start()
-		phase.wait()
-
 		# We check for unicode encoding issues after src_install. However,
 		# the check must be repeated here for binary packages (it's
 		# inexpensive since we call os.walk() here anyway).
@@ -3929,6 +3937,10 @@ class dblink(object):
 
 					relative_path = fpath[srcroot_len:]
 
+					# filter on INSTALL_MASK
+					if self._is_install_masked(relative_path):
+						continue
+
 					if line_ending_re.search(relative_path) is not None:
 						paths_with_newlines.append(relative_path)
 
@@ -4658,6 +4670,7 @@ class dblink(object):
 		while mergelist:
 
 			relative_path = mergelist.pop()
+			instmasked = self._is_install_masked(relative_path)
 			mysrc = join(srcroot, relative_path)
 			mydest = join(destroot, relative_path)
 			# myrealdest is mydest without the $ROOT prefix (makes a difference if ROOT!="/")
@@ -4744,7 +4757,7 @@ class dblink(object):
 				destmd5 = None
 
 			moveme = True
-			if protected:
+			if protected and not instmasked:
 				mydest, protected, moveme = self._protect(cfgfiledict,
 					protect_if_modified, mymd5, myto, mydest,
 					myrealdest, mydmode, destmd5, mydest_link)
@@ -4772,7 +4785,7 @@ class dblink(object):
 				# we can simply test for existence of this file to see if the target has been merged yet
 				myrealto = normalize_path(os.path.join(destroot, myabsto))
 				if mydmode is not None and stat.S_ISDIR(mydmode):
-					if not protected:
+					if not protected and not instmasked:
 						# we can't merge a symlink over a directory
 						newdest = self._new_backup_path(mydest)
 						msg = []
@@ -4792,26 +4805,32 @@ class dblink(object):
 					# it later.
 					secondhand.append(mysrc[len(srcroot):])
 					continue
-				# unlinking no longer necessary; "movefile" will overwrite symlinks atomically and correctly
-				if moveme:
-					zing = ">>>"
-					mymtime = movefile(mysrc, mydest, newmtime=thismtime,
-						sstat=mystat, mysettings=self.settings,
-						encoding=_encodings['merge'])
 
-				try:
-					self._merged_path(mydest, os.lstat(mydest))
-				except OSError:
-					pass
+				if instmasked:
+					zing = "###"
+					# pass mymtime through from initial stat
+				else:
+					# unlinking no longer necessary; "movefile" will overwrite symlinks atomically and correctly
+					if moveme:
+						zing = ">>>"
+						mymtime = movefile(mysrc, mydest, newmtime=thismtime,
+							sstat=mystat, mysettings=self.settings,
+							encoding=_encodings['merge'])
+
+					try:
+						self._merged_path(mydest, os.lstat(mydest))
+					except OSError:
+						pass
 
 				if mymtime != None:
-					# Use lexists, since if the target happens to be a broken
-					# symlink then that should trigger an independent warning.
-					if not (os.path.lexists(myrealto) or
-						os.path.lexists(join(srcroot, myabsto))):
-						self._eqawarn('preinst',
-							[_("QA Notice: Symbolic link /%s points to /%s which does not exist.")
-							% (relative_path, myabsto)])
+					if not instmasked:
+						# Use lexists, since if the target happens to be a broken
+						# symlink then that should trigger an independent warning.
+						if not (os.path.lexists(myrealto) or
+							os.path.lexists(join(srcroot, myabsto))):
+							self._eqawarn('preinst',
+								[_("QA Notice: Symbolic link /%s points to /%s which does not exist.")
+								% (relative_path, myabsto)])
 
 					showMessage("%s %s -> %s\n" % (zing, mydest, myto))
 					if sys.hexversion >= 0x3030000:
@@ -4826,7 +4845,9 @@ class dblink(object):
 					return 1
 			elif stat.S_ISDIR(mymode):
 				# we are merging a directory
-				if mydmode != None:
+				if instmasked:
+					showMessage("### %s/\n" % mydest)
+				elif mydmode != None:
 					# destination exists
 
 					if bsd_chflags:
@@ -4913,10 +4934,11 @@ class dblink(object):
 					os.chown(mydest, mystat[4], mystat[5])
 					showMessage(">>> %s/\n" % mydest)
 
-				try:
-					self._merged_path(mydest, os.lstat(mydest))
-				except OSError:
-					pass
+				if not instmasked:
+					try:
+						self._merged_path(mydest, os.lstat(mydest))
+					except OSError:
+						pass
 
 				outfile.write("dir "+myrealdest+"\n")
 				# recurse and merge this directory
@@ -4925,7 +4947,7 @@ class dblink(object):
 
 			elif stat.S_ISREG(mymode):
 				# we are merging a regular file
-				if not protected and \
+				if not protected and not instmasked and \
 					mydmode is not None and stat.S_ISDIR(mydmode):
 						# install of destination is blocked by an existing directory with the same name
 						newdest = self._new_backup_path(mydest)
@@ -4939,9 +4961,11 @@ class dblink(object):
 						self._eerror("preinst", msg)
 						mydest = newdest
 
+				if instmasked:
+					zing = "###"
 				# whether config protection or not, we merge the new file the
 				# same way.  Unless moveme=0 (blocking directory)
-				if moveme:
+				elif moveme:
 					# Create hardlinks only for source files that already exist
 					# as hardlinks (having identical st_dev and st_ino).
 					hardlink_key = (mystat.st_dev, mystat.st_ino)
@@ -4974,7 +4998,9 @@ class dblink(object):
 			else:
 				# we are merging a fifo or device node
 				zing = "!!!"
-				if mydmode is None:
+				if instmasked:
+					zing = "###"
+				elif mydmode is None:
 					# destination doesn't exist
 					if movefile(mysrc, mydest, newmtime=thismtime,
 						sstat=mystat, mysettings=self.settings,
diff --git a/pym/portage/package/ebuild/config.py b/pym/portage/package/ebuild/config.py
index 3f575fcaf..d04baacf9 100644
--- a/pym/portage/package/ebuild/config.py
+++ b/pym/portage/package/ebuild/config.py
@@ -271,6 +271,7 @@ class config(object):
 			self.mycpv = clone.mycpv
 			self._setcpv_args_hash = clone._setcpv_args_hash
 			self._soname_provided = clone._soname_provided
+			self.install_mask = clone.install_mask
 
 			# immutable attributes (internal policy ensures lack of mutation)
 			self._locations_manager = clone._locations_manager
@@ -2473,7 +2474,7 @@ class config(object):
 			install_mask.append("/usr/share/info")
 		if 'noman' in self.features:
 			install_mask.append("/usr/share/man")
-		self["INSTALL_MASK"] = ' '.join(install_mask)
+		self.install_mask = tuple(install_mask)
 
 		if self.mycpv is None:
 			# Generate global USE_EXPAND variables settings that are
-- 
2.16.2



  parent reply	other threads:[~2018-03-15 19:22 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-03-15 19:22 [gentoo-portage-dev] [PATCH 0/3] INSTALL_MASK refurbishing resubmit Michał Górny
2018-03-15 19:22 ` [gentoo-portage-dev] [PATCH 1/3] portage.package.ebuild.config: Move FEATURES=no* handling there Michał Górny
2018-03-15 19:22 ` Michał Górny [this message]
2018-03-15 19:22 ` [gentoo-portage-dev] [PATCH 3/3] portage.dbapi.vartree: Support exclusions in INSTALL_MASK Michał Górny
2018-03-15 21:02   ` Alec Warner
2018-03-15 21:17     ` Michał Górny
2018-03-15 21:44     ` Joakim Tjernlund
2018-03-16  7:50       ` Michał Górny
2018-03-16  8:08         ` Joakim Tjernlund
2018-03-16  5:10 ` [gentoo-portage-dev] [PATCH 0/3] INSTALL_MASK refurbishing resubmit Zac Medico
2018-03-16  8:31   ` Joakim Tjernlund
2018-03-16 10:08   ` Michał Górny
2018-03-16 17:07     ` Zac Medico
2018-03-16 21:13       ` Michał Górny
2018-03-16 21:25         ` Zac Medico
2018-03-18  9:03   ` Michał Górny
2018-03-18 18:22     ` Zac Medico
2018-03-19  6:27     ` Joakim Tjernlund
2018-03-16  8:11 ` Joakim Tjernlund
2018-03-16  8:13   ` Michał Górny
2018-03-18  9:57     ` Joakim Tjernlund
2018-03-19 22:59 ` Zac Medico
2018-03-23  0:52   ` Joakim Tjernlund
2018-03-23  1:09     ` Zac Medico
2018-03-23  8:33     ` Michał Górny
2018-03-23  9:05       ` Joakim Tjernlund

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180315192212.13454-3-mgorny@gentoo.org \
    --to=mgorny@gentoo.org \
    --cc=gentoo-portage-dev@lists.gentoo.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox