Gentoo Archives: gentoo-commits

From: Zac Medico <zmedico@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/portage:master commit in: man/, pym/portage/dbapi/, bin/, pym/portage/
Date: Sun, 01 Jul 2012 07:54:26
Message-Id: 1341129232.f807bb54317db5f8073f8904897cf4b9d87bf2cd.zmedico@gentoo
1 commit: f807bb54317db5f8073f8904897cf4b9d87bf2cd
2 Author: Zac Medico <zmedico <AT> gentoo <DOT> org>
3 AuthorDate: Sun Jul 1 07:53:52 2012 +0000
4 Commit: Zac Medico <zmedico <AT> gentoo <DOT> org>
5 CommitDate: Sun Jul 1 07:53:52 2012 +0000
6 URL: http://git.overlays.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=f807bb54
7
8 Support FEATURES={downgrade,unmerge}-backup
9
10 This will fix bug #156282 and bug #424275.
11
12 ---
13 bin/quickpkg | 15 ++++---
14 man/make.conf.5 | 13 +++++-
15 pym/portage/const.py | 4 +-
16 pym/portage/dbapi/vartree.py | 93 +++++++++++++++++++++++++++++++++++++----
17 4 files changed, 108 insertions(+), 17 deletions(-)
18
19 diff --git a/bin/quickpkg b/bin/quickpkg
20 index d908c03..a6bd4d4 100755
21 --- a/bin/quickpkg
22 +++ b/bin/quickpkg
23 @@ -1,5 +1,5 @@
24 #!/usr/bin/python
25 -# Copyright 1999-2010 Gentoo Foundation
26 +# Copyright 1999-2012 Gentoo Foundation
27 # Distributed under the terms of the GNU General Public License v2
28
29 from __future__ import print_function
30 @@ -68,11 +68,14 @@ def quickpkg_atom(options, infos, arg, eout):
31 bintree.prevent_collision(cpv)
32 dblnk = vardb._dblink(cpv)
33 have_lock = False
34 - try:
35 - dblnk.lockdb()
36 - have_lock = True
37 - except PermissionDenied:
38 - pass
39 +
40 + if "__PORTAGE_INHERIT_VARDB_LOCK" not in settings:
41 + try:
42 + dblnk.lockdb()
43 + have_lock = True
44 + except PermissionDenied:
45 + pass
46 +
47 try:
48 if not dblnk.exists():
49 # unmerged by a concurrent process
50
51 diff --git a/man/make.conf.5 b/man/make.conf.5
52 index 7d07344..876a8a3 100644
53 --- a/man/make.conf.5
54 +++ b/man/make.conf.5
55 @@ -1,4 +1,4 @@
56 -.TH "MAKE.CONF" "5" "May 2012" "Portage VERSION" "Portage"
57 +.TH "MAKE.CONF" "5" "Jul 2012" "Portage VERSION" "Portage"
58 .SH "NAME"
59 make.conf \- custom settings for Portage
60 .SH "SYNOPSIS"
61 @@ -293,6 +293,12 @@ strangely configured Samba server (oplocks off, NFS re\-export). A tool
62 /usr/lib/portage/bin/clean_locks exists to help handle lock issues
63 when a problem arises (normally due to a crash or disconnect).
64 .TP
65 +.B downgrade\-backup
66 +When a package is downgraded to a lower version, call \fBquickpkg\fR(1)
67 +in order to create a backup of the installed version before it is
68 +unmerged (if a binary package of the same version does not already
69 +exist). Also see the related \fIunmerge\-backup\fR feature.
70 +.TP
71 .B ebuild\-locks
72 Use locks to ensure that unsandboxed ebuild phases never execute
73 concurrently. Also see \fIparallel\-install\fR.
74 @@ -514,6 +520,11 @@ continue to execute the remaining phases as if the failure had not occurred.
75 Note that the test phase for a specific package may be disabled by masking
76 the "test" \fBUSE\fR flag in \fBpackage.use.mask\fR (see \fBportage\fR(5)).
77 .TP
78 +.B unmerge\-backup
79 +Call \fBquickpkg\fR(1) to create a backup of each package before it is
80 +unmerged (if a binary package of the same version does not already exist).
81 +Also see the related \fIdowngrade\-backup\fR feature.
82 +.TP
83 .B unmerge\-logs
84 Keep logs from successful unmerge phases. This is relevant only when
85 \fBPORT_LOGDIR\fR is set.
86
87 diff --git a/pym/portage/const.py b/pym/portage/const.py
88 index 3607df0..4a07710 100644
89 --- a/pym/portage/const.py
90 +++ b/pym/portage/const.py
91 @@ -90,7 +90,8 @@ SUPPORTED_FEATURES = frozenset([
92 "ccache", "chflags", "clean-logs",
93 "collision-protect", "compress-build-logs", "compressdebug",
94 "config-protect-if-modified",
95 - "digest", "distcc", "distcc-pump", "distlocks", "ebuild-locks", "fakeroot",
96 + "digest", "distcc", "distcc-pump", "distlocks",
97 + "downgrade-backup", "ebuild-locks", "fakeroot",
98 "fail-clean", "force-mirror", "force-prefix", "getbinpkg",
99 "installsources", "keeptemp", "keepwork", "fixlafiles", "lmirror",
100 "metadata-transfer", "mirror", "multilib-strict", "news",
101 @@ -103,6 +104,7 @@ SUPPORTED_FEATURES = frozenset([
102 "sign", "skiprocheck", "split-elog", "split-log", "splitdebug",
103 "strict", "stricter", "suidctl", "test", "test-fail-continue",
104 "unknown-features-filter", "unknown-features-warn",
105 + "unmerge-backup",
106 "unmerge-logs", "unmerge-orphans", "userfetch", "userpriv",
107 "usersandbox", "usersync", "webrsync-gpg", "xattr"])
108
109
110 diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py
111 index 34098ea..0d7327a 100644
112 --- a/pym/portage/dbapi/vartree.py
113 +++ b/pym/portage/dbapi/vartree.py
114 @@ -21,6 +21,7 @@ portage.proxy.lazyimport.lazyimport(globals(),
115 'portage.package.ebuild.doebuild:doebuild_environment,' + \
116 '_merge_unicode_error', '_spawn_phase',
117 'portage.package.ebuild.prepare_build_dirs:prepare_build_dirs',
118 + 'portage.package.ebuild._ipc.QueryCommand:QueryCommand',
119 'portage.update:fixdbentries',
120 'portage.util:apply_secpass_permissions,ConfigProtect,ensure_dirs,' + \
121 'writemsg,writemsg_level,write_atomic,atomic_ofstream,writedict,' + \
122 @@ -62,6 +63,7 @@ from _emerge.EbuildPhase import EbuildPhase
123 from _emerge.emergelog import emergelog
124 from _emerge.PollScheduler import PollScheduler
125 from _emerge.MiscFunctionsProcess import MiscFunctionsProcess
126 +from _emerge.SpawnProcess import SpawnProcess
127
128 import errno
129 import fnmatch
130 @@ -1777,6 +1779,11 @@ class dblink(object):
131 showMessage = self._display_merge
132 if self.vartree.dbapi._categories is not None:
133 self.vartree.dbapi._categories = None
134 +
135 + # When others_in_slot is not None, the backup has already been
136 + # handled by the caller.
137 + caller_handles_backup = others_in_slot is not None
138 +
139 # When others_in_slot is supplied, the security check has already been
140 # done for this slot, so it shouldn't be repeated until the next
141 # replacement or unmerge operation.
142 @@ -1842,6 +1849,11 @@ class dblink(object):
143 prepare_build_dirs(settings=self.settings, cleanup=True)
144 log_path = self.settings.get("PORTAGE_LOG_FILE")
145
146 + if not caller_handles_backup:
147 + retval = self._pre_unmerge_backup(background)
148 + if retval != os.EX_OK:
149 + return retval
150 +
151 # Log the error after PORTAGE_LOG_FILE is initialized
152 # by prepare_build_dirs above.
153 if eapi_unsupported:
154 @@ -3833,6 +3845,20 @@ class dblink(object):
155 self.delete()
156 ensure_dirs(self.dbtmpdir)
157
158 + downgrade = False
159 + if self._installed_instance is not None and \
160 + vercmp(self.mycpv.version,
161 + self._installed_instance.mycpv.version) < 0:
162 + downgrade = True
163 +
164 + if self._installed_instance is not None:
165 + rval = self._pre_merge_backup(self._installed_instance, downgrade)
166 + if rval != os.EX_OK:
167 + showMessage(_("!!! FAILED preinst: ") +
168 + "quickpkg: %s\n" % rval,
169 + level=logging.ERROR, noiselevel=-1)
170 + return rval
171 +
172 # run preinst script
173 showMessage(_(">>> Merging %(cpv)s to %(destroot)s\n") % \
174 {"cpv":self.mycpv, "destroot":destroot})
175 @@ -3866,20 +3892,15 @@ class dblink(object):
176 #if we have a file containing previously-merged config file md5sums, grab it.
177 self.vartree.dbapi._fs_lock()
178 try:
179 + # Always behave like --noconfmem is enabled for downgrades
180 + # so that people who don't know about this option are less
181 + # likely to get confused when doing upgrade/downgrade cycles.
182 cfgfiledict = grabdict(self.vartree.dbapi._conf_mem_file)
183 - if "NOCONFMEM" in self.settings:
184 + if "NOCONFMEM" in self.settings or downgrade:
185 cfgfiledict["IGNORE"]=1
186 else:
187 cfgfiledict["IGNORE"]=0
188
189 - # Always behave like --noconfmem is enabled for downgrades
190 - # so that people who don't know about this option are less
191 - # likely to get confused when doing upgrade/downgrade cycles.
192 - for other in others_in_slot:
193 - if vercmp(self.mycpv.version, other.mycpv.version) < 0:
194 - cfgfiledict["IGNORE"] = 1
195 - break
196 -
197 rval = self._merge_contents(srcroot, destroot, cfgfiledict)
198 if rval != os.EX_OK:
199 return rval
200 @@ -4682,6 +4703,60 @@ class dblink(object):
201 "Is this a regular package (does it have a CATEGORY file? A dblink can be virtual *and* regular)"
202 return os.path.exists(os.path.join(self.dbdir, "CATEGORY"))
203
204 + def _pre_merge_backup(self, backup_dblink, downgrade):
205 +
206 + if ("unmerge-backup" in self.settings.features or
207 + (downgrade and "downgrade-backup" in self.settings.features)):
208 + return self._quickpkg_dblink(backup_dblink, False, None)
209 +
210 + return os.EX_OK
211 +
212 + def _pre_unmerge_backup(self, background):
213 +
214 + if "unmerge-backup" in self.settings.features :
215 + logfile = None
216 + if self.settings.get("PORTAGE_BACKGROUND") != "subprocess":
217 + logfile = self.settings.get("PORTAGE_LOG_FILE")
218 + return self._quickpkg_dblink(self, background, logfile)
219 +
220 + return os.EX_OK
221 +
222 + def _quickpkg_dblink(self, backup_dblink, background, logfile):
223 +
224 + trees = QueryCommand.get_db()[self.settings["EROOT"]]
225 + bintree = trees["bintree"]
226 + binpkg_path = bintree.getname(backup_dblink.mycpv)
227 + if os.path.exists(binpkg_path) and \
228 + backup_dblink.mycpv not in bintree.invalids:
229 + return os.EX_OK
230 +
231 + self.lockdb()
232 + try:
233 +
234 + if not backup_dblink.exists():
235 + # It got unmerged by a concurrent process.
236 + return os.EX_OK
237 +
238 + # Call quickpkg for support of QUICKPKG_DEFAULT_OPTS and stuff.
239 + quickpkg_binary = os.path.join(self.settings["PORTAGE_BIN_PATH"],
240 + "quickpkg")
241 +
242 + # Let quickpkg inherit the global vartree config's env.
243 + env = dict(self.vartree.settings.items())
244 + env["__PORTAGE_INHERIT_VARDB_LOCK"] = "1"
245 +
246 + quickpkg_proc = SpawnProcess(
247 + args=[portage._python_interpreter, quickpkg_binary,
248 + "=%s" % (backup_dblink.mycpv,)],
249 + background=background, env=env,
250 + scheduler=self._scheduler, logfile=logfile)
251 + quickpkg_proc.start()
252 +
253 + return quickpkg_proc.wait()
254 +
255 + finally:
256 + self.unlockdb()
257 +
258 def merge(mycat, mypkg, pkgloc, infloc,
259 myroot=None, settings=None, myebuild=None,
260 mytree=None, mydbapi=None, vartree=None, prev_mtimes=None, blockers=None,