Merge lp:~paul-eggleton/smart/yocto-smart-fixes into lp:smart
- yocto-smart-fixes
- Merge into trunk
Status: | Needs review |
---|---|
Proposed branch: | lp:~paul-eggleton/smart/yocto-smart-fixes |
Merge into: | lp:smart |
Diff against target: |
1794 lines (+730/-71) 26 files modified
smart/backends/rpm/base.py (+36/-7) smart/backends/rpm/header.py (+12/-5) smart/backends/rpm/metadata.py (+21/-8) smart/backends/rpm/pm.py (+17/-0) smart/cache.py (+72/-3) smart/ccache.c (+355/-24) smart/channels/rpm_sys.py (+4/-4) smart/commands/channel.py (+15/-2) smart/commands/check.py (+3/-0) smart/commands/config.py (+10/-1) smart/commands/download.py (+8/-0) smart/commands/flag.py (+4/-1) smart/commands/info.py (+4/-0) smart/commands/install.py (+4/-0) smart/commands/mirror.py (+4/-1) smart/commands/priority.py (+4/-1) smart/commands/query.py (+51/-0) smart/commands/reinstall.py (+5/-1) smart/commands/remove.py (+4/-0) smart/commands/search.py (+2/-0) smart/commands/upgrade.py (+3/-0) smart/control.py (+2/-2) smart/plugins/detectsys.py (+2/-1) smart/searcher.py (+11/-3) smart/transaction.py (+21/-7) smart/util/optparse.py (+56/-0) |
To merge this branch: | bzr merge lp:~paul-eggleton/smart/yocto-smart-fixes |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Smart Package Manager Team | Pending | ||
Review via email: mp+147946@code.launchpad.net |
Commit message
Description of the change
Included are most of the patches for Smart developed within the Yocto Project and being carried in OE-core which are now being carried in OpenEmbedded-Core. Each patch has a commit message explaining what it does; if further clarification or adjustments are needed please let me know.
Unmerged revisions
- 1096. By Paul-eggleton
-
Print a more friendly error if YAML output is requested without PyYAML
Signed-off-by: Paul Eggleton <email address hidden>
- 1095. By Bogdan Marinescu <email address hidden>
-
To fix some multilib issues, change the way the RPM backend decides
if two packages can coexist: if they have a different architecture,
automatically assume that they can coexist (which is fundamental for
multilib).Signed-off-by: Bogdan Marinescu <email address hidden>
- 1094. By Bogdan Marinescu <email address hidden>
-
Improve error reporting in smart
Add code to check proper command line arguments for various
smart commands. Exit with error if erroneous/additional arguments
are given in the command line.Signed-off-by: Bogdan Marinescu <email address hidden>
- 1093. By Mark Hatle <email address hidden>
-
backends/rpm: Fix incorrect call to the match function
The match function should take three parameters, name, comparison, version...
The original code was passing it a reference to the object holding the data
instead, which caused the comparison in match to always fail.Signed-off-by: Mark Hatle <email address hidden>
- 1092. By Paul-eggleton
-
backends/rpm: remove creation of /var/tmp
This doesn't appear to be needed, and breaks installation of base-files
in OpenEmbedded (since that is a symlink installed as part of the
package).Signed-off-by: Paul Eggleton <email address hidden>
- 1091. By Paul-eggleton
-
backends/rpm: fix parsing of rpm-md metadata
If assertions are disabled then the queue.pop() wasn't being executed,
leading to requires, recommends etc. not being read properly.Signed-off-by: Paul Eggleton <email address hidden>
- 1090. By Paul-eggleton
-
backends/rpm: add support for setting dependency flags
This is useful for OpenEmbedded so that we can do the equivalent of
the --nolinktos and --noparentdirs rpm command line options.Signed-off-by: Paul Eggleton <email address hidden>
- 1089. By Paul-eggleton
-
backends/rpm: implement rpm-extra-macros option
Allow defining extra macros in the smart configuration to be passed
to rpm before opening the database.Signed-off-by: Paul Eggleton <email address hidden>
- 1088. By Paul-eggleton
-
Handle recommended packages in core and rpm backends
Identify and store recommended packages in the cache, add a query option
to read them and ignore them if they are not present when installing.Initial identification code from Mark Hatle <email address hidden>.
Signed-off-by: Paul Eggleton <email address hidden>
- 1087. By Paul-eggleton
-
Fix smart RPM backend to handle rpm-dbpath/rpm-root properly
Don't assume that if the dbpath starts with / that it is an absolute
path. This matches the behaviour of rpm itself. (If the root path is
specified and does not start with /, rpm will prepend the root path
twice and fail).Signed-off-by: Paul Eggleton <email address hidden>
Preview Diff
1 | === modified file 'smart/backends/rpm/base.py' |
2 | --- smart/backends/rpm/base.py 2011-10-06 07:10:20 +0000 |
3 | +++ smart/backends/rpm/base.py 2013-02-12 14:46:20 +0000 |
4 | @@ -46,7 +46,17 @@ |
5 | "rpm", "getTS", "getArchScore", "getArchColor", "system_provides", |
6 | "collapse_libc_requires"] |
7 | |
8 | +def rpm_join_dbpath(root, dbpath): |
9 | + if dbpath.startswith('/') and root: |
10 | + return os.path.join(root, dbpath[1:]) |
11 | + else: |
12 | + return os.path.join(root, dbpath) |
13 | + |
14 | def getTS(new=False): |
15 | + if sysconf.get("rpm-extra-macros"): |
16 | + for key, value in sysconf.get("rpm-extra-macros").items(): |
17 | + rpm.addMacro(key, str(value)) |
18 | + |
19 | rpm_root = os.path.abspath(sysconf.get("rpm-root", "/")) |
20 | if not hasattr(getTS, "ts") or getTS.root != rpm_root: |
21 | getTS.root = rpm_root |
22 | @@ -56,7 +66,7 @@ |
23 | if not sysconf.get("rpm-check-signatures", False): |
24 | getTS.ts.setVSFlags(rpm._RPMVSF_NOSIGNATURES) |
25 | rpm_dbpath = sysconf.get("rpm-dbpath", "var/lib/rpm") |
26 | - dbdir = os.path.join(getTS.root, rpm_dbpath) |
27 | + dbdir = rpm_join_dbpath(getTS.root, rpm_dbpath) |
28 | if not os.path.isdir(dbdir): |
29 | try: |
30 | os.makedirs(dbdir) |
31 | @@ -72,12 +82,6 @@ |
32 | else: |
33 | iface.warning(_("Initialized new rpm database at %s") |
34 | % getTS.root) |
35 | - tmpdir = os.path.join(getTS.root, "var/tmp") |
36 | - if not os.path.isdir(tmpdir): |
37 | - try: |
38 | - os.makedirs(tmpdir) |
39 | - except OSError: |
40 | - pass |
41 | if new: |
42 | if sysconf.get("rpm-dbpath"): |
43 | rpm.addMacro('_dbpath', "/" + sysconf.get("rpm-dbpath")) |
44 | @@ -192,6 +196,29 @@ |
45 | break |
46 | else: |
47 | return False |
48 | + srecs = fk(self.recommends) |
49 | + orecs = fk(other.recommends) |
50 | + if srecs != orecs: |
51 | + for srec in srecs: |
52 | + if srec.name[0] == "/" or srec in orecs: |
53 | + continue |
54 | + for orec in orecs: |
55 | + if (srec.name == orec.name and |
56 | + srec.relation == orec.relation and |
57 | + checkver(srec.version, orec.version)): |
58 | + break |
59 | + else: |
60 | + return False |
61 | + for orec in orecs: |
62 | + if orec.name[0] == "/" or orec in srecs: |
63 | + continue |
64 | + for srec in srecs: |
65 | + if (srec.name == orec.name and |
66 | + srec.relation == orec.relation and |
67 | + checkver(srec.version, orec.version)): |
68 | + break |
69 | + else: |
70 | + return False |
71 | return True |
72 | |
73 | def coexists(self, other): |
74 | @@ -201,6 +228,8 @@ |
75 | return False |
76 | selfver, selfarch = splitarch(self.version) |
77 | otherver, otherarch = splitarch(other.version) |
78 | + if selfarch != otherarch: |
79 | + return True |
80 | selfcolor = getArchColor(selfarch) |
81 | othercolor = getArchColor(otherarch) |
82 | if (selfcolor and othercolor and selfcolor != othercolor and |
83 | |
84 | === modified file 'smart/backends/rpm/header.py' |
85 | --- smart/backends/rpm/header.py 2011-10-05 15:09:41 +0000 |
86 | +++ smart/backends/rpm/header.py 2013-02-12 14:46:20 +0000 |
87 | @@ -292,6 +292,7 @@ |
88 | f = [0] |
89 | elif type(f) != list: |
90 | f = [f] |
91 | + recdict = {} |
92 | reqdict = {} |
93 | for i in range(len(n)): |
94 | ni = n[i] |
95 | @@ -308,10 +309,16 @@ |
96 | # RPMSENSE_SCRIPT_PREUN | |
97 | # RPMSENSE_SCRIPT_POST | |
98 | # RPMSENSE_SCRIPT_POSTUN == 7744 |
99 | - reqdict[(f[i]&7744 and PreReq or Req, |
100 | - intern(ni), r, vi)] = True |
101 | + if (f[i]&rpm.RPMSENSE_MISSINGOK): |
102 | + recdict[(f[i]&7744 and PreReq or Req, |
103 | + intern(ni), r, vi)] = True |
104 | + else: |
105 | + reqdict[(f[i]&7744 and PreReq or Req, |
106 | + intern(ni), r, vi)] = True |
107 | + recargs = collapse_libc_requires(recdict.keys()) |
108 | reqargs = collapse_libc_requires(reqdict.keys()) |
109 | else: |
110 | + recargs = None |
111 | reqargs = None |
112 | |
113 | n = h[1054] # RPMTAG_CONFLICTNAME |
114 | @@ -365,7 +372,7 @@ |
115 | versionarch = "%s@%s" % (distversion, arch) |
116 | |
117 | pkg = self.buildPackage((Pkg, name, versionarch), |
118 | - prvargs, reqargs, upgargs, cnfargs) |
119 | + prvargs, reqargs, upgargs, cnfargs, recargs) |
120 | pkg.loaders[self] = offset |
121 | self._offsets[offset] = pkg |
122 | self._groups[pkg] = intern(h[rpm.RPMTAG_GROUP]) |
123 | @@ -583,8 +590,8 @@ |
124 | def setErrataFlags(self, flagdict): |
125 | self._flagdict = flagdict |
126 | |
127 | - def buildPackage(self, pkgargs, prvargs, reqargs, upgargs, cnfargs): |
128 | - pkg = Loader.buildPackage(self, pkgargs, prvargs, reqargs, upgargs, cnfargs) |
129 | + def buildPackage(self, pkgargs, prvargs, reqargs, upgargs, cnfargs, recargs): |
130 | + pkg = Loader.buildPackage(self, pkgargs, prvargs, reqargs, upgargs, cnfargs, recargs) |
131 | name = pkgargs[1] |
132 | if hasattr(self, '_flagdict') and self._flagdict and name in self._flagdict: |
133 | if sysconf.getReadOnly(): |
134 | |
135 | === modified file 'smart/backends/rpm/metadata.py' |
136 | --- smart/backends/rpm/metadata.py 2011-10-05 15:09:41 +0000 |
137 | +++ smart/backends/rpm/metadata.py 2013-02-12 14:46:20 +0000 |
138 | @@ -165,6 +165,7 @@ |
139 | distepoch = None |
140 | info = {} |
141 | reqdict = {} |
142 | + recdict = {} |
143 | prvdict = {} |
144 | upgdict = {} |
145 | cnfdict = {} |
146 | @@ -188,7 +189,8 @@ |
147 | |
148 | elif event == "end": |
149 | |
150 | - assert queue.pop() is elem |
151 | + popped = queue.pop() |
152 | + assert popped is elem |
153 | |
154 | if skip: |
155 | if tag == skip: |
156 | @@ -287,12 +289,16 @@ |
157 | |
158 | lasttag = queue[-1].tag |
159 | if lasttag == REQUIRES: |
160 | - if elem.get("pre") == "1": |
161 | - reqdict[(RPMPreRequires, |
162 | - ename, erelation, eversion)] = True |
163 | + if elem.get("missingok") == "1": |
164 | + recdict[(RPMRequires, |
165 | + ename, erelation, eversion)] = True |
166 | else: |
167 | - reqdict[(RPMRequires, |
168 | - ename, erelation, eversion)] = True |
169 | + if elem.get("pre") == "1": |
170 | + reqdict[(RPMPreRequires, |
171 | + ename, erelation, eversion)] = True |
172 | + else: |
173 | + reqdict[(RPMRequires, |
174 | + ename, erelation, eversion)] = True |
175 | |
176 | elif lasttag == PROVIDES: |
177 | if ename[0] == "/": |
178 | @@ -326,8 +332,14 @@ |
179 | reqargs = [x for x in reqdict |
180 | if not ((x[2] is None or "=" in x[2]) and |
181 | (RPMProvides, x[1], x[3]) in prvdict or |
182 | - system_provides.match(*x[:3]))] |
183 | + system_provides.match(x[1], x[2], x[3]))] |
184 | reqargs = collapse_libc_requires(reqargs) |
185 | + |
186 | + recargs = [x for x in recdict |
187 | + if not ((x[2] is None or "=" in x[2]) and |
188 | + (RPMProvides, x[1], x[3]) in prvdict or |
189 | + system_provides.match(x[1], x[2], x[3]))] |
190 | + |
191 | prvargs = prvdict.keys() |
192 | cnfargs = cnfdict.keys() |
193 | upgargs = upgdict.keys() |
194 | @@ -339,7 +351,7 @@ |
195 | versionarch = "%s@%s" % (distversion, arch) |
196 | |
197 | pkg = self.buildPackage((RPMPackage, name, versionarch), |
198 | - prvargs, reqargs, upgargs, cnfargs) |
199 | + prvargs, reqargs, upgargs, cnfargs, recargs) |
200 | pkg.loaders[self] = info |
201 | |
202 | # Store the provided files for future usage. |
203 | @@ -362,6 +374,7 @@ |
204 | distepoch = None |
205 | pkgid = None |
206 | reqdict.clear() |
207 | + recdict.clear() |
208 | prvdict.clear() |
209 | upgdict.clear() |
210 | cnfdict.clear() |
211 | |
212 | === modified file 'smart/backends/rpm/pm.py' |
213 | --- smart/backends/rpm/pm.py 2010-12-17 11:26:28 +0000 |
214 | +++ smart/backends/rpm/pm.py 2013-02-12 14:46:20 +0000 |
215 | @@ -106,6 +106,23 @@ |
216 | flags |= rpm.RPMTRANS_FLAG_TEST |
217 | ts.setFlags(flags) |
218 | |
219 | + dflags = ts.setDFlags(0) |
220 | + if sysconf.get("rpm-noupgrade", False): |
221 | + dflags |= rpm.RPMDEPS_FLAG_NOUPGRADE |
222 | + if sysconf.get("rpm-norequires", False): |
223 | + dflags |= rpm.RPMDEPS_FLAG_NOREQUIRES |
224 | + if sysconf.get("rpm-noconflicts", False): |
225 | + dflags |= rpm.RPMDEPS_FLAG_NOCONFLICTS |
226 | + if sysconf.get("rpm-noobsoletes", False): |
227 | + dflags |= rpm.RPMDEPS_FLAG_NOOBSOLETES |
228 | + if sysconf.get("rpm-noparentdirs", False): |
229 | + dflags |= rpm.RPMDEPS_FLAG_NOPARENTDIRS |
230 | + if sysconf.get("rpm-nolinktos", False): |
231 | + dflags |= rpm.RPMDEPS_FLAG_NOLINKTOS |
232 | + if sysconf.get("rpm-nosuggest", False): |
233 | + dflags |= rpm.RPMDEPS_FLAG_NOSUGGEST |
234 | + ts.setDFlags(dflags) |
235 | + |
236 | # Set rpm verbosity level. |
237 | levelname = sysconf.get('rpm-log-level') |
238 | level = { |
239 | |
240 | === modified file 'smart/cache.py' |
241 | --- smart/cache.py 2010-08-24 08:15:35 +0000 |
242 | +++ smart/cache.py 2013-02-12 14:46:20 +0000 |
243 | @@ -32,7 +32,8 @@ |
244 | self.name = name |
245 | self.version = version |
246 | self.provides = () |
247 | - self.requires = () |
248 | + self.requires = [] |
249 | + self.recommends = [] |
250 | self.upgrades = () |
251 | self.conflicts = () |
252 | self.installed = False |
253 | @@ -55,7 +56,9 @@ |
254 | fk([x for x in self.provides if x.name[0] != "/"]) != |
255 | fk([x for x in other.provides if x.name[0] != "/"]) or |
256 | fk([x for x in self.requires if x.name[0] != "/"]) != |
257 | - fk([x for x in other.requires if x.name[0] != "/"])): |
258 | + fk([x for x in other.requires if x.name[0] != "/"]) or |
259 | + fk([x for x in self.recommends if x.name[0] != "/"]) != |
260 | + fk([x for x in other.recommends if x.name[0] != "/"])): |
261 | return False |
262 | return True |
263 | |
264 | @@ -110,6 +113,7 @@ |
265 | self.version, |
266 | self.provides, |
267 | self.requires, |
268 | + self.recommends, |
269 | self.upgrades, |
270 | self.conflicts, |
271 | self.installed, |
272 | @@ -122,6 +126,7 @@ |
273 | self.version, |
274 | self.provides, |
275 | self.requires, |
276 | + self.recommends, |
277 | self.upgrades, |
278 | self.conflicts, |
279 | self.installed, |
280 | @@ -274,6 +279,7 @@ |
281 | self.version = version |
282 | self.packages = [] |
283 | self.requiredby = () |
284 | + self.recommendedby = () |
285 | self.upgradedby = () |
286 | self.conflictedby = () |
287 | |
288 | @@ -401,7 +407,7 @@ |
289 | def loadFileProvides(self, fndict): |
290 | pass |
291 | |
292 | - def buildPackage(self, pkgargs, prvargs, reqargs, upgargs, cnfargs): |
293 | + def buildPackage(self, pkgargs, prvargs, reqargs, upgargs, cnfargs, recargs = None): |
294 | cache = self._cache |
295 | pkg = pkgargs[0](*pkgargs[1:]) |
296 | relpkgs = [] |
297 | @@ -427,6 +433,17 @@ |
298 | relpkgs.append(req.packages) |
299 | pkg.requires.append(req) |
300 | |
301 | + if recargs: |
302 | + pkg.recommends = [] |
303 | + for args in recargs: |
304 | + rec = cache._objmap.get(args) |
305 | + if not rec: |
306 | + rec = args[0](*args[1:]) |
307 | + cache._objmap[args] = rec |
308 | + cache._recommends.append(rec) |
309 | + relpkgs.append(rec.packages) |
310 | + pkg.recommends.append(rec) |
311 | + |
312 | if upgargs: |
313 | pkg.upgrades = [] |
314 | for args in upgargs: |
315 | @@ -572,6 +589,7 @@ |
316 | self._packages = [] |
317 | self._provides = [] |
318 | self._requires = [] |
319 | + self._recommends = [] |
320 | self._upgrades = [] |
321 | self._conflicts = [] |
322 | self._objmap = {} |
323 | @@ -581,6 +599,8 @@ |
324 | del prv.packages[:] |
325 | if prv.requiredby: |
326 | del prv.requiredby[:] |
327 | + if prv.recommendedby: |
328 | + del prv.recommendedby[:] |
329 | if prv.upgradedby: |
330 | del prv.upgradedby[:] |
331 | if prv.conflictedby: |
332 | @@ -589,6 +609,10 @@ |
333 | del req.packages[:] |
334 | if req.providedby: |
335 | del req.providedby[:] |
336 | + for rec in self._recommends: |
337 | + del rec.packages[:] |
338 | + if rec.providedby: |
339 | + del rec.providedby[:] |
340 | for upg in self._upgrades: |
341 | del upg.packages[:] |
342 | if upg.providedby: |
343 | @@ -600,6 +624,7 @@ |
344 | del self._packages[:] |
345 | del self._provides[:] |
346 | del self._requires[:] |
347 | + del self._recommends[:] |
348 | del self._upgrades[:] |
349 | del self._conflicts[:] |
350 | self._objmap.clear() |
351 | @@ -621,6 +646,7 @@ |
352 | packages = {} |
353 | provides = {} |
354 | requires = {} |
355 | + recommends = {} |
356 | upgrades = {} |
357 | conflicts = {} |
358 | objmap = self._objmap |
359 | @@ -646,6 +672,11 @@ |
360 | if req not in requires: |
361 | objmap[req.getInitArgs()] = req |
362 | requires[req] = True |
363 | + for rec in pkg.recommends[:]: |
364 | + rec.packages.append(pkg) |
365 | + if rec not in recommends: |
366 | + objmap[rec.getInitArgs()] = rec |
367 | + recommends[rec] = True |
368 | for upg in pkg.upgrades: |
369 | upg.packages.append(pkg) |
370 | if upg not in upgrades: |
371 | @@ -659,6 +690,7 @@ |
372 | self._packages[:] = packages.keys() |
373 | self._provides[:] = provides.keys() |
374 | self._requires[:] = requires.keys() |
375 | + self._recommends[:] = recommends.keys() |
376 | self._upgrades[:] = upgrades.keys() |
377 | self._conflicts[:] = conflicts.keys() |
378 | |
379 | @@ -710,6 +742,14 @@ |
380 | lst.append(req) |
381 | else: |
382 | reqnames[name] = [req] |
383 | + recnames = {} |
384 | + for rec in self._recommends: |
385 | + for name in rec.getMatchNames(): |
386 | + lst = recnames.get(name) |
387 | + if lst: |
388 | + lst.append(rec) |
389 | + else: |
390 | + recnames[name] = [rec] |
391 | upgnames = {} |
392 | for upg in self._upgrades: |
393 | for name in upg.getMatchNames(): |
394 | @@ -739,6 +779,18 @@ |
395 | prv.requiredby.append(req) |
396 | else: |
397 | prv.requiredby = [req] |
398 | + lst = recnames.get(prv.name) |
399 | + if lst: |
400 | + for rec in lst: |
401 | + if rec.matches(prv): |
402 | + if rec.providedby: |
403 | + rec.providedby.append(prv) |
404 | + else: |
405 | + rec.providedby = [prv] |
406 | + if prv.recommendedby: |
407 | + prv.recommendedby.append(rec) |
408 | + else: |
409 | + prv.recommendedby = [rec] |
410 | lst = upgnames.get(prv.name) |
411 | if lst: |
412 | for upg in lst: |
413 | @@ -782,6 +834,12 @@ |
414 | else: |
415 | return [x for x in self._requires if x.name == name] |
416 | |
417 | + def getRecommends(self, name=None): |
418 | + if not name: |
419 | + return self._recommends |
420 | + else: |
421 | + return [x for x in self._recommends if x.name == name] |
422 | + |
423 | def getUpgrades(self, name=None): |
424 | if not name: |
425 | return self._upgrades |
426 | @@ -807,6 +865,12 @@ |
427 | for req in self._requires: |
428 | if prvname in req.getMatchNames() and req.matches(prv): |
429 | searcher.addResult(req) |
430 | + if searcher.recommends: |
431 | + for prv in searcher.recommends: |
432 | + prvname = prv.name |
433 | + for req in self._recommends: |
434 | + if prvname in req.getMatchNames() and req.matches(prv): |
435 | + searcher.addResult(req) |
436 | if searcher.upgrades: |
437 | for prv in searcher.upgrades: |
438 | prvname = prv.name |
439 | @@ -839,6 +903,7 @@ |
440 | self._packages = state["_packages"] |
441 | provides = {} |
442 | requires = {} |
443 | + recommends = {} |
444 | upgrades = {} |
445 | conflicts = {} |
446 | for pkg in self._packages: |
447 | @@ -848,6 +913,9 @@ |
448 | for req in pkg.requires: |
449 | req.packages.append(pkg) |
450 | requires[req] = True |
451 | + for rec in pkg.recommends: |
452 | + rec.packages.append(pkg) |
453 | + recommends[rec] = True |
454 | for upg in pkg.upgrades: |
455 | upg.packages.append(pkg) |
456 | upgrades[upg] = True |
457 | @@ -856,6 +924,7 @@ |
458 | conflicts[cnf] = True |
459 | self._provides = provides.keys() |
460 | self._requires = requires.keys() |
461 | + self._recommends = recommends.keys() |
462 | self._upgrades = upgrades.keys() |
463 | self._conflicts = conflicts.keys() |
464 | self._objmap = {} |
465 | |
466 | === modified file 'smart/ccache.c' |
467 | --- smart/ccache.c 2009-03-02 12:56:54 +0000 |
468 | +++ smart/ccache.c 2013-02-12 14:46:20 +0000 |
469 | @@ -82,6 +82,7 @@ |
470 | PyObject *version; |
471 | PyObject *provides; |
472 | PyObject *requires; |
473 | + PyObject *recommends; |
474 | PyObject *upgrades; |
475 | PyObject *conflicts; |
476 | PyObject *installed; |
477 | @@ -96,6 +97,7 @@ |
478 | PyObject *version; |
479 | PyObject *packages; |
480 | PyObject *requiredby; |
481 | + PyObject *recommendedby; |
482 | PyObject *upgradedby; |
483 | PyObject *conflictedby; |
484 | } ProvidesObject; |
485 | @@ -123,6 +125,7 @@ |
486 | PyObject *_packages; |
487 | PyObject *_provides; |
488 | PyObject *_requires; |
489 | + PyObject *_recommends; |
490 | PyObject *_upgrades; |
491 | PyObject *_conflicts; |
492 | PyObject *_objmap; |
493 | @@ -211,7 +214,8 @@ |
494 | Py_INCREF(self->name); |
495 | Py_INCREF(self->version); |
496 | self->provides = PyTuple_New(0); |
497 | - self->requires = PyTuple_New(0); |
498 | + self->requires = PyList_New(0); |
499 | + self->recommends = PyList_New(0); |
500 | self->upgrades = PyTuple_New(0); |
501 | self->conflicts = PyTuple_New(0); |
502 | Py_INCREF(Py_False); |
503 | @@ -228,6 +232,7 @@ |
504 | { |
505 | Py_VISIT(self->provides); |
506 | Py_VISIT(self->requires); |
507 | + Py_VISIT(self->recommends); |
508 | Py_VISIT(self->upgrades); |
509 | Py_VISIT(self->conflicts); |
510 | Py_VISIT(self->loaders); |
511 | @@ -239,6 +244,7 @@ |
512 | { |
513 | Py_CLEAR(self->provides); |
514 | Py_CLEAR(self->requires); |
515 | + Py_CLEAR(self->recommends); |
516 | Py_CLEAR(self->upgrades); |
517 | Py_CLEAR(self->conflicts); |
518 | Py_CLEAR(self->loaders); |
519 | @@ -252,6 +258,7 @@ |
520 | Py_XDECREF(self->version); |
521 | Py_XDECREF(self->provides); |
522 | Py_XDECREF(self->requires); |
523 | + Py_XDECREF(self->recommends); |
524 | Py_XDECREF(self->upgrades); |
525 | Py_XDECREF(self->conflicts); |
526 | Py_XDECREF(self->installed); |
527 | @@ -453,6 +460,46 @@ |
528 | } |
529 | } |
530 | |
531 | + ilen = 0; |
532 | + jlen = 0; |
533 | + for (i = 0; i != PyList_GET_SIZE(self->recommends); i++) { |
534 | + PyObject *item = PyList_GET_ITEM(self->recommends, i); |
535 | + if (!PyObject_IsInstance(item, (PyObject *)&Depends_Type)) { |
536 | + PyErr_SetString(PyExc_TypeError, "Depends instance expected"); |
537 | + return NULL; |
538 | + } |
539 | + if (STR(((DependsObject *)item)->name)[0] != '/') |
540 | + ilen += 1; |
541 | + } |
542 | + for (j = 0; j != PyList_GET_SIZE(other->recommends); j++) { |
543 | + PyObject *item = PyList_GET_ITEM(other->recommends, j); |
544 | + if (!PyObject_IsInstance(item, (PyObject *)&Depends_Type)) { |
545 | + PyErr_SetString(PyExc_TypeError, "Depends instance expected"); |
546 | + return NULL; |
547 | + } |
548 | + if (STR(((DependsObject *)item)->name)[0] != '/') |
549 | + jlen += 1; |
550 | + } |
551 | + if (ilen != jlen) { |
552 | + ret = Py_False; |
553 | + goto exit; |
554 | + } |
555 | + |
556 | + ilen = PyList_GET_SIZE(self->recommends); |
557 | + jlen = PyList_GET_SIZE(other->recommends); |
558 | + for (i = 0; i != ilen; i++) { |
559 | + PyObject *item = PyList_GET_ITEM(self->recommends, i); |
560 | + if (STR(((DependsObject *)item)->name)[0] != '/') { |
561 | + for (j = 0; j != jlen; j++) |
562 | + if (item == PyList_GET_ITEM(other->recommends, j)) |
563 | + break; |
564 | + if (j == jlen) { |
565 | + ret = Py_False; |
566 | + goto exit; |
567 | + } |
568 | + } |
569 | + } |
570 | + |
571 | exit: |
572 | Py_INCREF(ret); |
573 | return ret; |
574 | @@ -606,13 +653,14 @@ |
575 | static PyObject * |
576 | Package__getstate__(PackageObject *self, PyObject *args) |
577 | { |
578 | - PyObject *state = PyTuple_New(10); |
579 | + PyObject *state = PyTuple_New(11); |
580 | if (!state) return NULL; |
581 | |
582 | Py_INCREF(self->name); |
583 | Py_INCREF(self->version); |
584 | Py_INCREF(self->provides); |
585 | Py_INCREF(self->requires); |
586 | + Py_INCREF(self->recommends); |
587 | Py_INCREF(self->upgrades); |
588 | Py_INCREF(self->conflicts); |
589 | Py_INCREF(self->installed); |
590 | @@ -620,16 +668,17 @@ |
591 | Py_INCREF(self->priority); |
592 | Py_INCREF(self->loaders); |
593 | |
594 | - PyTuple_SET_ITEM(state, 0, self->name); |
595 | - PyTuple_SET_ITEM(state, 1, self->version); |
596 | - PyTuple_SET_ITEM(state, 2, self->provides); |
597 | - PyTuple_SET_ITEM(state, 3, self->requires); |
598 | - PyTuple_SET_ITEM(state, 4, self->upgrades); |
599 | - PyTuple_SET_ITEM(state, 5, self->conflicts); |
600 | - PyTuple_SET_ITEM(state, 6, self->installed); |
601 | - PyTuple_SET_ITEM(state, 7, self->essential); |
602 | - PyTuple_SET_ITEM(state, 8, self->priority); |
603 | - PyTuple_SET_ITEM(state, 9, self->loaders); |
604 | + PyTuple_SET_ITEM(state, 0, self->name); |
605 | + PyTuple_SET_ITEM(state, 1, self->version); |
606 | + PyTuple_SET_ITEM(state, 2, self->provides); |
607 | + PyTuple_SET_ITEM(state, 3, self->requires); |
608 | + PyTuple_SET_ITEM(state, 4, self->recommends); |
609 | + PyTuple_SET_ITEM(state, 5, self->upgrades); |
610 | + PyTuple_SET_ITEM(state, 6, self->conflicts); |
611 | + PyTuple_SET_ITEM(state, 7, self->installed); |
612 | + PyTuple_SET_ITEM(state, 8, self->essential); |
613 | + PyTuple_SET_ITEM(state, 9, self->priority); |
614 | + PyTuple_SET_ITEM(state, 10, self->loaders); |
615 | |
616 | return state; |
617 | } |
618 | @@ -637,7 +686,7 @@ |
619 | static PyObject * |
620 | Package__setstate__(PackageObject *self, PyObject *state) |
621 | { |
622 | - if (!PyTuple_Check(state) || PyTuple_GET_SIZE(state) != 10) { |
623 | + if (!PyTuple_Check(state) || PyTuple_GET_SIZE(state) != 11) { |
624 | PyErr_SetString(StateVersionError, ""); |
625 | return NULL; |
626 | } |
627 | @@ -645,18 +694,20 @@ |
628 | self->version = PyTuple_GET_ITEM(state, 1); |
629 | self->provides = PyTuple_GET_ITEM(state, 2); |
630 | self->requires = PyTuple_GET_ITEM(state, 3); |
631 | - self->upgrades = PyTuple_GET_ITEM(state, 4); |
632 | - self->conflicts = PyTuple_GET_ITEM(state, 5); |
633 | - self->installed = PyTuple_GET_ITEM(state, 6); |
634 | - self->essential = PyTuple_GET_ITEM(state, 7); |
635 | - self->priority = PyTuple_GET_ITEM(state, 8); |
636 | - self->loaders = PyTuple_GET_ITEM(state, 9); |
637 | + self->recommends = PyTuple_GET_ITEM(state, 4); |
638 | + self->upgrades = PyTuple_GET_ITEM(state, 5); |
639 | + self->conflicts = PyTuple_GET_ITEM(state, 6); |
640 | + self->installed = PyTuple_GET_ITEM(state, 7); |
641 | + self->essential = PyTuple_GET_ITEM(state, 8); |
642 | + self->priority = PyTuple_GET_ITEM(state, 9); |
643 | + self->loaders = PyTuple_GET_ITEM(state, 10); |
644 | |
645 | |
646 | Py_INCREF(self->name); |
647 | Py_INCREF(self->version); |
648 | Py_INCREF(self->provides); |
649 | Py_INCREF(self->requires); |
650 | + Py_INCREF(self->recommends); |
651 | Py_INCREF(self->upgrades); |
652 | Py_INCREF(self->conflicts); |
653 | Py_INCREF(self->installed); |
654 | @@ -686,6 +737,7 @@ |
655 | {"version", T_OBJECT, OFF(version), 0, 0}, |
656 | {"provides", T_OBJECT, OFF(provides), 0, 0}, |
657 | {"requires", T_OBJECT, OFF(requires), 0, 0}, |
658 | + {"recommends", T_OBJECT, OFF(recommends), 0, 0}, |
659 | {"upgrades", T_OBJECT, OFF(upgrades), 0, 0}, |
660 | {"conflicts", T_OBJECT, OFF(conflicts), 0, 0}, |
661 | {"installed", T_OBJECT, OFF(installed), 0, 0}, |
662 | @@ -750,6 +802,7 @@ |
663 | Py_INCREF(self->version); |
664 | self->packages = PyList_New(0); |
665 | self->requiredby = PyTuple_New(0); |
666 | + self->recommendedby = PyTuple_New(0); |
667 | self->upgradedby = PyTuple_New(0); |
668 | self->conflictedby = PyTuple_New(0); |
669 | return 0; |
670 | @@ -760,6 +813,7 @@ |
671 | { |
672 | Py_VISIT(self->packages); |
673 | Py_VISIT(self->requiredby); |
674 | + Py_VISIT(self->recommendedby); |
675 | Py_VISIT(self->upgradedby); |
676 | Py_VISIT(self->conflictedby); |
677 | return 0; |
678 | @@ -770,6 +824,7 @@ |
679 | { |
680 | Py_CLEAR(self->packages); |
681 | Py_CLEAR(self->requiredby); |
682 | + Py_CLEAR(self->recommendedby); |
683 | Py_CLEAR(self->upgradedby); |
684 | Py_CLEAR(self->conflictedby); |
685 | return 0; |
686 | @@ -782,6 +837,7 @@ |
687 | Py_XDECREF(self->version); |
688 | Py_XDECREF(self->packages); |
689 | Py_XDECREF(self->requiredby); |
690 | + Py_XDECREF(self->recommendedby); |
691 | Py_XDECREF(self->upgradedby); |
692 | Py_XDECREF(self->conflictedby); |
693 | self->ob_type->tp_free((PyObject *)self); |
694 | @@ -960,6 +1016,7 @@ |
695 | {"version", T_OBJECT, OFF(version), 0, 0}, |
696 | {"packages", T_OBJECT, OFF(packages), 0, 0}, |
697 | {"requiredby", T_OBJECT, OFF(requiredby), 0, 0}, |
698 | + {"recommendedby", T_OBJECT, OFF(recommendedby), 0, 0}, |
699 | {"upgradedby", T_OBJECT, OFF(upgradedby), 0, 0}, |
700 | {"conflictedby", T_OBJECT, OFF(conflictedby), 0, 0}, |
701 | {NULL} |
702 | @@ -1555,6 +1612,7 @@ |
703 | PyObject *reqargs; |
704 | PyObject *upgargs; |
705 | PyObject *cnfargs; |
706 | + PyObject *recargs = NULL; |
707 | PyObject *callargs; |
708 | |
709 | PyObject *pkg; |
710 | @@ -1574,9 +1632,10 @@ |
711 | |
712 | cache = (CacheObject *)self->_cache; |
713 | |
714 | - if (!PyArg_ParseTuple(args, "O!O&O&O&O&", &PyTuple_Type, &pkgargs, |
715 | + if (!PyArg_ParseTuple(args, "O!O&O&O&O&|O&", &PyTuple_Type, &pkgargs, |
716 | mylist, &prvargs, mylist, &reqargs, |
717 | - mylist, &upgargs, mylist, &cnfargs)) |
718 | + mylist, &upgargs, mylist, &cnfargs, |
719 | + mylist, &recargs)) |
720 | return NULL; |
721 | |
722 | if (PyTuple_GET_SIZE(pkgargs) < 2) { |
723 | @@ -1701,6 +1760,59 @@ |
724 | } |
725 | } |
726 | |
727 | + /* if recargs: */ |
728 | + if (recargs) { |
729 | + int i = 0; |
730 | + int len = PyList_GET_SIZE(recargs); |
731 | + /* pkg.recommends = [] */ |
732 | + Py_DECREF(pkgobj->recommends); |
733 | + pkgobj->recommends = PyList_New(len); |
734 | + /* for args in recargs: */ |
735 | + for (; i != len; i++) { |
736 | + PyObject *args = PyList_GET_ITEM(recargs, i); |
737 | + DependsObject *recobj; |
738 | + PyObject *rec; |
739 | + |
740 | + if (!PyTuple_Check(args)) { |
741 | + PyErr_SetString(PyExc_TypeError, |
742 | + "Item in recargs is not a tuple"); |
743 | + return NULL; |
744 | + } |
745 | + |
746 | + /* rec = cache._objmap.get(args) */ |
747 | + rec = PyDict_GetItem(cache->_objmap, args); |
748 | + recobj = (DependsObject *)rec; |
749 | + |
750 | + /* if not rec: */ |
751 | + if (!rec) { |
752 | + if (!PyTuple_Check(args) || PyTuple_GET_SIZE(args) < 2) { |
753 | + PyErr_SetString(PyExc_ValueError, "Invalid recargs tuple"); |
754 | + return NULL; |
755 | + } |
756 | + /* rec = args[0](*args[1:]) */ |
757 | + callargs = PyTuple_GetSlice(args, 1, PyTuple_GET_SIZE(args)); |
758 | + rec = PyObject_CallObject(PyTuple_GET_ITEM(args, 0), callargs); |
759 | + Py_DECREF(callargs); |
760 | + if (!rec) return NULL; |
761 | + recobj = (DependsObject *)rec; |
762 | + |
763 | + /* cache._objmap[args] = rec */ |
764 | + PyDict_SetItem(cache->_objmap, args, rec); |
765 | + Py_DECREF(rec); |
766 | + |
767 | + /* cache._recommends.append(rec) */ |
768 | + PyList_Append(cache->_recommends, rec); |
769 | + } |
770 | + |
771 | + /* relpkgs.append(rec.packages) */ |
772 | + PyList_Append(relpkgs, recobj->packages); |
773 | + |
774 | + /* pkg.recommends.append(rec) */ |
775 | + Py_INCREF(rec); |
776 | + PyList_SET_ITEM(pkgobj->recommends, i, rec); |
777 | + } |
778 | + } |
779 | + |
780 | /* if upgargs: */ |
781 | if (upgargs) { |
782 | int i = 0; |
783 | @@ -2391,6 +2503,7 @@ |
784 | self->_packages = PyList_New(0); |
785 | self->_provides = PyList_New(0); |
786 | self->_requires = PyList_New(0); |
787 | + self->_recommends = PyList_New(0); |
788 | self->_upgrades = PyList_New(0); |
789 | self->_conflicts = PyList_New(0); |
790 | self->_objmap = PyDict_New(); |
791 | @@ -2404,6 +2517,7 @@ |
792 | Py_VISIT(self->_packages); |
793 | Py_VISIT(self->_provides); |
794 | Py_VISIT(self->_requires); |
795 | + Py_VISIT(self->_recommends); |
796 | Py_VISIT(self->_upgrades); |
797 | Py_VISIT(self->_conflicts); |
798 | Py_VISIT(self->_objmap); |
799 | @@ -2417,6 +2531,7 @@ |
800 | Py_CLEAR(self->_packages); |
801 | Py_CLEAR(self->_provides); |
802 | Py_CLEAR(self->_requires); |
803 | + Py_CLEAR(self->_recommends); |
804 | Py_CLEAR(self->_upgrades); |
805 | Py_CLEAR(self->_conflicts); |
806 | Py_CLEAR(self->_objmap); |
807 | @@ -2430,6 +2545,7 @@ |
808 | Py_XDECREF(self->_packages); |
809 | Py_XDECREF(self->_provides); |
810 | Py_XDECREF(self->_requires); |
811 | + Py_XDECREF(self->_recommends); |
812 | Py_XDECREF(self->_upgrades); |
813 | Py_XDECREF(self->_conflicts); |
814 | Py_XDECREF(self->_objmap); |
815 | @@ -2449,6 +2565,8 @@ |
816 | LIST_CLEAR(prvobj->packages); |
817 | if (PyList_Check(prvobj->requiredby)) |
818 | LIST_CLEAR(prvobj->requiredby); |
819 | + if (PyList_Check(prvobj->recommendedby)) |
820 | + LIST_CLEAR(prvobj->recommendedby); |
821 | if (PyList_Check(prvobj->upgradedby)) |
822 | LIST_CLEAR(prvobj->upgradedby); |
823 | if (PyList_Check(prvobj->conflictedby)) |
824 | @@ -2464,6 +2582,16 @@ |
825 | if (PyList_Check(reqobj->providedby)) |
826 | LIST_CLEAR(reqobj->providedby); |
827 | } |
828 | + len = PyList_GET_SIZE(self->_recommends); |
829 | + for (i = 0; i != len; i++) { |
830 | + DependsObject *reqobj; |
831 | + PyObject *req; |
832 | + req = PyList_GET_ITEM(self->_recommends, i); |
833 | + reqobj = (DependsObject *)req; |
834 | + LIST_CLEAR(reqobj->packages); |
835 | + if (PyList_Check(reqobj->providedby)) |
836 | + LIST_CLEAR(reqobj->providedby); |
837 | + } |
838 | len = PyList_GET_SIZE(self->_upgrades); |
839 | for (i = 0; i != len; i++) { |
840 | DependsObject *upgobj; |
841 | @@ -2487,6 +2615,7 @@ |
842 | LIST_CLEAR(self->_packages); |
843 | LIST_CLEAR(self->_provides); |
844 | LIST_CLEAR(self->_requires); |
845 | + LIST_CLEAR(self->_recommends); |
846 | LIST_CLEAR(self->_upgrades); |
847 | LIST_CLEAR(self->_conflicts); |
848 | PyDict_Clear(self->_objmap); |
849 | @@ -2534,6 +2663,7 @@ |
850 | packages = {} |
851 | provides = {} |
852 | requires = {} |
853 | + recommends = {} |
854 | upgrades = {} |
855 | conflicts = {} |
856 | objmap = self._objmap |
857 | @@ -2541,11 +2671,12 @@ |
858 | PyObject *packages = PyDict_New(); |
859 | PyObject *provides = PyDict_New(); |
860 | PyObject *requires = PyDict_New(); |
861 | + PyObject *recommends = PyDict_New(); |
862 | PyObject *upgrades = PyDict_New(); |
863 | PyObject *conflicts = PyDict_New(); |
864 | PyObject *objmap = self->_objmap; |
865 | int i, ilen; |
866 | - if (!packages || !provides || !requires || !conflicts) |
867 | + if (!packages || !provides || !requires || !recommends || !conflicts ) |
868 | return NULL; |
869 | |
870 | /* for loader in loaders: */ |
871 | @@ -2679,6 +2810,30 @@ |
872 | } |
873 | |
874 | /* |
875 | + for rec in pkg.recommends: |
876 | + rec.packages.append(pkg) |
877 | + if rec not in recommends: |
878 | + recommends[rec] = True |
879 | + objmap[rec.getInitArgs()] = rec |
880 | + */ |
881 | + if (PyList_Check(pkg->recommends)) { |
882 | + klen = PyList_GET_SIZE(pkg->recommends); |
883 | + for (k = 0; k != klen; k++) { |
884 | + PyObject *rec = PyList_GET_ITEM(pkg->recommends, k); |
885 | + PyList_Append(((DependsObject *)rec)->packages, |
886 | + (PyObject *)pkg); |
887 | + if (!PyDict_GetItem(recommends, rec)) { |
888 | + PyDict_SetItem(recommends, rec, Py_True); |
889 | + args = PyObject_CallMethod(rec, "getInitArgs", |
890 | + NULL); |
891 | + if (!args) return NULL; |
892 | + PyDict_SetItem(objmap, args, rec); |
893 | + Py_DECREF(args); |
894 | + } |
895 | + } |
896 | + } |
897 | + |
898 | + /* |
899 | for upg in pkg.upgrades: |
900 | upg.packages.append(pkg) |
901 | if upg not in upgrades: |
902 | @@ -2747,6 +2902,11 @@ |
903 | self->_requires = PyDict_Keys(requires); |
904 | Py_DECREF(requires); |
905 | |
906 | + /* self._recommends[:] = recommends.keys() */ |
907 | + Py_DECREF(self->_recommends); |
908 | + self->_recommends = PyDict_Keys(recommends); |
909 | + Py_DECREF(recommends); |
910 | + |
911 | /* self._upgrades[:] = upgrades.keys() */ |
912 | Py_DECREF(self->_upgrades); |
913 | self->_upgrades = PyDict_Keys(upgrades); |
914 | @@ -2852,7 +3012,7 @@ |
915 | Cache_linkDeps(CacheObject *self, PyObject *args) |
916 | { |
917 | int i, j, len; |
918 | - PyObject *reqnames, *upgnames, *cnfnames; |
919 | + PyObject *reqnames, *recnames, *upgnames, *cnfnames; |
920 | PyObject *lst; |
921 | |
922 | /* reqnames = {} */ |
923 | @@ -2896,6 +3056,47 @@ |
924 | Py_DECREF(seq); |
925 | } |
926 | |
927 | + /* recnames = {} */ |
928 | + recnames = PyDict_New(); |
929 | + /* for rec in self._recommends: */ |
930 | + len = PyList_GET_SIZE(self->_recommends); |
931 | + for (i = 0; i != len; i++) { |
932 | + PyObject *rec = PyList_GET_ITEM(self->_recommends, i); |
933 | + |
934 | + /* for name in rec.getMatchNames(): */ |
935 | + PyObject *names = PyObject_CallMethod(rec, "getMatchNames", NULL); |
936 | + PyObject *seq = PySequence_Fast(names, "getMatchNames() returned " |
937 | + "non-sequence object"); |
938 | + int nameslen; |
939 | + if (!seq) return NULL; |
940 | + nameslen = PySequence_Fast_GET_SIZE(seq); |
941 | + for (j = 0; j != nameslen; j++) { |
942 | + PyObject *name = PySequence_Fast_GET_ITEM(seq, j); |
943 | + |
944 | + /* lst = recnames.get(name) */ |
945 | + lst = PyDict_GetItem(recnames, name); |
946 | + |
947 | + /* |
948 | + if lst: |
949 | + lst.append(rec) |
950 | + else: |
951 | + recnames[name] = [rec] |
952 | + */ |
953 | + if (lst) { |
954 | + PyList_Append(lst, rec); |
955 | + } else { |
956 | + lst = PyList_New(1); |
957 | + Py_INCREF(rec); |
958 | + PyList_SET_ITEM(lst, 0, rec); |
959 | + PyDict_SetItem(recnames, name, lst); |
960 | + Py_DECREF(lst); |
961 | + } |
962 | + } |
963 | + |
964 | + Py_DECREF(names); |
965 | + Py_DECREF(seq); |
966 | + } |
967 | + |
968 | /* upgnames = {} */ |
969 | upgnames = PyDict_New(); |
970 | /* for upg in self._upgrades: */ |
971 | @@ -3035,6 +3236,56 @@ |
972 | } |
973 | } |
974 | |
975 | + /* lst = recnames.get(prv.name) */ |
976 | + lst = PyDict_GetItem(recnames, prv->name); |
977 | + |
978 | + /* if lst: */ |
979 | + if (lst) { |
980 | + /* for rec in lst: */ |
981 | + int reclen = PyList_GET_SIZE(lst); |
982 | + for (j = 0; j != reclen; j++) { |
983 | + DependsObject *rec = (DependsObject *)PyList_GET_ITEM(lst, j); |
984 | + /* if rec.matches(prv): */ |
985 | + PyObject *ret = PyObject_CallMethod((PyObject *)rec, "matches", |
986 | + "O", (PyObject *)prv); |
987 | + if (!ret) return NULL; |
988 | + if (PyObject_IsTrue(ret)) { |
989 | + /* |
990 | + if rec.providedby: |
991 | + rec.providedby.append(prv) |
992 | + else: |
993 | + rec.providedby = [prv] |
994 | + */ |
995 | + if (PyList_Check(rec->providedby)) { |
996 | + PyList_Append(rec->providedby, (PyObject *)prv); |
997 | + } else { |
998 | + PyObject *_lst = PyList_New(1); |
999 | + Py_INCREF(prv); |
1000 | + PyList_SET_ITEM(_lst, 0, (PyObject *)prv); |
1001 | + Py_DECREF(rec->providedby); |
1002 | + rec->providedby = _lst; |
1003 | + } |
1004 | + |
1005 | + /* |
1006 | + if prv.recommendedby: |
1007 | + prv.recommendedby.append(prv) |
1008 | + else: |
1009 | + prv.recommendedby = [prv] |
1010 | + */ |
1011 | + if (PyList_Check(prv->recommendedby)) { |
1012 | + PyList_Append(prv->recommendedby, (PyObject *)rec); |
1013 | + } else { |
1014 | + PyObject *_lst = PyList_New(1); |
1015 | + Py_INCREF(rec); |
1016 | + PyList_SET_ITEM(_lst, 0, (PyObject *)rec); |
1017 | + Py_DECREF(prv->recommendedby); |
1018 | + prv->recommendedby = _lst; |
1019 | + } |
1020 | + } |
1021 | + Py_DECREF(ret); |
1022 | + } |
1023 | + } |
1024 | + |
1025 | /* lst = upgnames.get(prv.name) */ |
1026 | lst = PyDict_GetItem(upgnames, prv->name); |
1027 | |
1028 | @@ -3139,6 +3390,7 @@ |
1029 | } |
1030 | |
1031 | Py_DECREF(reqnames); |
1032 | + Py_DECREF(recnames); |
1033 | Py_DECREF(upgnames); |
1034 | Py_DECREF(cnfnames); |
1035 | |
1036 | @@ -3215,6 +3467,29 @@ |
1037 | } |
1038 | |
1039 | PyObject * |
1040 | +Cache_getRecommends(CacheObject *self, PyObject *args) |
1041 | +{ |
1042 | + const char *name = NULL; |
1043 | + PyObject *lst; |
1044 | + int i, len; |
1045 | + if (!PyArg_ParseTuple(args, "|s", &name)) |
1046 | + return NULL; |
1047 | + if (!name) { |
1048 | + Py_INCREF(self->_recommends); |
1049 | + return self->_recommends; |
1050 | + } |
1051 | + lst = PyList_New(0); |
1052 | + len = PyList_GET_SIZE(self->_recommends); |
1053 | + for (i = 0; i != len; i++) { |
1054 | + DependsObject *rec = |
1055 | + (DependsObject*)PyList_GET_ITEM(self->_recommends, i); |
1056 | + if (strcmp(STR(rec->name), name) == 0) |
1057 | + PyList_Append(lst, (PyObject *)rec); |
1058 | + } |
1059 | + return lst; |
1060 | +} |
1061 | + |
1062 | +PyObject * |
1063 | Cache_getUpgrades(CacheObject *self, PyObject *args) |
1064 | { |
1065 | const char *name = NULL; |
1066 | @@ -3324,6 +3599,38 @@ |
1067 | } |
1068 | Py_DECREF(lst); |
1069 | |
1070 | + lst = PyObject_GetAttrString(searcher, "recommends"); |
1071 | + if (lst == NULL || !PyList_Check(lst)) { |
1072 | + PyErr_SetString(PyExc_TypeError, "Invalid recommends attribute"); |
1073 | + return NULL; |
1074 | + } |
1075 | + for (i = 0; i != PyList_GET_SIZE(lst); i++) { |
1076 | + ProvidesObject *prv = (ProvidesObject *)PyList_GET_ITEM(lst, i); |
1077 | + for (j = 0; j != PyList_GET_SIZE(self->_recommends); j++) { |
1078 | + PyObject *rec = PyList_GET_ITEM(self->_recommends, j); |
1079 | + PyObject *names = PyObject_CallMethod(rec, "getMatchNames", NULL); |
1080 | + PyObject *seq = PySequence_Fast(names, "getMatchNames() returned " |
1081 | + "non-sequence object"); |
1082 | + if (seq == NULL) return NULL; |
1083 | + for (k = 0; k != PySequence_Fast_GET_SIZE(seq); k++) { |
1084 | + if (strcmp(PyString_AS_STRING(PySequence_Fast_GET_ITEM(seq, k)), |
1085 | + PyString_AS_STRING(prv->name)) == 0) { |
1086 | + res = PyObject_CallMethod(rec, "matches", "O", prv); |
1087 | + if (res == NULL) |
1088 | + return NULL; |
1089 | + if (PyObject_IsTrue(res)) |
1090 | + CALLMETHOD(searcher, "addResult", "O", rec); |
1091 | + Py_DECREF(res); |
1092 | + break; |
1093 | + } |
1094 | + } |
1095 | + |
1096 | + Py_DECREF(names); |
1097 | + Py_DECREF(seq); |
1098 | + } |
1099 | + } |
1100 | + Py_DECREF(lst); |
1101 | + |
1102 | lst = PyObject_GetAttrString(searcher, "upgrades"); |
1103 | if (lst == NULL || !PyList_Check(lst)) { |
1104 | PyErr_SetString(PyExc_TypeError, "Invalid upgrades attribute"); |
1105 | @@ -3420,7 +3727,7 @@ |
1106 | static PyObject * |
1107 | Cache__setstate__(CacheObject *self, PyObject *state) |
1108 | { |
1109 | - PyObject *provides, *requires, *upgrades, *conflicts; |
1110 | + PyObject *provides, *requires, *recommends, *upgrades, *conflicts; |
1111 | int i, ilen; |
1112 | int j, jlen; |
1113 | |
1114 | @@ -3452,11 +3759,13 @@ |
1115 | /* |
1116 | provides = {} |
1117 | requires = {} |
1118 | + recommends = {} |
1119 | upgrades = {} |
1120 | conflicts = {} |
1121 | */ |
1122 | provides = PyDict_New(); |
1123 | requires = PyDict_New(); |
1124 | + recommends = PyDict_New(); |
1125 | upgrades = PyDict_New(); |
1126 | conflicts = PyDict_New(); |
1127 | |
1128 | @@ -3497,6 +3806,21 @@ |
1129 | } |
1130 | |
1131 | /* |
1132 | + for rec in pkg.recommends: |
1133 | + rec.packages.append(pkg) |
1134 | + recommends[rec] = True |
1135 | + */ |
1136 | + if (PyList_Check(pkgobj->recommends)) { |
1137 | + jlen = PyList_GET_SIZE(pkgobj->recommends); |
1138 | + for (j = 0; j != jlen; j++) { |
1139 | + PyObject *rec = PyList_GET_ITEM(pkgobj->recommends, j); |
1140 | + DependsObject *recobj = (DependsObject *)rec; |
1141 | + PyList_Append(recobj->packages, pkg); |
1142 | + PyDict_SetItem(recommends, rec, Py_True); |
1143 | + } |
1144 | + } |
1145 | + |
1146 | + /* |
1147 | for upg in pkg.upgrades: |
1148 | upg.packages.append(pkg) |
1149 | upgrades[upg] = True |
1150 | @@ -3525,6 +3849,7 @@ |
1151 | PyDict_SetItem(conflicts, cnf, Py_True); |
1152 | } |
1153 | } |
1154 | + |
1155 | } |
1156 | |
1157 | /* self._provides = provides.keys() */ |
1158 | @@ -3535,6 +3860,10 @@ |
1159 | self->_requires = PyDict_Keys(requires); |
1160 | Py_DECREF(requires); |
1161 | |
1162 | + /* self._recommends = recommends.keys() */ |
1163 | + self->_recommends = PyDict_Keys(recommends); |
1164 | + Py_DECREF(recommends); |
1165 | + |
1166 | /* self._upgrades = upgrades.keys() */ |
1167 | self->_upgrades = PyDict_Keys(upgrades); |
1168 | Py_DECREF(upgrades); |
1169 | @@ -3562,6 +3891,7 @@ |
1170 | {"getPackages", (PyCFunction)Cache_getPackages, METH_VARARGS, NULL}, |
1171 | {"getProvides", (PyCFunction)Cache_getProvides, METH_VARARGS, NULL}, |
1172 | {"getRequires", (PyCFunction)Cache_getRequires, METH_VARARGS, NULL}, |
1173 | + {"getRecommends", (PyCFunction)Cache_getRecommends, METH_VARARGS, NULL}, |
1174 | {"getUpgrades", (PyCFunction)Cache_getUpgrades, METH_VARARGS, NULL}, |
1175 | {"getConflicts", (PyCFunction)Cache_getConflicts, METH_VARARGS, NULL}, |
1176 | {"search", (PyCFunction)Cache_search, METH_O, NULL}, |
1177 | @@ -3576,6 +3906,7 @@ |
1178 | {"_packages", T_OBJECT, OFF(_packages), RO, 0}, |
1179 | {"_provides", T_OBJECT, OFF(_provides), RO, 0}, |
1180 | {"_requires", T_OBJECT, OFF(_requires), RO, 0}, |
1181 | + {"_recommends", T_OBJECT, OFF(_recommends), RO, 0}, |
1182 | {"_upgrades", T_OBJECT, OFF(_upgrades), RO, 0}, |
1183 | {"_conflicts", T_OBJECT, OFF(_conflicts), RO, 0}, |
1184 | {"_objmap", T_OBJECT, OFF(_objmap), RO, 0}, |
1185 | |
1186 | === modified file 'smart/channels/rpm_sys.py' |
1187 | --- smart/channels/rpm_sys.py 2009-12-18 14:50:03 +0000 |
1188 | +++ smart/channels/rpm_sys.py 2013-02-12 14:46:20 +0000 |
1189 | @@ -20,7 +20,7 @@ |
1190 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
1191 | # |
1192 | from smart.backends.rpm.header import RPMDBLoader |
1193 | -from smart.backends.rpm.base import getTS |
1194 | +from smart.backends.rpm.base import getTS, rpm_join_dbpath |
1195 | from smart.channel import PackageChannel |
1196 | from smart import * |
1197 | import os |
1198 | @@ -32,9 +32,9 @@ |
1199 | |
1200 | def fetch(self, fetcher, progress): |
1201 | getTS() # Make sure the db exists. |
1202 | - path = os.path.join(sysconf.get("rpm-root", "/"), |
1203 | - sysconf.get("rpm-dbpath", "var/lib/rpm"), |
1204 | - "Packages") |
1205 | + dbdir = rpm_join_dbpath(sysconf.get("rpm-root", "/"), |
1206 | + sysconf.get("rpm-dbpath", "var/lib/rpm")) |
1207 | + path = os.path.join(dbdir, "Packages") |
1208 | digest = os.path.getmtime(path) |
1209 | if digest == self._digest: |
1210 | return True |
1211 | |
1212 | === modified file 'smart/commands/channel.py' |
1213 | --- smart/commands/channel.py 2010-12-06 07:35:59 +0000 |
1214 | +++ smart/commands/channel.py 2013-02-12 14:46:20 +0000 |
1215 | @@ -157,7 +157,17 @@ |
1216 | opts.show is None and opts.yaml is None): |
1217 | iface.warning(_("Can't edit channels information.")) |
1218 | raise Error, _("Configuration is in readonly mode.") |
1219 | - |
1220 | + |
1221 | + # Argument check |
1222 | + opts.check_args_of_option("set", -1) |
1223 | + opts.check_args_of_option("remove", -1) |
1224 | + opts.check_args_of_option("edit", 0) |
1225 | + opts.check_args_of_option("enable", -1) |
1226 | + opts.check_args_of_option("disable", -1) |
1227 | + opts.ensure_action("channel", ["add", "set", "remove", "remove-all", |
1228 | + "list", "show", "yaml", "enable", "disable"]) |
1229 | + opts.check_remaining_args() |
1230 | + |
1231 | if opts.add is not None: |
1232 | if not opts.add and opts.args == ["-"]: |
1233 | newchannels = [] |
1234 | @@ -329,7 +339,10 @@ |
1235 | |
1236 | |
1237 | if opts.yaml is not None: |
1238 | - import yaml |
1239 | + try: |
1240 | + import yaml |
1241 | + except ImportError: |
1242 | + raise Error, _("Please install PyYAML in order to use this function") |
1243 | yamlchannels = {} |
1244 | for alias in (opts.yaml or sysconf.get("channels", ())): |
1245 | channel = sysconf.get(("channels", alias)) |
1246 | |
1247 | === modified file 'smart/commands/check.py' |
1248 | --- smart/commands/check.py 2010-06-22 20:51:32 +0000 |
1249 | +++ smart/commands/check.py 2013-02-12 14:46:20 +0000 |
1250 | @@ -72,6 +72,9 @@ |
1251 | |
1252 | def main(ctrl, opts, reloadchannels=True): |
1253 | |
1254 | + # Argument check |
1255 | + opts.check_args_of_option("channels", 1) |
1256 | + |
1257 | if sysconf.get("auto-update"): |
1258 | from smart.commands import update |
1259 | updateopts = update.parse_options([]) |
1260 | |
1261 | === modified file 'smart/commands/config.py' |
1262 | --- smart/commands/config.py 2010-07-02 13:55:04 +0000 |
1263 | +++ smart/commands/config.py 2013-02-12 14:46:20 +0000 |
1264 | @@ -80,6 +80,12 @@ |
1265 | globals["false"] = False |
1266 | globals["no"] = False |
1267 | |
1268 | + # Check arguments |
1269 | + opts.check_args_of_option("set", -1) |
1270 | + opts.check_args_of_option("remove", -1) |
1271 | + opts.ensure_action("config", ["set", "show", "yaml", "remove"]) |
1272 | + opts.check_remaining_args() |
1273 | + |
1274 | if opts.set: |
1275 | for opt in opts.set: |
1276 | m = SETRE.match(opt) |
1277 | @@ -131,7 +137,10 @@ |
1278 | pprint.pprint(sysconf.get((), hard=True)) |
1279 | |
1280 | if opts.yaml is not None: |
1281 | - import yaml |
1282 | + try: |
1283 | + import yaml |
1284 | + except ImportError: |
1285 | + raise Error, _("Please install PyYAML in order to use this function") |
1286 | if opts.yaml: |
1287 | marker = object() |
1288 | for opt in opts.yaml: |
1289 | |
1290 | === modified file 'smart/commands/download.py' |
1291 | --- smart/commands/download.py 2010-06-22 20:51:32 +0000 |
1292 | +++ smart/commands/download.py 2013-02-12 14:46:20 +0000 |
1293 | @@ -81,6 +81,14 @@ |
1294 | |
1295 | def main(ctrl, opts): |
1296 | |
1297 | + # Argument check |
1298 | + opts.check_args_of_option("target", 1) |
1299 | + opts.check_args_of_option("output", 1) |
1300 | + opts.check_args_of_option("from_urls", -1) |
1301 | + opts.check_args_of_option("from_metalink", -1) |
1302 | + if not opts.args and not opts.from_metalink and not opts.from_urls: |
1303 | + raise Error, _("no package(s) given") |
1304 | + |
1305 | packages = [] |
1306 | if opts.args: |
1307 | if sysconf.get("auto-update"): |
1308 | |
1309 | === modified file 'smart/commands/flag.py' |
1310 | --- smart/commands/flag.py 2010-12-05 15:14:50 +0000 |
1311 | +++ smart/commands/flag.py 2013-02-12 14:46:20 +0000 |
1312 | @@ -138,7 +138,10 @@ |
1313 | |
1314 | |
1315 | if opts.yaml is not None: |
1316 | - import yaml |
1317 | + try: |
1318 | + import yaml |
1319 | + except ImportError: |
1320 | + raise Error, _("Please install PyYAML in order to use this function") |
1321 | yamlflags = {} |
1322 | for flag in opts.yaml or pkgconf.getFlagNames(): |
1323 | flag = flag.strip() |
1324 | |
1325 | === modified file 'smart/commands/info.py' |
1326 | --- smart/commands/info.py 2010-06-22 20:51:32 +0000 |
1327 | +++ smart/commands/info.py 2013-02-12 14:46:20 +0000 |
1328 | @@ -58,6 +58,10 @@ |
1329 | |
1330 | def main(ctrl, opts, reloadchannels=True): |
1331 | |
1332 | + # Argument check |
1333 | + if not opts.args: |
1334 | + raise Error, _("No package(s) given") |
1335 | + |
1336 | if sysconf.get("auto-update"): |
1337 | from smart.commands import update |
1338 | updateopts = update.parse_options([]) |
1339 | |
1340 | === modified file 'smart/commands/install.py' |
1341 | --- smart/commands/install.py 2011-01-30 21:55:29 +0000 |
1342 | +++ smart/commands/install.py 2013-02-12 14:46:20 +0000 |
1343 | @@ -76,6 +76,10 @@ |
1344 | |
1345 | def main(ctrl, opts): |
1346 | |
1347 | + # Argument check |
1348 | + if not opts.args: |
1349 | + raise Error, _("no package(s) given") |
1350 | + |
1351 | if opts.explain: |
1352 | sysconf.set("explain-changesets", True, soft=True) |
1353 | |
1354 | |
1355 | === modified file 'smart/commands/mirror.py' |
1356 | --- smart/commands/mirror.py 2010-07-02 13:55:04 +0000 |
1357 | +++ smart/commands/mirror.py 2013-02-12 14:46:20 +0000 |
1358 | @@ -218,7 +218,10 @@ |
1359 | |
1360 | |
1361 | if opts.yaml: |
1362 | - import yaml |
1363 | + try: |
1364 | + import yaml |
1365 | + except ImportError: |
1366 | + raise Error, _("Please install PyYAML in order to use this function") |
1367 | yamlmirrors = {} |
1368 | mirrors = sysconf.get("mirrors", ()) |
1369 | for origin in mirrors: |
1370 | |
1371 | === modified file 'smart/commands/priority.py' |
1372 | --- smart/commands/priority.py 2010-07-02 13:55:04 +0000 |
1373 | +++ smart/commands/priority.py 2013-02-12 14:46:20 +0000 |
1374 | @@ -117,7 +117,10 @@ |
1375 | |
1376 | |
1377 | elif opts.yaml: |
1378 | - import yaml |
1379 | + try: |
1380 | + import yaml |
1381 | + except ImportError: |
1382 | + raise Error, _("Please install PyYAML in order to use this function") |
1383 | yamlpriorities = {} |
1384 | priorities = sysconf.get("package-priorities", {}) |
1385 | for name in opts.args or priorities: |
1386 | |
1387 | === modified file 'smart/commands/query.py' |
1388 | --- smart/commands/query.py 2010-12-05 15:11:14 +0000 |
1389 | +++ smart/commands/query.py 2013-02-12 14:46:20 +0000 |
1390 | @@ -107,6 +107,8 @@ |
1391 | help=_("show requires for the given packages")) |
1392 | parser.add_option("--show-prerequires", action="store_true", |
1393 | help=_("show requires selecting only pre-dependencies")) |
1394 | + parser.add_option("--show-recommends", action="store_true", |
1395 | + help=_("show recommends for the given packages")) |
1396 | parser.add_option("--show-upgrades", action="store_true", |
1397 | help=_("show upgrades for the given packages")) |
1398 | parser.add_option("--show-conflicts", action="store_true", |
1399 | @@ -488,6 +490,19 @@ |
1400 | continue |
1401 | output.showRequiresProvidedBy(pkg, req, |
1402 | prv, prvpkg) |
1403 | + if pkg.recommends and (opts.show_recommends): |
1404 | + pkg.recommends.sort() |
1405 | + first = True |
1406 | + for req in pkg.recommends: |
1407 | + output.showRecommends(pkg, req) |
1408 | + if opts.show_providedby and req.providedby: |
1409 | + for prv in req.providedby: |
1410 | + prv.packages.sort() |
1411 | + for prvpkg in prv.packages: |
1412 | + if opts.installed and not prvpkg.installed: |
1413 | + continue |
1414 | + output.showRecommendsProvidedBy(pkg, req, |
1415 | + prv, prvpkg) |
1416 | if pkg.upgrades and (opts.show_upgrades or whoupgrades): |
1417 | pkg.upgrades.sort() |
1418 | first = True |
1419 | @@ -594,6 +609,12 @@ |
1420 | def showRequiresProvidedBy(self, pkg, req, prv, prvpkg): |
1421 | pass |
1422 | |
1423 | + def showRecommends(self, pkg, req): |
1424 | + pass |
1425 | + |
1426 | + def showRecommendsProvidedBy(self, pkg, req, prv, prvpkg): |
1427 | + pass |
1428 | + |
1429 | def showUpgrades(self, pkg, upg): |
1430 | pass |
1431 | |
1432 | @@ -619,6 +640,8 @@ |
1433 | self._firstconflictedby = True |
1434 | self._firstrequires = True |
1435 | self._firstrequiresprovidedby = True |
1436 | + self._firstrecommends = True |
1437 | + self._firstrecommendsprovidedby = True |
1438 | self._firstupgrades = True |
1439 | self._firstupgradesprovidedby = True |
1440 | self._firstconflicts = True |
1441 | @@ -711,6 +734,22 @@ |
1442 | name = str(prvpkg) |
1443 | print " ", "%s (%s)" % (name, prv) |
1444 | |
1445 | + def showRecommends(self, pkg, rec): |
1446 | + if self._firstrecommends: |
1447 | + self._firstrecommends = False |
1448 | + print " ", _("Recommends:") |
1449 | + print " ", rec |
1450 | + |
1451 | + def showRecommendsProvidedBy(self, pkg, req, prv, prvpkg): |
1452 | + if self._firstrecommendsprovidedby: |
1453 | + self._firstrecommendsprovidedby = False |
1454 | + print " ", _("Provided By:") |
1455 | + if self.opts.hide_version: |
1456 | + name = prvpkg.name |
1457 | + else: |
1458 | + name = str(prvpkg) |
1459 | + print " ", "%s (%s)" % (name, prv) |
1460 | + |
1461 | def showUpgrades(self, pkg, upg): |
1462 | if self._firstupgrades: |
1463 | self._firstupgrades = False |
1464 | @@ -797,6 +836,18 @@ |
1465 | self._shown[req, prv] = True |
1466 | print ' "Requires: %s" -> "Provides: %s";' % (req, prv) |
1467 | |
1468 | + def showRecommends(self, pkg, req): |
1469 | + if (pkg, req) not in self._shown: |
1470 | + self._shown[pkg, req] = True |
1471 | + print ' "%s" -> "Recommends: %s";' % (pkg, req) |
1472 | + |
1473 | + def showRecommendsProvidedBy(self, pkg, req, prv, prvpkg): |
1474 | + self.showPackage(prvpkg) |
1475 | + self.showProvides(prvpkg, prv) |
1476 | + if (req, prv) not in self._shown: |
1477 | + self._shown[req, prv] = True |
1478 | + print ' "Recommends: %s" -> "Provides: %s";' % (req, prv) |
1479 | + |
1480 | def showUpgrades(self, pkg, upg): |
1481 | if (pkg, upg) not in self._shown: |
1482 | self._shown[pkg, upg] = True |
1483 | |
1484 | === modified file 'smart/commands/reinstall.py' |
1485 | --- smart/commands/reinstall.py 2010-06-22 20:51:32 +0000 |
1486 | +++ smart/commands/reinstall.py 2013-02-12 14:46:20 +0000 |
1487 | @@ -68,7 +68,11 @@ |
1488 | return opts |
1489 | |
1490 | def main(ctrl, opts): |
1491 | - |
1492 | + |
1493 | + # Argument check |
1494 | + if not opts.args: |
1495 | + raise Error, _("no package(s) given") |
1496 | + |
1497 | if opts.explain: |
1498 | sysconf.set("explain-changesets", True, soft=True) |
1499 | |
1500 | |
1501 | === modified file 'smart/commands/remove.py' |
1502 | --- smart/commands/remove.py 2010-06-22 20:51:32 +0000 |
1503 | +++ smart/commands/remove.py 2013-02-12 14:46:20 +0000 |
1504 | @@ -74,6 +74,10 @@ |
1505 | |
1506 | def main(ctrl, opts): |
1507 | |
1508 | + # Argument check |
1509 | + if not opts.args: |
1510 | + raise Error, _("no package(s) given") |
1511 | + |
1512 | if opts.explain: |
1513 | sysconf.set("explain-changesets", True, soft=True) |
1514 | |
1515 | |
1516 | === modified file 'smart/commands/search.py' |
1517 | --- smart/commands/search.py 2010-11-28 13:12:37 +0000 |
1518 | +++ smart/commands/search.py 2013-02-12 14:46:20 +0000 |
1519 | @@ -44,6 +44,8 @@ |
1520 | def parse_options(argv): |
1521 | opts = query.parse_options(argv, usage=USAGE, \ |
1522 | description=DESCRIPTION, examples=EXAMPLES) |
1523 | + if not argv: |
1524 | + raise Error, _("Search expression not specified") |
1525 | opts.name = opts.args |
1526 | opts.summary = opts.args |
1527 | opts.description = opts.args |
1528 | |
1529 | === modified file 'smart/commands/upgrade.py' |
1530 | --- smart/commands/upgrade.py 2010-12-05 15:11:14 +0000 |
1531 | +++ smart/commands/upgrade.py 2013-02-12 14:46:20 +0000 |
1532 | @@ -91,6 +91,9 @@ |
1533 | |
1534 | def main(ctrl, opts): |
1535 | |
1536 | + # Argument check |
1537 | + opts.check_args_of_option("flag", 1) |
1538 | + |
1539 | if opts.explain: |
1540 | sysconf.set("explain-changesets", True, soft=True) |
1541 | |
1542 | |
1543 | === modified file 'smart/control.py' |
1544 | --- smart/control.py 2011-10-05 22:02:21 +0000 |
1545 | +++ smart/control.py 2013-02-12 14:46:20 +0000 |
1546 | @@ -447,7 +447,7 @@ |
1547 | queue = marked.keys() |
1548 | while queue: |
1549 | pkg = queue.pop(0) |
1550 | - for req in pkg.requires: |
1551 | + for req in pkg.requires + pkg.recommends: |
1552 | for prv in req.providedby: |
1553 | for prvpkg in prv.packages: |
1554 | if (prvpkg.installed and |
1555 | @@ -794,7 +794,7 @@ |
1556 | pkglst = [] |
1557 | for pkg in changeset: |
1558 | n = 0 |
1559 | - for req in pkg.requires: |
1560 | + for req in pkg.requires + pkg.recommends: |
1561 | for prv in req.providedby: |
1562 | for prvpkg in prv.packages: |
1563 | if changeset.get(prvpkg) is INSTALL: |
1564 | |
1565 | === modified file 'smart/plugins/detectsys.py' |
1566 | --- smart/plugins/detectsys.py 2011-09-22 20:06:16 +0000 |
1567 | +++ smart/plugins/detectsys.py 2013-02-12 14:46:20 +0000 |
1568 | @@ -20,10 +20,11 @@ |
1569 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
1570 | # |
1571 | from smart import * |
1572 | +from smart.backends.rpm.base import rpm_join_dbpath |
1573 | import os |
1574 | |
1575 | def detectRPMSystem(): |
1576 | - dir = os.path.join(sysconf.get("rpm-root", "/"), |
1577 | + dir = rpm_join_dbpath(sysconf.get("rpm-root", "/"), |
1578 | sysconf.get("rpm-dbpath", "var/lib/rpm")) |
1579 | file = os.path.join(dir, "Packages") |
1580 | if os.path.exists(file): |
1581 | |
1582 | === modified file 'smart/searcher.py' |
1583 | --- smart/searcher.py 2010-06-22 10:41:16 +0000 |
1584 | +++ smart/searcher.py 2013-02-12 14:46:20 +0000 |
1585 | @@ -45,9 +45,9 @@ |
1586 | |
1587 | - provides is matched in Provides.search(), for the same reason. |
1588 | |
1589 | - - requires, upgrades, and conflicts don't have special searching |
1590 | - methods. Instead, their usual match() method is given an instance |
1591 | - of the Provides type. |
1592 | + - requires, recommends, upgrades, and conflicts don't have special |
1593 | + searching methods. Instead, their usual match() method is given |
1594 | + an instance of the Provides type. |
1595 | |
1596 | - group, path, url, and other information which is found by |
1597 | PackageInfo, is searched by the Loader.search() method and |
1598 | @@ -62,6 +62,7 @@ |
1599 | self.nameversion = [] |
1600 | self.provides = [] |
1601 | self.requires = [] |
1602 | + self.recommends = [] |
1603 | self.upgrades = [] |
1604 | self.conflicts = [] |
1605 | self.path = [] |
1606 | @@ -76,6 +77,7 @@ |
1607 | del self.nameversion[:] |
1608 | del self.provides[:] |
1609 | del self.requires[:] |
1610 | + del self.recommends[:] |
1611 | del self.upgrades[:] |
1612 | del self.conflicts[:] |
1613 | del self.path[:] |
1614 | @@ -122,6 +124,8 @@ |
1615 | self.addProvides(s[9:], cutoff) |
1616 | elif s.startswith("requires:"): |
1617 | self.addRequires(s[9:]) |
1618 | + elif s.startswith("recommends:"): |
1619 | + self.addRecommends(s[11:]) |
1620 | elif s.startswith("upgrades:"): |
1621 | self.addUpgrades(s[9:]) |
1622 | elif s.startswith("conflicts:"): |
1623 | @@ -151,6 +155,7 @@ |
1624 | return s and ( |
1625 | s.startswith("provides:") or |
1626 | s.startswith("requires:") or |
1627 | + s.startswith("recommends:") or |
1628 | s.startswith("upgrades:") or |
1629 | s.startswith("conflicts:") or |
1630 | s.startswith("url:") or |
1631 | @@ -182,6 +187,9 @@ |
1632 | def addRequires(self, s): |
1633 | self.requires.append(self._buildProvides(s)) |
1634 | |
1635 | + def addRecommends(self, s): |
1636 | + self.recommends.append(self._buildProvides(s)) |
1637 | + |
1638 | def addUpgrades(self, s): |
1639 | self.upgrades.append(self._buildProvides(s)) |
1640 | |
1641 | |
1642 | === modified file 'smart/transaction.py' |
1643 | --- smart/transaction.py 2010-06-22 17:01:09 +0000 |
1644 | +++ smart/transaction.py 2013-02-12 14:46:20 +0000 |
1645 | @@ -573,7 +573,7 @@ |
1646 | self._remove(namepkg, changeset, locked, pending, depth) |
1647 | |
1648 | # Install packages required by this one. |
1649 | - for req in pkg.requires: |
1650 | + for req in pkg.requires + pkg.recommends: |
1651 | |
1652 | # Check if someone is already providing it. |
1653 | prvpkgs = {} |
1654 | @@ -596,8 +596,12 @@ |
1655 | |
1656 | if not prvpkgs: |
1657 | # No packages provide it at all. Give up. |
1658 | - raise Failed, _("Can't install %s: no package provides %s") % \ |
1659 | - (pkg, req) |
1660 | + if req in pkg.requires: |
1661 | + raise Failed, _("Can't install %s: no package provides %s") % \ |
1662 | + (pkg, req) |
1663 | + else: |
1664 | + # It's only a recommend, skip |
1665 | + continue |
1666 | |
1667 | if len(prvpkgs) == 1: |
1668 | # Don't check locked here. prvpkgs was |
1669 | @@ -1359,7 +1363,7 @@ |
1670 | set = self._changeset |
1671 | |
1672 | # Check all dependencies needed by this package. |
1673 | - for req in pkg.requires: |
1674 | + for req in pkg.requires + pkg.recommends: |
1675 | |
1676 | # Check if any already installed or to be installed |
1677 | # package will solve the problem. |
1678 | @@ -1424,8 +1428,9 @@ |
1679 | |
1680 | # There are no solutions for the problem. |
1681 | # Should we really care about it? |
1682 | - if (self._forcerequires or |
1683 | - isinstance(req, PreRequires)): |
1684 | + if ((self._forcerequires or |
1685 | + isinstance(req, PreRequires)) |
1686 | + and req in pkg.requires): |
1687 | raise Error, _("No providers for '%s', " |
1688 | "required by '%s'") % (req, pkg) |
1689 | |
1690 | @@ -1625,7 +1630,7 @@ |
1691 | return n |
1692 | |
1693 | def forwardRequires(pkg, map): |
1694 | - for req in pkg.requires: |
1695 | + for req in pkg.requires + pkg.recommends: |
1696 | if req not in map: |
1697 | map[req] = True |
1698 | for prv in req.providedby: |
1699 | @@ -1794,6 +1799,15 @@ |
1700 | iface.info(_("Unsatisfied dependency: %s requires %s") % |
1701 | (pkg, req)) |
1702 | |
1703 | + for req in pkg.recommends: |
1704 | + for prv in req.providedby: |
1705 | + for prvpkg in prv.packages: |
1706 | + if prvpkg in relateset: |
1707 | + break |
1708 | + else: |
1709 | + continue |
1710 | + break |
1711 | + |
1712 | if not pkg.installed: |
1713 | continue |
1714 | |
1715 | |
1716 | === modified file 'smart/util/optparse.py' |
1717 | --- smart/util/optparse.py 2005-06-14 17:41:24 +0000 |
1718 | +++ smart/util/optparse.py 2013-02-12 14:46:20 +0000 |
1719 | @@ -70,6 +70,8 @@ |
1720 | import types |
1721 | import textwrap |
1722 | from gettext import gettext as _ |
1723 | +from smart import Error |
1724 | +import re |
1725 | |
1726 | def _repr(self): |
1727 | return "<%s at 0x%x: %s>" % (self.__class__.__name__, id(self), self) |
1728 | @@ -708,6 +710,12 @@ |
1729 | self.action, self.dest, opt, value, values, parser) |
1730 | |
1731 | def take_action(self, action, dest, opt, value, values, parser): |
1732 | + # Keep all the options in the command line in the '_given_opts' array |
1733 | + # This will be used later to validate the command line |
1734 | + given_opts = getattr(parser.values, "_given_opts", []) |
1735 | + user_opt = re.sub(r"^\-*", "", opt).replace("-", "_") |
1736 | + given_opts.append(user_opt) |
1737 | + setattr(parser.values, "_given_opts", given_opts) |
1738 | if action == "store": |
1739 | setattr(values, dest, value) |
1740 | elif action == "store_const": |
1741 | @@ -819,6 +827,54 @@ |
1742 | setattr(self, attr, value) |
1743 | return getattr(self, attr) |
1744 | |
1745 | + # Check if the given option has the specified number of arguments |
1746 | + # Raise an error if the option has an invalid number of arguments |
1747 | + # A negative number for 'nargs' means "at least |nargs| arguments are needed" |
1748 | + def check_args_of_option(self, opt, nargs, err=None): |
1749 | + given_opts = getattr(self, "_given_opts", []) |
1750 | + if not opt in given_opts: |
1751 | + return |
1752 | + values = getattr(self, opt, []) |
1753 | + if type(values) != type([]): |
1754 | + return |
1755 | + if nargs < 0: |
1756 | + nargs = -nargs |
1757 | + if len(values) >= nargs: |
1758 | + return |
1759 | + if not err: |
1760 | + if nargs == 1: |
1761 | + err = _("Option '%s' requires at least one argument") % opt |
1762 | + else: |
1763 | + err = _("Option '%s' requires at least %d arguments") % (opt, nargs) |
1764 | + raise Error, err |
1765 | + elif nargs == 0: |
1766 | + if len( values ) == 0: |
1767 | + return |
1768 | + raise Error, err |
1769 | + else: |
1770 | + if len(values) == nargs: |
1771 | + return |
1772 | + if not err: |
1773 | + if nargs == 1: |
1774 | + err = _("Option '%s' requires one argument") % opt |
1775 | + else: |
1776 | + err = _("Option '%s' requires %d arguments") % (opt, nargs) |
1777 | + raise Error, err |
1778 | + |
1779 | + # Check that at least one of the options in 'actlist' was given as an argument |
1780 | + # to the command 'cmdname' |
1781 | + def ensure_action(self, cmdname, actlist): |
1782 | + given_opts = getattr(self, "_given_opts", []) |
1783 | + for action in actlist: |
1784 | + if action in given_opts: |
1785 | + return |
1786 | + raise Error, _("No action specified for command '%s'") % cmdname |
1787 | + |
1788 | + # Check if there are any other arguments left after parsing the command line and |
1789 | + # raise an error if such arguments are found |
1790 | + def check_remaining_args(self): |
1791 | + if self.args: |
1792 | + raise Error, _("Invalid argument(s) '%s'" % str(self.args)) |
1793 | |
1794 | class OptionContainer: |
1795 |