Gentoo Archives: gentoo-portage-dev

From: Zac Medico <zmedico@g.o>
To: gentoo-portage-dev@l.g.o
Cc: Zac Medico <zmedico@g.o>
Subject: [gentoo-portage-dev] [PATCH] Add --sync-submodule <glsa|news|profiles> (534070)
Date: Wed, 31 Dec 2014 08:07:40
Message-Id: 1420013239-22660-1-git-send-email-zmedico@gentoo.org
1 This adds support for a new --sync-submodule option to both emerge and
2 emaint. When this option is used with the sync action, only the selected
3 submodules are synced. Each submodule is referenced using an abstract
4 identifier, which serves to hide the implementation details involving
5 the precise locations of specific submodules within each repository.
6
7 Currently, --sync-submodule has no effect for sync protocols other than
8 rsync, but the new SyncBase._get_submodule_paths() method will be useful
9 for implementing support in other SyncBase subclasses.
10
11 X-Gentoo-Bug: 534070
12 X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=534070
13 ---
14 man/emaint.1 | 9 ++++++++-
15 man/emerge.1 | 7 +++++++
16 pym/_emerge/main.py | 7 +++++++
17 pym/portage/emaint/main.py | 12 +++++++++++-
18 pym/portage/emaint/modules/sync/__init__.py | 10 ++++++++++
19 pym/portage/emaint/modules/sync/sync.py | 19 +++++++++++++++----
20 pym/portage/module.py | 15 +++++++++++++++
21 pym/portage/sync/modules/rsync/rsync.py | 16 +++++++++++++++-
22 pym/portage/sync/syncbase.py | 14 +++++++++++++-
23 9 files changed, 101 insertions(+), 8 deletions(-)
24
25 diff --git a/man/emaint.1 b/man/emaint.1
26 index f02bc68..67e05f1 100644
27 --- a/man/emaint.1
28 +++ b/man/emaint.1
29 @@ -1,4 +1,4 @@
30 -.TH "EMAINT" "1" "Nov 2008" "Portage VERSION" "Portage"
31 +.TH "EMAINT" "1" "Dec 2014" "Portage VERSION" "Portage"
32 .SH NAME
33 emaint \- performs system health checks and maintenance
34 .SH SYNOPSIS
35 @@ -71,6 +71,13 @@ Sync all repositories which have a sync\-uri specified. (sync command only)
36 .TP
37 .B \-r, \-\-repo REPO
38 Sync the repository specified. (sync command only)
39 +.TP
40 +.BR "\-\-sync-submodule <glsa|news|profiles>"
41 +Restrict sync to the specified submodule(s). This option may be
42 +specified multiple times, in order to sync multiple submodules.
43 +Currently, this option has no effect for sync protocols other
44 +than rsync.
45 +(sync command only)
46 .SH "REPORTING BUGS"
47 Please report bugs via http://bugs.gentoo.org/
48 .SH AUTHORS
49 diff --git a/man/emerge.1 b/man/emerge.1
50 index faa1f33..3d4042c 100644
51 --- a/man/emerge.1
52 +++ b/man/emerge.1
53 @@ -836,6 +836,13 @@ remaining packages and any that have unsatisfied dependencies or are
54 masked will be automatically dropped. Also see the related
55 \fB\-\-keep\-going\fR option.
56 .TP
57 +.BR "\-\-sync\-submodule <glsa|news|profiles>"
58 +Restrict sync to the specified submodule(s). This option may be
59 +specified multiple times, in order to sync multiple submodules.
60 +Currently, this option has no effect for sync protocols other
61 +than rsync.
62 +(--sync action only)
63 +.TP
64 .BR "\-\-tree " (\fB\-t\fR)
65 Shows the dependency tree for the given target by indenting dependencies.
66 This is only really useful in combination with \fB\-\-emptytree\fR or
67 diff --git a/pym/_emerge/main.py b/pym/_emerge/main.py
68 index 7c707f9..695a732 100644
69 --- a/pym/_emerge/main.py
70 +++ b/pym/_emerge/main.py
71 @@ -633,6 +633,13 @@ def parse_opts(tmpcmdline, silent=False):
72 "choices" : true_y_or_n
73 },
74
75 + "--sync-submodule": {
76 + "help" : ("Restrict sync to the specified submodule(s)."
77 + " (--sync action only)"),
78 + "choices" : ("glsa", "news", "profiles"),
79 + "action" : "append",
80 + },
81 +
82 "--use-ebuild-visibility": {
83 "help" : "use unbuilt ebuild metadata for visibility checks on built packages",
84 "choices" : true_y_or_n
85 diff --git a/pym/portage/emaint/main.py b/pym/portage/emaint/main.py
86 index fea4832..25a7706 100644
87 --- a/pym/portage/emaint/main.py
88 +++ b/pym/portage/emaint/main.py
89 @@ -34,6 +34,7 @@ class OptionItem(object):
90 self.action = opt.get('action')
91 self.type = opt.get('type')
92 self.dest = opt.get('dest')
93 + self.choices = opt.get('choices')
94
95 @property
96 def pargs(self):
97 @@ -58,6 +59,8 @@ class OptionItem(object):
98 kwargs['type'] = self.type
99 if self.dest is not None:
100 kwargs['dest'] = self.dest
101 + if self.choices is not None:
102 + kwargs['choices'] = self.choices
103 return kwargs
104
105 def usage(module_controller):
106 @@ -89,7 +92,10 @@ def module_opts(module_controller, module):
107 opts = DEFAULT_OPTIONS
108 for opt in sorted(opts):
109 optd = opts[opt]
110 - opto = " %s, %s" % (optd['short'], optd['long'])
111 + if 'short' in optd:
112 + opto = " %s, %s" % (optd['short'], optd['long'])
113 + else:
114 + opto = " %s" % (optd['long'],)
115 _usage += '%s %s\n' % (opto.ljust(15), optd['help'])
116 _usage += '\n'
117 return _usage
118 @@ -174,6 +180,10 @@ def emaint_main(myargv):
119 if desc:
120 for opt in desc:
121 parser_options.append(OptionItem(desc[opt]))
122 + desc = module_controller.get_opt_descriptions(mod)
123 + if desc:
124 + for opt in desc:
125 + parser_options.append(OptionItem(desc[opt]))
126 for opt in parser_options:
127 parser.add_argument(*opt.pargs, **opt.kwargs)
128
129 diff --git a/pym/portage/emaint/modules/sync/__init__.py b/pym/portage/emaint/modules/sync/__init__.py
130 index 32469b5..bc6dc5f 100644
131 --- a/pym/portage/emaint/modules/sync/__init__.py
132 +++ b/pym/portage/emaint/modules/sync/__init__.py
133 @@ -37,6 +37,16 @@ module_spec = {
134 'dest': 'auto',
135 'func': 'auto_sync',
136 },
137 + },
138 + 'opt_desc': {
139 + 'sync-submodule': {
140 + "long": "--sync-submodule",
141 + "help": ("(sync module only): Restrict sync "
142 + "to the specified submodule(s)"),
143 + "choices": ("glsa", "news", "profiles"),
144 + "action": "append",
145 + "dest": "sync_submodule",
146 + },
147 }
148 }
149 }
150 diff --git a/pym/portage/emaint/modules/sync/sync.py b/pym/portage/emaint/modules/sync/sync.py
151 index 77c685c..c6aef95 100644
152 --- a/pym/portage/emaint/modules/sync/sync.py
153 +++ b/pym/portage/emaint/modules/sync/sync.py
154 @@ -90,7 +90,8 @@ class SyncRepos(object):
155 return_messages = options.get('return-messages', False)
156 else:
157 return_messages = False
158 - return self._sync(selected, return_messages)
159 + return self._sync(selected, return_messages,
160 + emaint_opts=options)
161
162
163 def all_repos(self, **kwargs):
164 @@ -101,7 +102,8 @@ class SyncRepos(object):
165 return_messages = options.get('return-messages', False)
166 else:
167 return_messages = False
168 - return self._sync(selected, return_messages)
169 + return self._sync(selected, return_messages,
170 + emaint_opts=options)
171
172
173 def repo(self, **kwargs):
174 @@ -123,7 +125,8 @@ class SyncRepos(object):
175 if return_messages:
176 return msgs
177 return
178 - return self._sync(selected, return_messages)
179 + return self._sync(selected, return_messages,
180 + emaint_opts=options)
181
182
183 @staticmethod
184 @@ -189,7 +192,15 @@ class SyncRepos(object):
185 return selected
186
187
188 - def _sync(self, selected_repos, return_messages):
189 + def _sync(self, selected_repos, return_messages,
190 + emaint_opts=None):
191 +
192 + if emaint_opts is not None:
193 + for k, v in emaint_opts.items():
194 + if v is not None:
195 + k = "--" + k.replace("_", "-")
196 + self.emerge_config.opts[k] = v
197 +
198 msgs = []
199 if not selected_repos:
200 msgs.append("Emaint sync, nothing to sync... returning")
201 diff --git a/pym/portage/module.py b/pym/portage/module.py
202 index a78bb2e..e40a548 100644
203 --- a/pym/portage/module.py
204 +++ b/pym/portage/module.py
205 @@ -179,3 +179,18 @@ class Modules(object):
206 raise InvalidModuleName("Module name '%s' was invalid or not"
207 %modname + "found")
208 return desc
209 +
210 + def get_opt_descriptions(self, modname):
211 + """Retrieves the module class exported options descriptions
212 +
213 + @type modname: string
214 + @param modname: the module class name
215 + @type dictionary
216 + @return: the modules class exported options descriptions
217 + """
218 + if modname and modname in self.module_names:
219 + desc = self._modules[modname].get('opt_desc')
220 + else:
221 + raise InvalidModuleName(
222 + "Module name '%s' was invalid or not found" % modname)
223 + return desc
224 diff --git a/pym/portage/sync/modules/rsync/rsync.py b/pym/portage/sync/modules/rsync/rsync.py
225 index 74c10e7..900351d 100644
226 --- a/pym/portage/sync/modules/rsync/rsync.py
227 +++ b/pym/portage/sync/modules/rsync/rsync.py
228 @@ -488,7 +488,21 @@ class RsyncSync(SyncBase):
229 exitcode = SERVER_OUT_OF_DATE
230 elif (servertimestamp == 0) or (servertimestamp > timestamp):
231 # actual sync
232 - command = rsynccommand + [syncuri+"/", self.repo.location]
233 + command = rsynccommand[:]
234 + submodule_paths = self._get_submodule_paths()
235 + if submodule_paths:
236 + # The only way to select multiple directories to
237 + # sync, without calling rsync multiple times, is
238 + # to use --relative.
239 + command.append("--relative")
240 + for path in submodule_paths:
241 + # /./ is special syntax supported with the
242 + # rsync --relative option.
243 + command.append(syncuri + "/./" + path)
244 + command.append(self.repo.location)
245 + else:
246 + command.extend([syncuri + "/", self.repo.location])
247 +
248 exitcode = None
249 try:
250 exitcode = portage.process.spawn(command,
251 diff --git a/pym/portage/sync/syncbase.py b/pym/portage/sync/syncbase.py
252 index 94d4aab..fcde51f 100644
253 --- a/pym/portage/sync/syncbase.py
254 +++ b/pym/portage/sync/syncbase.py
255 @@ -12,6 +12,11 @@ import os
256 import portage
257 from portage.util import writemsg_level
258
259 +_SUBMODULE_PATH_MAP = {
260 + 'glsa': 'metadata/glsa',
261 + 'news': 'metadata/news',
262 + 'profiles': 'profiles',
263 +}
264
265 class SyncBase(object):
266 '''Base Sync class for subclassing'''
267 @@ -57,7 +62,6 @@ class SyncBase(object):
268 self.xterm_titles = self.options.get('xterm_titles', False)
269 self.spawn_kwargs = self.options.get('spawn_kwargs', None)
270
271 -
272 def exists(self, **kwargs):
273 '''Tests whether the repo actually exists'''
274 if kwargs:
275 @@ -100,3 +104,11 @@ class SyncBase(object):
276 # and portdb properly account for its existence.
277 '''
278 pass
279 +
280 + def _get_submodule_paths(self):
281 + paths = []
282 + emerge_config = self.options.get('emerge_config')
283 + if emerge_config is not None:
284 + for name in emerge_config.opts.get('--sync-submodule', []):
285 + paths.append(_SUBMODULE_PATH_MAP[name])
286 + return tuple(paths)
287 --
288 2.0.5

Replies