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 |