Gentoo Archives: gentoo-portage-dev

From: Brian Dolbec <dolsen@g.o>
To: gentoo-portage-dev@l.g.o
Subject: Re: [gentoo-portage-dev] [PATCH] repos.conf: support sync-hooks-lazy attribute (bug 565172)
Date: Mon, 09 Nov 2015 01:44:47
Message-Id: 20151108174347.03559464.dolsen@gentoo.org
In Reply to: [gentoo-portage-dev] [PATCH] repos.conf: support sync-hooks-lazy attribute (bug 565172) by Zac Medico
1 On Sun, 8 Nov 2015 15:20:01 -0800
2 Zac Medico <zmedico@g.o> wrote:
3
4 > If sync-hooks-lazy is set to true, do not trigger postsync hooks
5 > unless hooks would have executed for a master repository or the
6 > repository has changed since the previous sync operation.
7 >
8 > If the user has not explicitly enabled sync-hooks-lazy in repos.conf,
9 > then execute all hooks regardless of whether or not anything has
10 > changed (for backward compatibility).
11 >
12 > X-Gentoo-Bug: 565172
13 > X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=565172
14 > ---
15 > man/portage.5 | 7 +++-
16 > pym/portage/emaint/modules/sync/sync.py | 57
17 > +++++++++++++++++++++++++++------
18 > pym/portage/repository/config.py | 6 ++--
19 > pym/portage/sync/controller.py | 17 ++++++---- 4 files
20 > changed, 69 insertions(+), 18 deletions(-)
21 >
22 > diff --git a/man/portage.5 b/man/portage.5
23 > index 8e2be4f..9ddbee8 100644
24 > --- a/man/portage.5
25 > +++ b/man/portage.5
26 > @@ -1,4 +1,4 @@
27 > -.TH "PORTAGE" "5" "Feb 2015" "Portage VERSION" "Portage"
28 > +.TH "PORTAGE" "5" "Nov 2015" "Portage VERSION" "Portage"
29 > .SH NAME
30 > portage \- the heart of Gentoo
31 > .SH "DESCRIPTION"
32 > @@ -968,6 +968,11 @@ Specifies CVS repository.
33 > Specifies clone depth to use for DVCS repositories. Defaults to 1
34 > (only the newest commit). If set to 0, the depth is unlimited.
35 > .TP
36 > +.B sync\-hooks\-lazy
37 > +If set to true, then sync of a given repository will not trigger
38 > postsync +hooks unless hooks would have executed for a master
39 > repository or the +repository has changed since the previous sync
40 > operation. +.TP
41 > .B sync\-type
42 > Specifies type of synchronization performed by `emerge \-\-sync`.
43 > .br
44 > diff --git a/pym/portage/emaint/modules/sync/sync.py
45 > b/pym/portage/emaint/modules/sync/sync.py index 57c779d..15d63e2
46 > 100644 --- a/pym/portage/emaint/modules/sync/sync.py
47 > +++ b/pym/portage/emaint/modules/sync/sync.py
48 > @@ -233,15 +233,17 @@ class SyncRepos(object):
49 > retvals = sync_scheduler.retvals
50 > msgs.extend(sync_scheduler.msgs)
51 >
52 > - # run the post_sync_hook one last time for
53 > - # run only at sync completion hooks
54 > - rcode = sync_manager.perform_post_sync_hook('')
55 > if retvals:
56 > msgs.extend(self.rmessage(retvals, 'sync'))
57 > else:
58 > msgs.extend(self.rmessage([('None',
59 > os.EX_OK)], 'sync'))
60 > - if rcode:
61 > - msgs.extend(self.rmessage([('None', rcode)],
62 > 'post-sync')) +
63 > + # run the post_sync_hook one last time for
64 > + # run only at sync completion hooks
65 > + if sync_scheduler.global_hooks_enabled:
66 > + rcode =
67 > sync_manager.perform_post_sync_hook('')
68 > + if rcode:
69 > + msgs.extend(self.rmessage([('None',
70 > rcode)], 'post-sync'))
71 > # Reload the whole config.
72 > portage._sync_mode = False
73 > @@ -339,6 +341,8 @@ class SyncScheduler(AsyncScheduler):
74 > if master.name in
75 > selected_repo_names: self._repo_map[master.name] = master
76 > self._sync_graph.add(master.name,
77 > repo.name)
78 > + self._complete_graph = self._sync_graph.copy()
79 > + self._hooks_repos = set()
80 > self._update_leaf_nodes()
81 >
82 > def _task_exit(self, task):
83 > @@ -347,9 +351,13 @@ class SyncScheduler(AsyncScheduler):
84 > more leaf nodes.
85 > '''
86 > self._running_tasks.discard(task)
87 > + # Set hooks_enabled = True by default, in order to
88 > ensure
89 > + # that hooks will be called in a backward-compatible
90 > manner
91 > + # even if all sync tasks have failed.
92 > + hooks_enabled = True
93 > returncode = task.returncode
94 > if task.returncode == os.EX_OK:
95 > - returncode, message, updatecache_flg =
96 > task.result
97 > + returncode, message, updatecache_flg,
98 > hooks_enabled = task.result if message:
99 > self.msgs.append(message)
100 > repo = task.kwargs['repo'].name
101 > @@ -357,8 +365,38 @@ class SyncScheduler(AsyncScheduler):
102 > self.retvals.append((repo, returncode))
103 > self._sync_graph.remove(repo)
104 > self._update_leaf_nodes()
105 > + if hooks_enabled:
106 > + self._hooks_repos.add(repo)
107 > super(SyncScheduler, self)._task_exit(self)
108 >
109 > + def _master_hooks(self, repo_name):
110 > + """
111 > + @param repo_name: a repo name
112 > + @type repo_name: str
113 > + @return: True if hooks would have been executed for
114 > any master
115 > + repositories of the given repo, False
116 > otherwise
117 > + @rtype: bool
118 > + """
119 > + traversed_nodes = set()
120 > + node_stack = [repo_name]
121 > + while node_stack:
122 > + node = node_stack.pop()
123 > + if node in self._hooks_repos:
124 > + return True
125 > + if node not in traversed_nodes:
126 > + traversed_nodes.add(node)
127 > +
128 > node_stack.extend(self._complete_graph.child_nodes(node))
129 > + return False
130 > +
131 > + @property
132 > + def global_hooks_enabled(self):
133 > + """
134 > + @return: True if repo.postsync.d hooks would have
135 > been executed
136 > + for any repositories.
137 > + @rtype: bool
138 > + """
139 > + return bool(self._hooks_repos)
140 > +
141 > def _update_leaf_nodes(self):
142 > '''
143 > Populate self._leaf_nodes with current leaves from
144 > @@ -389,9 +427,10 @@ class SyncScheduler(AsyncScheduler):
145 > self._running_repos.add(node)
146 > self._update_leaf_nodes()
147 >
148 > - task = self._sync_manager.async(
149 > - self._emerge_config, self._repo_map[node])
150 > - return task
151 > + return self._sync_manager.async(
152 > + emerge_config=self._emerge_config,
153 > + repo=self._repo_map[node],
154 > + master_hooks=self._master_hooks(node))
155 >
156 > def _can_add_job(self):
157 > '''
158 > diff --git a/pym/portage/repository/config.py
159 > b/pym/portage/repository/config.py index 1060bc7..c7a1a1a 100644
160 > --- a/pym/portage/repository/config.py
161 > +++ b/pym/portage/repository/config.py
162 > @@ -87,7 +87,7 @@ class RepoConfig(object):
163 > 'main_repo', 'manifest_hashes', 'masters',
164 > 'missing_repo_name', 'name', 'portage1_profiles',
165 > 'portage1_profiles_compat', 'priority', 'profile_formats',
166 > 'sign_commit', 'sign_manifest',
167 > - 'sync_depth',
168 > + 'sync_depth', 'sync_hooks_lazy',
169 > 'sync_type', 'sync_umask', 'sync_uri', 'sync_user',
170 > 'thin_manifest', 'update_changelog', 'user_location', '_eapis_banned',
171 > '_eapis_deprecated', '_masters_orig',
172 > 'module_specific_options', @@ -175,6 +175,8 @@ class
173 > RepoConfig(object): self.auto_sync = auto_sync
174 >
175 > self.sync_depth = repo_opts.get('sync-depth')
176 > + self.sync_hooks_lazy =
177 > repo_opts.get('sync-hooks-lazy',
178 > + 'false').lower() == 'true'
179 >
180 > self.module_specific_options = {}
181 >
182 > @@ -506,7 +508,7 @@ class RepoConfigLoader(object):
183 > # repos.conf is
184 > allowed to override. for k in ('aliases', 'auto_sync',
185 > 'eclass_overrides', 'force', 'masters', 'priority',
186 > - 'sync_depth',
187 > + 'sync_depth',
188 > 'sync_hooks_lazy', 'sync_type', 'sync_umask', 'sync_uri', 'sync_user',
189 > 'module_specific_options'):
190 > v =
191 > getattr(repos_conf_opts, k, None) diff --git
192 > a/pym/portage/sync/controller.py b/pym/portage/sync/controller.py
193 > index e8132c2..57add91 100644 --- a/pym/portage/sync/controller.py
194 > +++ b/pym/portage/sync/controller.py
195 > @@ -114,16 +114,17 @@ class SyncManager(object):
196 > return desc
197 > return []
198 >
199 > - def async(self, emerge_config=None, repo=None):
200 > + def async(self, emerge_config=None, repo=None,
201 > master_hooks=True): self.emerge_config = emerge_config
202 > self.settings, self.trees, self.mtimedb =
203 > emerge_config self.xterm_titles = "notitles" not in
204 > self.settings.features self.portdb =
205 > self.trees[self.settings['EROOT']]['porttree'].dbapi return
206 > SyncRepo(sync_task=AsyncFunction(target=self.sync,
207 > - kwargs=dict(emerge_config=emerge_config,
208 > repo=repo)),
209 > + kwargs=dict(emerge_config=emerge_config,
210 > repo=repo,
211 > + master_hooks=master_hooks)),
212 > sync_callback=self._sync_callback)
213 >
214 > - def sync(self, emerge_config=None, repo=None):
215 > + def sync(self, emerge_config=None, repo=None,
216 > master_hooks=True): self.callback = None
217 > self.repo = repo
218 > self.exitcode = 1
219 > @@ -156,9 +157,13 @@ class SyncManager(object):
220 > taskmaster = TaskHandler(callback=self.do_callback)
221 > taskmaster.run_tasks(tasks, func, status,
222 > options=task_opts)
223 > - self.perform_post_sync_hook(repo.name,
224 > repo.sync_uri, repo.location)
225 > + hooks_enabled = False
226 > + if master_hooks or not repo.sync_hooks_lazy or
227 > self.updatecache_flg:
228 > + hooks_enabled = True
229 > + self.perform_post_sync_hook(
230 > + repo.name, repo.sync_uri,
231 > repo.location)
232 > - return self.exitcode, None, self.updatecache_flg
233 > + return self.exitcode, None, self.updatecache_flg,
234 > hooks_enabled
235 >
236 > def do_callback(self, result):
237 > @@ -328,7 +333,7 @@ class SyncManager(object):
238 > exitcode = proc.returncode
239 > updatecache_flg = False
240 > if proc.returncode == os.EX_OK:
241 > - exitcode, message, updatecache_flg =
242 > proc.result
243 > + exitcode, message, updatecache_flg,
244 > hooks_enabled = proc.result
245 > if updatecache_flg and "metadata-transfer" not in
246 > self.settings.features: updatecache_flg = False
247
248
249 The code changes look good to me :)
250
251 --
252 Brian Dolbec <dolsen>