1 |
commit: 82b99bbdb1dcc6327d80dc4b07f878ca14177080 |
2 |
Author: Brian Dolbec <dolsen <AT> gentoo <DOT> org> |
3 |
AuthorDate: Mon Apr 21 18:30:00 2014 +0000 |
4 |
Commit: Brian Dolbec <brian.dolbec <AT> gmail <DOT> com> |
5 |
CommitDate: Tue Sep 30 00:42:25 2014 +0000 |
6 |
URL: http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=82b99bbd |
7 |
|
8 |
emaint/modules: New emaint module "sync" |
9 |
|
10 |
This code is a migration from _emerge.actions.action_sync. |
11 |
The code has been split up into logical blocks. |
12 |
Some changes have been made to handle multiple repositories better. |
13 |
It also adds more flexibility as to what is synced. |
14 |
|
15 |
--- |
16 |
pym/portage/emaint/modules/sync/__init__.py | 44 ++++++ |
17 |
pym/portage/emaint/modules/sync/sync.py | 237 ++++++++++++++++++++++++++++ |
18 |
2 files changed, 281 insertions(+) |
19 |
|
20 |
diff --git a/pym/portage/emaint/modules/sync/__init__.py b/pym/portage/emaint/modules/sync/__init__.py |
21 |
new file mode 100644 |
22 |
index 0000000..4070200 |
23 |
--- /dev/null |
24 |
+++ b/pym/portage/emaint/modules/sync/__init__.py |
25 |
@@ -0,0 +1,44 @@ |
26 |
+# Copyright 2014 Gentoo Foundation |
27 |
+# Distributed under the terms of the GNU General Public License v2 |
28 |
+ |
29 |
+"""Check repos.conf settings and sync repositories. |
30 |
+""" |
31 |
+ |
32 |
+ |
33 |
+module_spec = { |
34 |
+ 'name': 'sync', |
35 |
+ 'description': __doc__, |
36 |
+ 'provides':{ |
37 |
+ 'sync-module': { |
38 |
+ 'name': "sync", |
39 |
+ 'class': "SyncRepos", |
40 |
+ 'description': __doc__, |
41 |
+ 'functions': ['allrepos', 'auto', 'repo'], |
42 |
+ 'func_desc': { |
43 |
+ 'repo': { |
44 |
+ "short": "-r", "long": "--repo", |
45 |
+ "help": "(sync module only): -r, --repo Sync the specified repo", |
46 |
+ 'status': "Syncing %s", |
47 |
+ 'action': 'store', |
48 |
+ 'func': 'repo', |
49 |
+ }, |
50 |
+ 'allrepos': { |
51 |
+ "short": "-A", "long": "--allrepos", |
52 |
+ "help": "(sync module only): -A, --allrepos Sync all repos that have a sync-url defined", |
53 |
+ 'status': "Syncing %s", |
54 |
+ 'action': 'store_true', |
55 |
+ 'dest': 'allrepos', |
56 |
+ 'func': 'all_repos', |
57 |
+ }, |
58 |
+ 'auto': { |
59 |
+ "short": "-a", "long": "--auto", |
60 |
+ "help": "(sync module only): -a, --auto Sync auto-sync enabled repos only", |
61 |
+ 'status': "Syncing %s", |
62 |
+ 'action': 'store_true', |
63 |
+ 'dest': 'auto', |
64 |
+ 'func': 'auto_sync', |
65 |
+ }, |
66 |
+ } |
67 |
+ } |
68 |
+ } |
69 |
+ } |
70 |
|
71 |
diff --git a/pym/portage/emaint/modules/sync/sync.py b/pym/portage/emaint/modules/sync/sync.py |
72 |
new file mode 100644 |
73 |
index 0000000..3aa318a |
74 |
--- /dev/null |
75 |
+++ b/pym/portage/emaint/modules/sync/sync.py |
76 |
@@ -0,0 +1,237 @@ |
77 |
+# Copyright 2014 Gentoo Foundation |
78 |
+# Distributed under the terms of the GNU General Public License v2 |
79 |
+ |
80 |
+import logging |
81 |
+import os |
82 |
+import sys |
83 |
+ |
84 |
+import portage |
85 |
+from portage.localization import _ |
86 |
+from portage.output import bold, create_color_func |
87 |
+from portage.sync import get_syncer |
88 |
+from portage._global_updates import _global_updates |
89 |
+from portage.util import writemsg_level |
90 |
+ |
91 |
+import _emerge |
92 |
+from _emerge.emergelog import emergelog |
93 |
+ |
94 |
+ |
95 |
+portage.proxy.lazyimport.lazyimport(globals(), |
96 |
+ '_emerge.actions:adjust_configs,load_emerge_config', |
97 |
+ '_emerge.chk_updated_cfg_files:chk_updated_cfg_files', |
98 |
+ '_emerge.main:parse_opts', |
99 |
+ '_emerge.post_emerge:display_news_notification', |
100 |
+) |
101 |
+ |
102 |
+warn = create_color_func("WARN") |
103 |
+ |
104 |
+if sys.hexversion >= 0x3000000: |
105 |
+ _basestring = str |
106 |
+else: |
107 |
+ _basestring = basestring |
108 |
+ |
109 |
+ |
110 |
+class SyncRepos(object): |
111 |
+ |
112 |
+ short_desc = "Check repos.conf settings and/or sync repositories" |
113 |
+ |
114 |
+ @staticmethod |
115 |
+ def name(): |
116 |
+ return "sync" |
117 |
+ |
118 |
+ |
119 |
+ def can_progressbar(self, func): |
120 |
+ return False |
121 |
+ |
122 |
+ |
123 |
+ def __init__(self, emerge_config=None, emerge_logging=False): |
124 |
+ '''Class init function |
125 |
+ |
126 |
+ @param emerge_config: optional an emerge_config instance to use |
127 |
+ @param emerge_logging: boolean, defaults to False |
128 |
+ ''' |
129 |
+ if emerge_config: |
130 |
+ self.emerge_config = emerge_config |
131 |
+ else: |
132 |
+ # need a basic options instance |
133 |
+ actions, opts, _files = parse_opts([], silent=True) |
134 |
+ self.emerge_config = load_emerge_config( |
135 |
+ action='sync', args=_files, trees=[], opts=opts) |
136 |
+ if emerge_logging: |
137 |
+ _emerge.emergelog._disable = False |
138 |
+ self.xterm_titles = "notitles" not in \ |
139 |
+ self.emerge_config.target_config.settings.features |
140 |
+ emergelog(self.xterm_titles, " === sync") |
141 |
+ |
142 |
+ |
143 |
+ def auto_sync(self, **kwargs): |
144 |
+ '''Sync auto-sync enabled repos''' |
145 |
+ options = kwargs.get('options', None) |
146 |
+ selected = self._get_repos(True) |
147 |
+ if options.get('return-messages', False): |
148 |
+ return self.rmessage(self._sync(selected), 'sync') |
149 |
+ return self._sync(selected) |
150 |
+ |
151 |
+ |
152 |
+ def all_repos(self, **kwargs): |
153 |
+ '''Sync all repos defined in repos.conf''' |
154 |
+ selected = self._get_repos(auto_sync_only=False) |
155 |
+ options = kwargs.get('options', None) |
156 |
+ if options.get('return-messages', False): |
157 |
+ return self.rmessage( |
158 |
+ self._sync(selected), |
159 |
+ 'sync') |
160 |
+ return self._sync(selected) |
161 |
+ |
162 |
+ |
163 |
+ def repo(self, **kwargs): |
164 |
+ '''Sync the specified repo''' |
165 |
+ options = kwargs.get('options', None) |
166 |
+ if options: |
167 |
+ repos = options.get('repo', '') |
168 |
+ return_messages = options.get('return-messages', False) |
169 |
+ else: |
170 |
+ return_messages = False |
171 |
+ if isinstance(repos, _basestring): |
172 |
+ repos = repos.split() |
173 |
+ available = self._get_repos(auto_sync_only=False) |
174 |
+ selected = self._match_repos(repos, available) |
175 |
+ if return_messages: |
176 |
+ return self.rmessage(self._sync(selected), 'sync') |
177 |
+ return self._sync(selected) |
178 |
+ |
179 |
+ |
180 |
+ @staticmethod |
181 |
+ def _match_repos(repos, available): |
182 |
+ '''Internal search, matches up the repo.name in repos |
183 |
+ |
184 |
+ @param repos: list, of repo names to match |
185 |
+ @param avalable: list of repo objects to search |
186 |
+ @return: list of repo objects that match |
187 |
+ ''' |
188 |
+ selected = [] |
189 |
+ for repo in available: |
190 |
+ if repo.name in repos: |
191 |
+ selected.append(repo) |
192 |
+ return selected |
193 |
+ |
194 |
+ |
195 |
+ def _get_repos(self, auto_sync_only=True): |
196 |
+ selected_repos = [] |
197 |
+ unknown_repo_names = [] |
198 |
+ missing_sync_type = [] |
199 |
+ if self.emerge_config.args: |
200 |
+ for repo_name in self.emerge_config.args: |
201 |
+ print("_get_repos(): repo_name =", repo_name) |
202 |
+ try: |
203 |
+ repo = self.emerge_config.target_config.settings.repositories[repo_name] |
204 |
+ except KeyError: |
205 |
+ unknown_repo_names.append(repo_name) |
206 |
+ else: |
207 |
+ selected_repos.append(repo) |
208 |
+ if repo.sync_type is None: |
209 |
+ missing_sync_type.append(repo) |
210 |
+ |
211 |
+ if unknown_repo_names: |
212 |
+ writemsg_level("!!! %s\n" % _("Unknown repo(s): %s") % |
213 |
+ " ".join(unknown_repo_names), |
214 |
+ level=logging.ERROR, noiselevel=-1) |
215 |
+ |
216 |
+ if missing_sync_type: |
217 |
+ writemsg_level("!!! %s\n" % |
218 |
+ _("Missing sync-type for repo(s): %s") % |
219 |
+ " ".join(repo.name for repo in missing_sync_type), |
220 |
+ level=logging.ERROR, noiselevel=-1) |
221 |
+ |
222 |
+ if unknown_repo_names or missing_sync_type: |
223 |
+ print("missing or unknown repos... returning") |
224 |
+ return [] |
225 |
+ |
226 |
+ else: |
227 |
+ selected_repos.extend(self.emerge_config.target_config.settings.repositories) |
228 |
+ #print("_get_repos(), selected =", selected_repos) |
229 |
+ if auto_sync_only: |
230 |
+ return self._filter_auto(selected_repos) |
231 |
+ return selected_repos |
232 |
+ |
233 |
+ |
234 |
+ def _filter_auto(self, repos): |
235 |
+ selected = [] |
236 |
+ for repo in repos: |
237 |
+ if repo.auto_sync in ['yes', 'true']: |
238 |
+ selected.append(repo) |
239 |
+ return selected |
240 |
+ |
241 |
+ |
242 |
+ def _sync(self, selected_repos): |
243 |
+ if not selected_repos: |
244 |
+ print("_sync(), nothing to sync... returning") |
245 |
+ return [('None', os.EX_OK)] |
246 |
+ # Portage needs to ensure a sane umask for the files it creates. |
247 |
+ os.umask(0o22) |
248 |
+ portage._sync_mode = True |
249 |
+ |
250 |
+ sync_manager = get_syncer(self.emerge_config.target_config.settings, emergelog) |
251 |
+ retvals = [] |
252 |
+ for repo in selected_repos: |
253 |
+ print("syncing repo:", repo.name) |
254 |
+ if repo.sync_type is not None: |
255 |
+ returncode = sync_manager.sync(self.emerge_config, repo) |
256 |
+ #if returncode != os.EX_OK: |
257 |
+ retvals.append((repo.name, returncode)) |
258 |
+ |
259 |
+ # Reload the whole config. |
260 |
+ portage._sync_mode = False |
261 |
+ self._reload_config() |
262 |
+ self._do_pkg_moves() |
263 |
+ self._check_updates() |
264 |
+ display_news_notification(self.emerge_config.target_config, |
265 |
+ self.emerge_config.opts) |
266 |
+ if retvals: |
267 |
+ return retvals |
268 |
+ return [('None', os.EX_OK)] |
269 |
+ |
270 |
+ |
271 |
+ def _do_pkg_moves(self): |
272 |
+ if self.emerge_config.opts.get('--package-moves') != 'n' and \ |
273 |
+ _global_updates(self.emerge_config.trees, |
274 |
+ self.emerge_config.target_config.mtimedb["updates"], |
275 |
+ quiet=("--quiet" in self.emerge_config.opts)): |
276 |
+ self.emerge_config.target_config.mtimedb.commit() |
277 |
+ # Reload the whole config. |
278 |
+ self._reload_config() |
279 |
+ |
280 |
+ |
281 |
+ def _check_updates(self): |
282 |
+ mybestpv = self.emerge_config.target_config.trees['porttree'].dbapi.xmatch( |
283 |
+ "bestmatch-visible", portage.const.PORTAGE_PACKAGE_ATOM) |
284 |
+ mypvs = portage.best( |
285 |
+ self.emerge_config.target_config.trees['vartree'].dbapi.match( |
286 |
+ portage.const.PORTAGE_PACKAGE_ATOM)) |
287 |
+ |
288 |
+ chk_updated_cfg_files(self.emerge_config.target_config.root, |
289 |
+ portage.util.shlex_split( |
290 |
+ self.emerge_config.target_config.settings.get("CONFIG_PROTECT", ""))) |
291 |
+ |
292 |
+ if mybestpv != mypvs and "--quiet" not in self.emerge_config.opts: |
293 |
+ print() |
294 |
+ print(warn(" * ")+bold("An update to portage is available.")+" It is _highly_ recommended") |
295 |
+ print(warn(" * ")+"that you update portage now, before any other packages are updated.") |
296 |
+ print() |
297 |
+ print(warn(" * ")+"To update portage, run 'emerge --oneshot portage' now.") |
298 |
+ print() |
299 |
+ |
300 |
+ |
301 |
+ def _reload_config(self): |
302 |
+ '''Reload the whole config from scratch.''' |
303 |
+ load_emerge_config(emerge_config=self.emerge_config) |
304 |
+ adjust_configs(self.emerge_config.opts, self.emerge_config.trees) |
305 |
+ |
306 |
+ |
307 |
+ def rmessage(self, rvals, action): |
308 |
+ '''Creates emaint style messages to return to the task handler''' |
309 |
+ messages = [] |
310 |
+ for rval in rvals: |
311 |
+ messages.append("Action: %s for repo: %s, returned code = %s" |
312 |
+ % (action, rval[0], rval[1])) |
313 |
+ return messages |