Gentoo Archives: gentoo-commits

From: "Zac Medico (zmedico)" <zmedico@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] portage r12303 - main/trunk/pym/_emerge
Date: Thu, 25 Dec 2008 00:31:49
Message-Id: E1LFe8g-0000DG-5V@stork.gentoo.org
1 Author: zmedico
2 Date: 2008-12-25 00:31:45 +0000 (Thu, 25 Dec 2008)
3 New Revision: 12303
4
5 Modified:
6 main/trunk/pym/_emerge/__init__.py
7 Log:
8 Add support for synchronizing ebuild and eclass timestamps with the metadata
9 cache timestamps which emerge --sync operates on a git repository. This is
10 necessary since git doesn't preserve timestamps. It is assumed that the
11 timestamps should be synchronized if the relevant ebuilds and eclasses are
12 unmodified relative to the HEAD commit (as reported by git-ls-files). This
13 feature was requested by Daniel Robbins, so that it's possible for the funtoo
14 git repository to distribute pre-generated metadata.
15
16
17 Modified: main/trunk/pym/_emerge/__init__.py
18 ===================================================================
19 --- main/trunk/pym/_emerge/__init__.py 2008-12-24 22:49:37 UTC (rev 12302)
20 +++ main/trunk/pym/_emerge/__init__.py 2008-12-25 00:31:45 UTC (rev 12303)
21 @@ -11803,6 +11803,7 @@
22 vcs_dirs = vcs_dirs.intersection(os.listdir(myportdir))
23
24 os.umask(0022)
25 + dosyncuri = syncuri
26 updatecache_flg = False
27 if myaction == "metadata":
28 print "skipping sync"
29 @@ -11825,7 +11826,9 @@
30 msg = ">>> Git pull in %s successful" % myportdir
31 emergelog(xterm_titles, msg)
32 writemsg_level(msg + "\n")
33 - return exitcode
34 + exitcode = git_sync_timestamps(settings, myportdir)
35 + if exitcode == os.EX_OK:
36 + updatecache_flg = True
37 elif syncuri[:8]=="rsync://":
38 for vcs_dir in vcs_dirs:
39 writemsg_level(("!!! %s appears to be under revision " + \
40 @@ -12248,6 +12251,138 @@
41 display_news_notification(root_config, myopts)
42 return os.EX_OK
43
44 +def git_sync_timestamps(settings, portdir):
45 + """
46 + Since git doesn't preserve timestamps, synchronize timestamps between
47 + entries and ebuilds/eclasses. Assume the cache has the correct timestamp
48 + for a given file as long as the file in the working tree is not modified
49 + (relative to HEAD).
50 + """
51 + cache_dir = os.path.join(portdir, "metadata", "cache")
52 + if not os.path.isdir(cache_dir):
53 + return os.EX_OK
54 + writemsg_level(">>> Synchronizing timestamps...\n")
55 +
56 + from portage.cache.cache_errors import CacheError
57 + try:
58 + cache_db = settings.load_best_module("portdbapi.metadbmodule")(
59 + portdir, "metadata/cache", portage.auxdbkeys[:], readonly=True)
60 + except CacheError, e:
61 + writemsg_level("!!! Unable to instantiate cache: %s\n" % (e,),
62 + level=logging.ERROR, noiselevel=-1)
63 + return 1
64 +
65 + ec_dir = os.path.join(portdir, "eclass")
66 + try:
67 + ec_names = set(f[:-7] for f in os.listdir(ec_dir) \
68 + if f.endswith(".eclass"))
69 + except OSError, e:
70 + writemsg_level("!!! Unable to list eclasses: %s\n" % (e,),
71 + level=logging.ERROR, noiselevel=-1)
72 + return 1
73 +
74 + args = [portage.const.BASH_BINARY, "-c",
75 + "cd %s && git ls-files -m --with-tree=HEAD" % \
76 + portage._shell_quote(portdir)]
77 + import subprocess
78 + proc = subprocess.Popen(args, stdout=subprocess.PIPE)
79 + modified_files = set(l.rstrip("\n") for l in proc.stdout)
80 + rval = proc.wait()
81 + if rval != os.EX_OK:
82 + return rval
83 +
84 + modified_eclasses = set(ec for ec in ec_names \
85 + if os.path.join("eclass", ec + ".eclass") in modified_files)
86 +
87 + updated_ec_mtimes = {}
88 +
89 + for cpv in cache_db:
90 + cpv_split = portage.catpkgsplit(cpv)
91 + if cpv_split is None:
92 + writemsg_level("!!! Invalid cache entry: %s\n" % (cpv,),
93 + level=logging.ERROR, noiselevel=-1)
94 + continue
95 +
96 + cat, pn, ver, rev = cpv_split
97 + cat, pf = portage.catsplit(cpv)
98 + relative_eb_path = os.path.join(cat, pn, pf + ".ebuild")
99 + if relative_eb_path in modified_files:
100 + continue
101 +
102 + try:
103 + cache_entry = cache_db[cpv]
104 + eb_mtime = cache_entry.get("_mtime_")
105 + ec_mtimes = cache_entry.get("_eclasses_")
106 + except KeyError:
107 + writemsg_level("!!! Missing cache entry: %s\n" % (cpv,),
108 + level=logging.ERROR, noiselevel=-1)
109 + continue
110 + except CacheError, e:
111 + writemsg_level("!!! Unable to access cache entry: %s %s\n" % \
112 + (cpv, e), level=logging.ERROR, noiselevel=-1)
113 + continue
114 +
115 + if eb_mtime is None:
116 + writemsg_level("!!! Missing ebuild mtime: %s\n" % (cpv,),
117 + level=logging.ERROR, noiselevel=-1)
118 + continue
119 +
120 + try:
121 + eb_mtime = long(eb_mtime)
122 + except ValueError:
123 + writemsg_level("!!! Invalid ebuild mtime: %s %s\n" % \
124 + (cpv, eb_mtime), level=logging.ERROR, noiselevel=-1)
125 + continue
126 +
127 + if ec_mtimes is None:
128 + writemsg_level("!!! Missing eclass mtimes: %s\n" % (cpv,),
129 + level=logging.ERROR, noiselevel=-1)
130 + continue
131 +
132 + if modified_eclasses.intersection(ec_mtimes):
133 + continue
134 +
135 + missing_eclasses = set(ec_mtimes).difference(ec_names)
136 + if missing_eclasses:
137 + writemsg_level("!!! Non-existent eclass(es): %s %s\n" % \
138 + (cpv, sorted(missing_eclasses)), level=logging.ERROR,
139 + noiselevel=-1)
140 + continue
141 +
142 + eb_path = os.path.join(portdir, relative_eb_path)
143 + try:
144 + current_eb_mtime = os.stat(eb_path)
145 + except OSError:
146 + writemsg_level("!!! Missing ebuild: %s\n" % \
147 + (cpv,), level=logging.ERROR, noiselevel=-1)
148 + continue
149 +
150 + inconsistent = False
151 + for ec, (ec_path, ec_mtime) in ec_mtimes.iteritems():
152 + updated_mtime = updated_ec_mtimes.get(ec)
153 + if updated_mtime is not None and updated_mtime != ec_mtime:
154 + writemsg_level("!!! Inconsistend eclass mtime: %s %s\n" % \
155 + (cpv, ec), level=logging.ERROR, noiselevel=-1)
156 + inconsistent = True
157 + break
158 +
159 + if inconsistent:
160 + continue
161 +
162 + if current_eb_mtime != eb_mtime:
163 + os.utime(eb_path, (eb_mtime, eb_mtime))
164 +
165 + for ec, (ec_path, ec_mtime) in ec_mtimes.iteritems():
166 + if ec in updated_ec_mtimes:
167 + continue
168 + ec_path = os.path.join(ec_dir, ec + ".eclass")
169 + current_mtime = long(os.stat(ec_path).st_mtime)
170 + if current_mtime != ec_mtime:
171 + os.utime(ec_path, (ec_mtime, ec_mtime))
172 + updated_ec_mtimes[ec] = ec_mtime
173 +
174 + return os.EX_OK
175 +
176 def action_metadata(settings, portdb, myopts):
177 portage.writemsg_stdout("\n>>> Updating Portage cache: ")
178 old_umask = os.umask(0002)