diff -Nur portage-2.0.50-r1.orig/bin/emerge portage-2.0.50-r1/bin/emerge --- portage-2.0.50-r1.orig/bin/emerge 2004-02-10 01:16:03.000000000 +0000 +++ portage-2.0.50-r1/bin/emerge 2004-02-10 17:11:31.000000000 +0000 @@ -2311,7 +2311,7 @@ if "--verbose" in myopts: myvars=portage.settings.keys() else: - myvars=['GENTOO_MIRRORS', 'CONFIG_PROTECT', 'CONFIG_PROTECT_MASK', + myvars=['GENTOO_MIRRORS', 'CONFIG_PROTECT', 'CONFIG_PROTECT_MASK', 'CONFIG_PROTECT_FILES', 'CONFIG_PROTECT_FILES_MASK', 'PORTDIR', 'DISTDIR', 'PKGDIR', 'PORTAGE_TMPDIR', 'PORTDIR_OVERLAY', 'USE', 'COMPILER', 'CHOST', 'CFLAGS', 'CXXFLAGS','ACCEPT_KEYWORDS', 'MAKEOPTS', 'AUTOCLEAN', 'SYNC', 'FEATURES'] diff -Nur portage-2.0.50-r1.orig/bin/emergehelp.py portage-2.0.50-r1/bin/emergehelp.py --- portage-2.0.50-r1.orig/bin/emergehelp.py 2004-02-04 22:40:21.000000000 +0000 +++ portage-2.0.50-r1/bin/emergehelp.py 2004-02-10 18:32:37.221313278 +0000 @@ -360,6 +360,10 @@ CONFIG_PROTECT_MASK="/etc/wget /etc/rc.d" +You can do the same only for files with CONFIG_PROTECT_FILES and +CONFIG_PROTECT_FILES_MASK. They will only match files, no recursion is +done and they will take precedence over CONFIG_PROTECT/CONFIG_PROTECT_MASK. + etc-update is also available to aid in the merging of these files. It provides a vimdiff interactive merging setup and can auto-merge trivial changes. diff -Nur portage-2.0.50-r1.orig/man/make.conf.5 portage-2.0.50-r1/man/make.conf.5 --- portage-2.0.50-r1.orig/man/make.conf.5 2004-01-20 02:08:25.000000000 +0000 +++ portage-2.0.50-r1/man/make.conf.5 2004-02-10 18:39:15.742391791 +0000 @@ -1,4 +1,4 @@ -.TH "MAKE.CONF" "5" "Feb 2003" "Portage 2.0.47" "portage" +.TH "MAKE.CONF" "5" "Feb 2004" "Portage 2.0.50" "portage" .SH "NAME" make.conf \- custom settings for Portage .SH "SYNOPSIS" @@ -92,6 +92,14 @@ All directories that are defined here will have "config file protection" disabled for them. For more information, please see `emerge \-\-help config`. .TP +\fBCONFIG_PROTECT_FILES\fR = \fI[space delimited list of files]\fR +All files that are defined here will have "config file protection" enabled +for them. For more information, please see `emerge \-\-help config`. +.TP +\fBCONFIG_PROTECT_FILES_MASK\fR = \fI[space delimited list of files]\fR +All files that are defined here will have "config file protection" disabled +for them. For more information, please see `emerge \-\-help config`. +.TP \fBDEBUGBUILD\fR If this is defined, binaries and libraries are not stripped before \fImerge\fR. .TP diff -Nur portage-2.0.50-r1.orig/pym/portage.py portage-2.0.50-r1/pym/portage.py --- portage-2.0.50-r1.orig/pym/portage.py 2004-02-10 01:22:13.000000000 +0000 +++ portage-2.0.50-r1/pym/portage.py 2004-02-10 18:35:51.079973464 +0000 @@ -208,7 +208,7 @@ writemsg(red("*** Please add this user to the portage group if you wish to use portage.\n")) writemsg("\n") -incrementals=["USE","FEATURES","ACCEPT_KEYWORDS","ACCEPT_LICENSE","CONFIG_PROTECT_MASK","CONFIG_PROTECT","PRELINK_PATH","PRELINK_PATH_MASK"] +incrementals=["USE","FEATURES","ACCEPT_KEYWORDS","ACCEPT_LICENSE","CONFIG_PROTECT_MASK","CONFIG_PROTECT","CONFIG_PROTECT_FILES_MASK","CONFIG_PROTECT_FILES","PRELINK_PATH","PRELINK_PATH_MASK"] stickies=["KEYWORDS_ACCEPT","USE","CFLAGS","CXXFLAGS","MAKEOPTS","EXTRA_ECONF","EXTRA_EMAKE"] def getcwd(): @@ -611,8 +611,10 @@ specials={ "KDEDIRS":[],"PATH":[],"CLASSPATH":[],"LDPATH":[],"MANPATH":[], "INFODIR":[],"INFOPATH":[],"ROOTPATH":[],"CONFIG_PROTECT":[], - "CONFIG_PROTECT_MASK":[],"PRELINK_PATH":[],"PRELINK_PATH_MASK":[], - "PYTHONPATH":[], "ADA_INCLUDE_PATH":[], "ADA_OBJECTS_PATH":[] + "CONFIG_PROTECT_MASK":[],"CONFIG_PROTECT_FILES":[], + "CONFIG_PROTECT_FILES_MASK":[],"PRELINK_PATH":[], + "PRELINK_PATH_MASK":[],"PYTHONPATH":[],"ADA_INCLUDE_PATH":[], + "ADA_OBJECTS_PATH":[] } colon_seperated = [ "ADA_INCLUDE_PATH", "ADA_OBJECTS_PATH", @@ -740,7 +742,7 @@ if len(specials[path])==0: continue outstring="export "+path+"='" - if path in ["CONFIG_PROTECT","CONFIG_PROTECT_MASK"]: + if path in ["CONFIG_PROTECT","CONFIG_PROTECT_MASK","CONFIG_PROTECT_FILES","CONFIG_PROTECT_FILES_MASK"]: for x in specials[path][:-1]: outstring += x+" " else: @@ -5190,33 +5192,60 @@ def updateprotect(self): #do some config file management prep - self.protect=[] + self.protect={} for x in string.split(self.settings["CONFIG_PROTECT"]): - ppath=os.path.normpath(self.myroot+"///"+x)+"/" - if os.path.isdir(ppath): - self.protect.append(ppath) - - self.protectmask=[] + x=os.path.normpath(self.myroot+"///"+x) + if os.path.isdir(x): + if os.path.basename(x)=="": + self.protect[os.path.dirname(x)]=1 + else: + self.protect[x]=1 + + self.protectmask={} for x in string.split(self.settings["CONFIG_PROTECT_MASK"]): - ppath=os.path.normpath(self.myroot+"///"+x)+"/" - if os.path.isdir(ppath): - self.protectmask.append(ppath) - #if it doesn't exist, silently skip it + x=os.path.normpath(self.myroot+"///"+x) + if os.path.isdir(x): + if os.path.basename(x)=="": + self.protectmask[os.path.dirname(x)]=1 + else: + self.protectmask[x]=1 + + self.protectfiles={} + for x in string.split(self.settings["CONFIG_PROTECT_FILES"]): + x=os.path.normpath(self.myroot+"///"+x) + if os.path.isfile(x): + self.protectfiles[x]=1 + + self.protectfilesmask={} + for x in string.split(self.settings["CONFIG_PROTECT_FILES_MASK"]): + x=os.path.normpath(self.myroot+"///"+x) + if os.path.isfile(x): + self.protectfilesmask[x]=1 def isprotected(self,obj): - """Checks if obj is in the current protect/mask directories. Returns - 0 on unprotected/masked, and 1 on protected.""" - masked=0 + """Checks if obj is in the current protect/mask directories or is a file protected. + Returns 0 on unprotected/masked, and 1 on protected.""" protected=0 - for ppath in self.protect: - if (len(ppath) > masked) and (obj[0:len(ppath)]==ppath): - protected=len(ppath) - #config file management - for pmpath in self.protectmask: - if (len(pmpath) >= protected) and (obj[0:len(pmpath)]==pmpath): - #skip, it's in the mask - masked=len(pmpath) - return (protected > masked) + npath=os.path.normpath(obj) + myobj="" + + #if obj is a file, we need to check the files protect/mask + if os.path.isfile(npath): + if self.protectfilesmask.has_key(npath): + return 0 + if self.protectfiles.has_key(npath): + return 1 + + #now we check/traverse the directory protects/masks + for x in string.split(npath, "/"): + myobj=myobj+x + if self.protect.has_key(myobj): + protected=1 + if self.protectmask.has_key(myobj): + protected=0 + myobj=myobj+"/" + + return protected def unmerge(self,pkgfiles=None,trimworld=1,cleanup=0): global dircache @@ -5700,11 +5729,6 @@ #A directory is specified. Figure out protection paths, listdir() it and process it. mergelist=listdir(srcroot+stufftomerge) offset=stufftomerge - # We need mydest defined up here to calc. protection paths. This is now done once per - # directory rather than once per file merge. This should really help merge performance. - # Trailing / ensures that protects/masks with trailing /'s match. - mytruncpath="/"+offset+"/" - myppath=self.isprotected(mytruncpath) else: mergelist=stufftomerge offset="" @@ -5843,7 +5867,7 @@ # install of destination is blocked by an existing regular file; # now, config file management may come into play. # we only need to tweak mydest if cfg file management is in play. - if myppath: + if self.isprotected(myrealdest): # we have a protection path; enable config file management. destmd5=perform_md5(mydest) cycled=0