Gentoo Archives: gentoo-commits

From: "Fabian Groffen (grobian)" <grobian@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] portage r12132 - in main/branches/prefix: bin man pym/_emerge pym/portage pym/portage/dbapi
Date: Mon, 01 Dec 2008 21:10:58
Message-Id: E1L7G2g-0007CX-Py@stork.gentoo.org
1 Author: grobian
2 Date: 2008-12-01 21:10:53 +0000 (Mon, 01 Dec 2008)
3 New Revision: 12132
4
5 Modified:
6 main/branches/prefix/bin/ebuild.sh
7 main/branches/prefix/bin/isolated-functions.sh
8 main/branches/prefix/bin/repoman
9 main/branches/prefix/man/portage.5
10 main/branches/prefix/pym/_emerge/__init__.py
11 main/branches/prefix/pym/portage/__init__.py
12 main/branches/prefix/pym/portage/dbapi/vartree.py
13 Log:
14 Merged from trunk -r12086:12117
15
16 | 12090 | Note that file names in /etc/portage/package.* directories |
17 | zmedico | are sorted ascending alphabetical order before being summed |
18 | | together. |
19
20 | 12092 | Bug #248782 - Handle permission error in |
21 | zmedico | EbuildFetchonly.execute() if PORTAGE_TMPDIR is not writable. |
22
23 | 12094 | Bug #248464 - With git, there's never any keyword expansion, |
24 | zmedico | so there's no need to regenerate manifests and all files |
25 | | will be committed in one big commit at the end. |
26
27 | 12096 | Remove redundant reference to 'mynew' since 'myupdates' |
28 | zmedico | already contains those files. |
29
30 | 12098 | Eliminate redundant Manifest separation code by combining |
31 | zmedico | mychanged + mynew sooner. |
32
33 | 12101 | Add some more clarification to the 'ebuild phase exited |
34 | zmedico | unexpectedly' message. |
35
36 | 12103 | Make Scheduler.merge() bail out early if PORTAGE_TMPDIR is |
37 | zmedico | not properly set. |
38
39 | 12105 | Bug #205044 - When creating $EBUILD_EXIT_STATUS_FILE, don't |
40 | zmedico | direct output to /dev/null since it should never fail and if |
41 | | it does then the error message might be useful. |
42
43 | 12107 | Don't direct to /dev/null when creating |
44 | zmedico | $EBUILD_EXIT_STATUS_FILE inside die. |
45
46 | 12109 | Bug #235642 - Create hardlinks when merging identical files. |
47 | zmedico | This works by using a tuple of (md5, st_size) as a key to a |
48 | | list of hardlink candidates. Multiple candidates are used in |
49 | | case some happen to be merged to separate devices. |
50
51 | 12111 | In movefile(), ignore the hardlink_candidates parameter when |
52 | zmedico | it's an empty list. |
53
54 | 12113 | For bug #235642, include the stat mode, uid, and gid bits in |
55 | zmedico | the hardlink key. |
56
57 | 12115 | Don't call prepare_build_dirs() inside doebuild() when |
58 | zmedico | called for parallel fetching. |
59
60 | 12117 | Use stat st_dev attributes instead of the older approach. |
61 | zmedico | |
62
63
64 Modified: main/branches/prefix/bin/ebuild.sh
65 ===================================================================
66 --- main/branches/prefix/bin/ebuild.sh 2008-12-01 20:59:48 UTC (rev 12131)
67 +++ main/branches/prefix/bin/ebuild.sh 2008-12-01 21:10:53 UTC (rev 12132)
68 @@ -275,9 +275,13 @@
69 # Ensure that $PWD is sane whenever possible, to protect against
70 # exploitation of insecure search path for python -c in ebuilds.
71 # See bug #239560.
72 -if ! hasq "$EBUILD_PHASE" clean depend help ; then
73 +if ! hasq "$EBUILD_PHASE" clean cleanrm depend help ; then
74 cd "$PORTAGE_BUILDDIR" || \
75 die "PORTAGE_BUILDDIR does not exist: '$PORTAGE_BUILDDIR'"
76 +else
77 + # Don't try to create this when it's parent
78 + # directory doesn't necessarily exist.
79 + unset EBUILD_EXIT_STATUS_FILE
80 fi
81
82 #if no perms are specified, dirs/files will have decent defaults
83 @@ -2087,8 +2091,10 @@
84 exit 1
85 ;;
86 esac
87 - [ -n "${EBUILD_EXIT_STATUS_FILE}" ] && \
88 - touch "${EBUILD_EXIT_STATUS_FILE}" &>/dev/null
89 + if [ -n "$EBUILD_EXIT_STATUS_FILE" ] ; then
90 + > "$EBUILD_EXIT_STATUS_FILE" || \
91 + die "failed to create '$EBUILD_EXIT_STATUS_FILE'"
92 + fi
93 }
94
95 [[ -n $EBUILD_SH_ARGS ]] && ebuild_main
96
97 Modified: main/branches/prefix/bin/isolated-functions.sh
98 ===================================================================
99 --- main/branches/prefix/bin/isolated-functions.sh 2008-12-01 20:59:48 UTC (rev 12131)
100 +++ main/branches/prefix/bin/isolated-functions.sh 2008-12-01 21:10:53 UTC (rev 12132)
101 @@ -128,22 +128,8 @@
102 done
103 fi
104
105 - [[ -n ${PORTAGE_LOG_FILE} ]] \
106 - && eerror "build log: '${PORTAGE_LOG_FILE}'"
107 - if [ -f "${T}/environment" ] ; then
108 - eerror "ebuild environment: '${T}/environment'"
109 - elif [ -d "${T}" ] ; then
110 - {
111 - set
112 - export
113 - } > "${T}/die.env"
114 - eerror "ebuild environment: '${T}/die.env'"
115 - fi
116 - eerror "S: '${S}'"
117 + [ -n "$EBUILD_EXIT_STATUS_FILE" ] && > "$EBUILD_EXIT_STATUS_FILE"
118
119 - [ -n "${EBUILD_EXIT_STATUS_FILE}" ] && \
120 - touch "${EBUILD_EXIT_STATUS_FILE}" &>/dev/null
121 -
122 # subshell die support
123 kill -s SIGTERM ${EBUILD_MASTER_PID}
124 exit 1
125
126 Modified: main/branches/prefix/bin/repoman
127 ===================================================================
128 --- main/branches/prefix/bin/repoman 2008-12-01 20:59:48 UTC (rev 12131)
129 +++ main/branches/prefix/bin/repoman 2008-12-01 21:10:53 UTC (rev 12132)
130 @@ -1758,23 +1758,14 @@
131 # Manifests need to be regenerated after all other commits, so don't commit
132 # them now even if they have changed.
133 mymanifests = set()
134 - changed_set = set()
135 - new_set = set()
136 - for f in mychanged:
137 + myupdates = set()
138 + for f in mychanged + mynew:
139 if "Manifest" == os.path.basename(f):
140 mymanifests.add(f)
141 else:
142 - changed_set.add(f)
143 - for f in mynew:
144 - if "Manifest" == os.path.basename(f):
145 - mymanifests.add(f)
146 - else:
147 - new_set.add(f)
148 - mychanged = list(changed_set)
149 - mynew = list(new_set)
150 + myupdates.add(f)
151 + myupdates = list(myupdates)
152 mymanifests = list(mymanifests)
153 - del changed_set, new_set
154 - myupdates = mychanged + mynew
155 myheaders = []
156 mydirty = []
157 headerstring = "'\$(Header|Id)"
158 @@ -1795,8 +1786,16 @@
159 if myout[0] == 0:
160 myheaders.append(myfile)
161
162 - print "*",green(str(len(myupdates))),"files being committed...",green(str(len(myheaders))),"have headers that will change."
163 - print "*","Files with headers will cause the manifests to be made and recommited."
164 + print "* %s files being committed..." % green(str(len(myupdates))),
165 + if vcs == 'git':
166 + # With git, there's never any keyword expansion, so there's
167 + # no need to regenerate manifests and all files will be
168 + # committed in one big commit at the end.
169 + print
170 + else:
171 + print "%s have headers that will change." % green(str(len(myheaders)))
172 + print "* Files with headers will cause the " + \
173 + "manifests to be made and recommited."
174 logging.info("myupdates:", str(myupdates))
175 logging.info("myheaders:", str(myheaders))
176
177 @@ -1844,7 +1843,7 @@
178 commitmessage += ", RepoMan options: --force"
179 commitmessage += ")"
180
181 - if myupdates or myremoved:
182 + if vcs != 'git' and (myupdates or myremoved):
183 myfiles = myupdates + myremoved
184 if not myheaders and "sign" not in repoman_settings.features:
185 myfiles += mymanifests
186 @@ -1937,8 +1936,8 @@
187 write_atomic(x, "".join(mylines))
188
189 manifest_commit_required = True
190 - if myupdates or myremoved or mynew:
191 - myfiles=myupdates+myremoved+mynew
192 + if vcs != 'git' and (myupdates or myremoved):
193 + myfiles = myupdates + myremoved
194 for x in range(len(myfiles)-1, -1, -1):
195 if myfiles[x].count("/") < 4-repolevel:
196 del myfiles[x]
197 @@ -2059,8 +2058,14 @@
198 portage.writemsg("!!! Disabled FEATURES='sign'\n")
199 signed = False
200
201 - if manifest_commit_required or signed:
202 + if vcs == 'git' or manifest_commit_required or signed:
203
204 + myfiles = mymanifests[:]
205 + if vcs == 'git':
206 + myfiles += myupdates
207 + myfiles += myremoved
208 + myfiles.sort()
209 +
210 fd, commitmessagefile = tempfile.mkstemp(".repoman.msg")
211 mymsg = os.fdopen(fd, "w")
212 mymsg.write(commitmessage)
213 @@ -2075,7 +2080,7 @@
214 commit_cmd.append("commit")
215 commit_cmd.extend(vcs_local_opts)
216 commit_cmd.extend(["-F", commitmessagefile])
217 - commit_cmd.extend(f.lstrip("./") for f in mymanifests)
218 + commit_cmd.extend(f.lstrip("./") for f in myfiles)
219
220 try:
221 if options.pretend:
222
223 Modified: main/branches/prefix/man/portage.5
224 ===================================================================
225 --- main/branches/prefix/man/portage.5 2008-12-01 20:59:48 UTC (rev 12131)
226 +++ main/branches/prefix/man/portage.5 2008-12-01 21:10:53 UTC (rev 12132)
227 @@ -371,13 +371,14 @@
228 .BR /etc/portage/
229 Any file in this directory that begins with "package." can be more than just a
230 flat file. If it is a directory, then all the files in that directory will be
231 -summed together as if it were a single file.
232 +sorted in ascending alphabetical order by file name and summed together as if
233 +it were a single file.
234
235 .I Example:
236 .nf
237 -/etc/portage/package.keywords/kde
238 /etc/portage/package.keywords/common
239 /etc/portage/package.keywords/e17
240 +/etc/portage/package.keywords/kde
241 .fi
242 .RS
243 .TP
244
245 Modified: main/branches/prefix/pym/_emerge/__init__.py
246 ===================================================================
247 --- main/branches/prefix/pym/_emerge/__init__.py 2008-12-01 20:59:48 UTC (rev 12131)
248 +++ main/branches/prefix/pym/_emerge/__init__.py 2008-12-01 21:10:53 UTC (rev 12132)
249 @@ -1632,7 +1632,12 @@
250 settings = self.settings
251 global_tmpdir = settings["PORTAGE_TMPDIR"]
252 from tempfile import mkdtemp
253 - private_tmpdir = mkdtemp("", "._portage_fetch_.", global_tmpdir)
254 + try:
255 + private_tmpdir = mkdtemp("", "._portage_fetch_.", global_tmpdir)
256 + except OSError, e:
257 + if e.errno != portage.exception.PermissionDenied.errno:
258 + raise
259 + raise portage.exception.PermissionDenied(global_tmpdir)
260 settings["PORTAGE_TMPDIR"] = private_tmpdir
261 settings.backup_changes("PORTAGE_TMPDIR")
262 try:
263 @@ -9734,6 +9739,22 @@
264
265 for root in self.trees:
266 root_config = self.trees[root]["root_config"]
267 +
268 + # Even for --pretend --fetch mode, PORTAGE_TMPDIR is required
269 + # since it might spawn pkg_nofetch which requires PORTAGE_BUILDDIR
270 + # for ensuring sane $PWD (bug #239560) and storing elog messages.
271 + tmpdir = root_config.settings.get("PORTAGE_TMPDIR", "")
272 + if not tmpdir or not os.path.isdir(tmpdir):
273 + msg = "The directory specified in your " + \
274 + "PORTAGE_TMPDIR variable, '%s', " % tmpdir + \
275 + "does not exist. Please create this " + \
276 + "directory or correct your PORTAGE_TMPDIR setting."
277 + msg = textwrap.wrap(msg, 70)
278 + out = portage.output.EOutput()
279 + for l in msg:
280 + out.eerror(l)
281 + return 1
282 +
283 if self._background:
284 root_config.settings.unlock()
285 root_config.settings["PORTAGE_BACKGROUND"] = "1"
286
287 Modified: main/branches/prefix/pym/portage/__init__.py
288 ===================================================================
289 --- main/branches/prefix/pym/portage/__init__.py 2008-12-01 20:59:48 UTC (rev 12131)
290 +++ main/branches/prefix/pym/portage/__init__.py 2008-12-01 21:10:53 UTC (rev 12132)
291 @@ -5190,9 +5190,20 @@
292 "is known to be triggered " + \
293 "by things such as failed variable " + \
294 "assignments (bug #190128) or bad substitution " + \
295 - "errors (bug #200313). This behavior may also be " + \
296 - "triggered by a corrupt bash binary or a hardware " + \
297 - "problem such as memory or cpu malfunction."
298 + "errors (bug #200313). Normally, before exiting, bash should " + \
299 + "have displayed an error message above. If bash did not " + \
300 + "produce an error message above, it's possible " + \
301 + "that the ebuild has called `exit` when it " + \
302 + "should have called `die` instead. This behavior may also " + \
303 + "be triggered by a corrupt bash binary or a hardware " + \
304 + "problem such as memory or cpu malfunction. If the problem is not " + \
305 + "reproducible or it appears to occur randomly, then it is likely " + \
306 + "to be triggered by a hardware problem. " + \
307 + "If you suspect a hardware problem then you should " + \
308 + "try some basic hardware diagnostics such as memtest. " + \
309 + "Please do not report this as a bug unless it is consistently " + \
310 + "reproducible and you are sure that your bash binary and hardware " + \
311 + "are functioning properly."
312 return msg
313
314 def _doebuild_exit_status_check_and_log(settings, mydo, retval):
315 @@ -5331,6 +5342,9 @@
316 fetchall = 1
317 mydo = "fetch"
318
319 + parallel_fetchonly = mydo in ("fetch", "fetchall") and \
320 + "PORTAGE_PARALLEL_FETCHONLY" in mysettings
321 +
322 if mydo not in clean_phases and not os.path.exists(myebuild):
323 writemsg("!!! doebuild: %s not found for %s\n" % (myebuild, mydo),
324 noiselevel=-1)
325 @@ -5564,7 +5578,7 @@
326
327 # Build directory creation isn't required for any of these.
328 have_build_dirs = False
329 - if not mydo in ("digest", "help", "manifest"):
330 + if not parallel_fetchonly and mydo not in ("digest", "help", "manifest"):
331 mystatus = prepare_build_dirs(myroot, mysettings, cleanup)
332 if mystatus:
333 return mystatus
334 @@ -6005,7 +6019,8 @@
335 raise portage.exception.PortageException(
336 "mv '%s' '%s'" % (src, dest))
337
338 -def movefile(src,dest,newmtime=None,sstat=None,mysettings=None):
339 +def movefile(src, dest, newmtime=None, sstat=None, mysettings=None,
340 + hardlink_candidates=None):
341 """moves a file from src to dest, preserving all permissions and attributes; mtime will
342 be preserved even when moving across filesystems. Returns true on success and false on
343 failure. Move is atomic."""
344 @@ -6077,8 +6092,44 @@
345 print "!!!",e
346 return None
347
348 + hardlinked = False
349 + # Since identical files might be merged to multiple filesystems,
350 + # so os.link() calls might fail for some paths, so try them all.
351 + # For atomic replacement, first create the link as a temp file
352 + # and them use os.rename() to replace the destination.
353 + if hardlink_candidates:
354 + head, tail = os.path.split(dest)
355 + hardlink_tmp = os.path.join(head, ".%s._portage_merge_.%s" % \
356 + (tail, os.getpid()))
357 + try:
358 + os.unlink(hardlink_tmp)
359 + except OSError, e:
360 + if e.errno != errno.ENOENT:
361 + writemsg("!!! Failed to remove hardlink temp file: %s\n" % \
362 + (hardlink_tmp,), noiselevel=-1)
363 + writemsg("!!! %s\n" % (e,), noiselevel=-1)
364 + return None
365 + del e
366 + for hardlink_src in hardlink_candidates:
367 + try:
368 + os.link(hardlink_src, hardlink_tmp)
369 + except OSError:
370 + continue
371 + else:
372 + try:
373 + os.rename(hardlink_tmp, dest)
374 + except OSError, e:
375 + writemsg("!!! Failed to rename %s to %s\n" % \
376 + (hardlink_tmp, dest), noiselevel=-1)
377 + writemsg("!!! %s\n" % (e,), noiselevel=-1)
378 + return None
379 + hardlinked = True
380 + break
381 +
382 renamefailed=1
383 - if sstat[stat.ST_DEV]==dstat[stat.ST_DEV] or selinux_enabled:
384 + if hardlinked:
385 + renamefailed = False
386 + if not hardlinked and (selinux_enabled or sstat.st_dev == dstat.st_dev):
387 try:
388 if selinux_enabled:
389 ret=selinux.secure_rename(src,dest)
390 @@ -6139,11 +6190,14 @@
391 return None
392
393 try:
394 - if newmtime is not None:
395 - os.utime(dest, (newmtime, newmtime))
396 + if hardlinked:
397 + newmtime = long(os.stat(dest).st_mtime)
398 else:
399 - os.utime(dest, (sstat.st_atime, sstat.st_mtime))
400 - newmtime = long(sstat.st_mtime)
401 + if newmtime is not None:
402 + os.utime(dest, (newmtime, newmtime))
403 + else:
404 + os.utime(dest, (sstat.st_atime, sstat.st_mtime))
405 + newmtime = long(sstat.st_mtime)
406 except OSError:
407 # The utime can fail here with EPERM even though the move succeeded.
408 # Instead of failing, use stat to return the mtime if possible.
409
410 Modified: main/branches/prefix/pym/portage/dbapi/vartree.py
411 ===================================================================
412 --- main/branches/prefix/pym/portage/dbapi/vartree.py 2008-12-01 20:59:48 UTC (rev 12131)
413 +++ main/branches/prefix/pym/portage/dbapi/vartree.py 2008-12-01 21:10:53 UTC (rev 12132)
414 @@ -2282,6 +2282,7 @@
415 self._contents_inodes = None
416 self._contents_basenames = None
417 self._linkmap_broken = False
418 + self._md5_merge_map = {}
419
420 def lockdb(self):
421 if self._lock_vdb:
422 @@ -3895,6 +3896,7 @@
423 if self.mergeme(srcroot, destroot, outfile, None,
424 secondhand, cfgfiledict, mymtime):
425 return 1
426 + self._md5_merge_map.clear()
427
428 #restore umask
429 os.umask(prevmask)
430 @@ -4296,9 +4298,18 @@
431 # whether config protection or not, we merge the new file the
432 # same way. Unless moveme=0 (blocking directory)
433 if moveme:
434 - mymtime = movefile(mysrc, mydest, newmtime=thismtime, sstat=mystat, mysettings=self.settings)
435 + hardlink_key = (mymd5, mystat.st_size,
436 + mystat.st_mode, mystat.st_uid, mystat.st_gid)
437 + hardlink_candidates = self._md5_merge_map.get(hardlink_key)
438 + if hardlink_candidates is None:
439 + hardlink_candidates = []
440 + self._md5_merge_map[hardlink_key] = hardlink_candidates
441 + mymtime = movefile(mysrc, mydest, newmtime=thismtime,
442 + sstat=mystat, mysettings=self.settings,
443 + hardlink_candidates=hardlink_candidates)
444 if mymtime is None:
445 return 1
446 + hardlink_candidates.append(mydest)
447 zing = ">>>"
448
449 if mymtime != None: