Gentoo Archives: gentoo-portage-dev

From: Brian Dolbec <dolsen@g.o>
To: gentoo-portage-dev@l.g.o
Subject: Re: [gentoo-portage-dev] [PATCH] Manifest.write: stable/predictable Manifest mtime for rsync (bug 557962)
Date: Mon, 17 Aug 2015 03:25:14
Message-Id: 20150816202506.159df465.dolsen@gentoo.org
In Reply to: [gentoo-portage-dev] [PATCH] Manifest.write: stable/predictable Manifest mtime for rsync (bug 557962) by Zac Medico
1 On Sun, 16 Aug 2015 20:08:10 -0700
2 Zac Medico <zmedico@g.o> wrote:
3
4 > Use the max mtime of the existing Manifest and the files that the
5 > updated Manifest contains.
6 >
7 > X-Gentoo-Bug: 557962
8 > X-Gentoo-Bug-url: https://bugs.gentoo.org/show_bug.cgi?id=557962
9 > ---
10 > pym/portage/manifest.py | 35 +++++++++++++++++++++++++++++++++++
11 > 1 file changed, 35 insertions(+)
12 >
13 > diff --git a/pym/portage/manifest.py b/pym/portage/manifest.py
14 > index 3936b9a..f5cf0f5 100644
15 > --- a/pym/portage/manifest.py
16 > +++ b/pym/portage/manifest.py
17 > @@ -6,6 +6,7 @@ from __future__ import unicode_literals
18 > import errno
19 > import io
20 > import re
21 > +import stat
22 > import sys
23 > import warnings
24 >
25 > @@ -281,6 +282,7 @@ class Manifest(object):
26 > try:
27 > myentries =
28 > list(self._createManifestEntries()) update_manifest = True
29 > + existing_st = None
30 > if myentries and not force:
31 > try:
32 > f =
33 > io.open(_unicode_encode(self.getFullname(), @@ -288,6 +290,7 @@ class
34 > Manifest(object): mode='r', encoding=_encodings['repo.content'],
35 > errors='replace')
36 > oldentries =
37 > list(self._parseManifestLines(f))
38 > + existing_st =
39 > os.fstat(f.fileno()) f.close()
40 > if len(oldentries) ==
41 > len(myentries): update_manifest = False
42 > @@ -309,6 +312,7 @@ class Manifest(object):
43 > # non-empty for all
44 > currently known use cases. write_atomic(self.getFullname(),
45 > "".join("%s\n" % _unicode(myentry) for myentry in myentries))
46 > +
47 > self._apply_max_mtime(existing_st, myentries) rval = True
48 > else:
49 > # With thin manifest,
50 > there's no need to have @@ -328,6 +332,37 @@ class Manifest(object):
51 > raise
52 > return rval
53 >
54 > + def _apply_max_mtime(self, existing_st, entries):
55 > + """
56 > + Set the Manifest mtime to the max mtime of all
57 > relevant files
58 > + (the existing Manifest mtime is included in order to
59 > account for
60 > + eclass modifications that change DIST entries). This
61 > results in a
62 > + stable/predictable mtime, which is useful when
63 > converting thin
64 > + manifests to thick manifests for distribution via
65 > rsync. For
66 > + portability, the mtime is set with 1 second
67 > resolution. +
68 > + @param existing_st: stat result for existing Manifest
69 > + @type existing_st: posix.stat_result
70 > + @param entries: list of current Manifest2Entry
71 > instances
72 > + @type entries: list
73 > + """
74 > + # Use stat_result[stat.ST_MTIME] for 1 second
75 > resolution, since
76 > + # it always rounds down. Note that
77 > stat_result.st_mtime will round
78 > + # up from 0.999999999 to 1.0 when precision is lost
79 > during conversion
80 > + # from nanosecond resolution to float.
81 > + max_mtime = None if existing_st is None else
82 > existing_st[stat.ST_MTIME]
83 > + for entry in entries:
84 > + if entry.type == 'DIST':
85 > + continue
86 > + abs_path = (os.path.join(self.pkgdir,
87 > 'files', entry.name) if
88 > + entry.type == 'AUX' else
89 > os.path.join(self.pkgdir, entry.name))
90 > + mtime = os.stat(abs_path)[stat.ST_MTIME]
91 > + if max_mtime is None or mtime > max_mtime:
92 > + max_mtime = mtime
93 > +
94 > + if max_mtime is not None:
95 > + os.utime(self.getFullname(), (max_mtime,
96 > max_mtime)) +
97 > def sign(self):
98 > """ Sign the Manifest """
99 > raise NotImplementedError()
100
101 looks fine :)
102 --
103 Brian Dolbec <dolsen>