From 6d9328b0c61620b3a91e3dd6ca4721fd87aea16f Mon Sep 17 00:00:00 2001 From: Michael Schroeder Date: Thu, 17 Feb 2011 19:41:09 +0100 Subject: [PATCH] - commit current state of python packagemanager. Is now able to install/erase packages --- examples/pysolv.py | 196 ++++++++++++++++++-- examples/solv.i | 436 ++++++++++++++++++++++++++++++++++++++------- 2 files changed, 555 insertions(+), 77 deletions(-) diff --git a/examples/pysolv.py b/examples/pysolv.py index e14fd841..d71d4007 100644 --- a/examples/pysolv.py +++ b/examples/pysolv.py @@ -9,8 +9,9 @@ import tempfile import time import subprocess import fnmatch +import rpm from stat import * -from solv import Pool, Repo, Dataiterator, Job +from solv import Pool, Repo, Dataiterator, Job, Solver, Transaction from iniparse import INIConfig from optparse import OptionParser @@ -168,7 +169,7 @@ def limitjobs(pool, jobs, flags, evr): how |= Job.SOLVER_SETEVR else: how |= Job.SOLVER_SETEV - njobs.append(Job(how, what)) + njobs.append(pool.Job(how, what)) return njobs def limitjobs_arch(pool, jobs, flags, evr): @@ -198,9 +199,9 @@ def mkjobs(pool, cmd, arg): if len(matches): print "[using file list match for '%s']" % arg if len(matches) > 1: - return [ Job(Job.SOLVER_SOLVABLE_ONE_OF, pool.towhatprovides(matches)) ] + return [ pool.Job(Job.SOLVER_SOLVABLE_ONE_OF, pool.towhatprovides(matches)) ] else: - return [ Job(Job.SOLVER_SOLVABLE | Job.SOLVER_NOAUTOSET, matches[0]) ] + return [ pool.Job(Job.SOLVER_SOLVABLE | Job.SOLVER_NOAUTOSET, matches[0]) ] m = re.match(r'(.+?)\s*([<=>]+)\s*(.+?)$', arg) if m: (name, rel, evr) = m.group(1, 2, 3); @@ -245,12 +246,12 @@ def depglob(pool, name, globname, globdep): match = False for s in pool.providers(id): if globname and s.nameid == id: - return [ Job(Job.SOLVER_SOLVABLE_NAME, id) ] + return [ pool.Job(Job.SOLVER_SOLVABLE_NAME, id) ] match = True if match: if globname and globdep: print "[using capability match for '%s']" % name - return [ Job(Job.SOLVER_SOLVABLE_PROVIDES, id) ] + return [ pool.Job(Job.SOLVER_SOLVABLE_PROVIDES, id) ] if not re.search(r'[[*?]', name): return [] if globname: @@ -260,7 +261,7 @@ def depglob(pool, name, globname, globdep): if s.installable() and fnmatch.fnmatch(s.name, name): idmatches[s.nameid] = True if len(idmatches): - return [ Job(Job.SOLVER_SOLVABLE_NAME, id) for id in sorted(idmatches.keys()) ] + return [ pool.Job(Job.SOLVER_SOLVABLE_NAME, id) for id in sorted(idmatches.keys()) ] if globdep: # try dependency glob idmatches = {} @@ -269,7 +270,7 @@ def depglob(pool, name, globname, globdep): idmatches[id] = True if len(idmatches): print "[using capability match for '%s']" % name - return [ Job(Job.SOLVER_SOLVABLE_PROVIDES, id) for id in sorted(idmatches.keys()) ] + return [ pool.Job(Job.SOLVER_SOLVABLE_PROVIDES, id) for id in sorted(idmatches.keys()) ] return [] @@ -379,7 +380,7 @@ if cmd == 'se' or cmd == 'search': matches[di.solvid] = True for solvid in sorted(matches.keys()): print " - %s: %s" % (pool.solvid2str(solvid), pool.lookup_str(solvid, solv.SOLVABLE_SUMMARY)) - exit(0) + sys.exit(0) # XXX: insert rewrite_repos function @@ -394,7 +395,7 @@ for arg in args: if cmd == 'li' or cmd == 'list' or cmd == 'info': if not jobs: print "no package matched." - exit(1) + sys.exit(1) for job in jobs: for s in pool.jobsolvables(job): if cmd == 'info': @@ -412,14 +413,14 @@ if cmd == 'li' or cmd == 'list' or cmd == 'info': else: print " - %s [%s]" % (s.str(), s.repo.name) print " %s" % s.lookup_str(solv.SOLVABLE_SUMMARY) - exit(0) + sys.exit(0) if cmd == 'in' or cmd == 'install' or cmd == 'rm' or cmd == 'erase' or cmd == 'up': if cmd == 'up' and not jobs: - jobs = [ Job(Job.SOLVER_SOLVABLE_ALL, 0) ] + jobs = [ pool.Job(Job.SOLVER_SOLVABLE_ALL, 0) ] if not jobs: print "no package matched." - exit(1) + sys.exit(1) for job in jobs: if cmd == 'up': if job.how == Job.SOLVER_SOLVABLE_ALL or filter(lambda s: s.isinstalled(), pool.jobsolvables(job)): @@ -433,12 +434,177 @@ if cmd == 'in' or cmd == 'install' or cmd == 'rm' or cmd == 'erase' or cmd == 'u #pool.set_debuglevel(2) solver = pool.create_solver() + solver.ignorealreadyrecommended = True problems = solver.solve(jobs) if problems: for problem in problems: print "Problem %d:" % problem.id r = problem.findproblemrule() - type, source, target, dep = solver.ruleinfo(r) - print type, source, target, dep + type, source, target, dep = r.info() + if type == Solver.SOLVER_RULE_DISTUPGRADE: + print "%s does not belong to a distupgrade repository" % source.str() + elif type == Solver.SOLVER_RULE_INFARCH: + print "%s has inferiour architecture" % source.str() + elif type == Solver.SOLVER_RULE_UPDATE: + print "problem with installed package %s" % source.str() + elif type == Solver.SOLVER_RULE_JOB: + print "conflicting requests" + elif type == Solver.SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP: + print "nothing provides requested %s" % pool.dep2str(dep) + elif type == Solver.SOLVER_RULE_RPM: + print "some dependency problem" + elif type == Solver.SOLVER_RULE_RPM_NOT_INSTALLABLE: + print "package %s is not installable" % source.str() + elif type == Solver.SOLVER_RULE_RPM_NOTHING_PROVIDES_DEP: + print "nothing provides %s needed by %s" % (pool.dep2str(dep), source.str()) + elif type == Solver.SOLVER_RULE_RPM_SAME_NAME: + print "cannot install both %s and %s" % (source.str(), target.str()) + elif type == Solver.SOLVER_RULE_RPM_PACKAGE_CONFLICT: + print "package %s conflicts with %s provided by %s" % (source.str(), pool.dep2str(dep), target.str()) + elif type == Solver.SOLVER_RULE_RPM_PACKAGE_OBSOLETES: + print "package %s obsoletes %s provided by %s" % (source.str(), pool.dep2str(dep), target.str()) + elif type == Solver.SOLVER_RULE_RPM_INSTALLEDPKG_OBSOLETES: + print "installed package %s obsoletes %s provided by %s" % (source.str(), pool.dep2str(dep), target.str()) + elif type == Solver.SOLVER_RULE_RPM_IMPLICIT_OBSOLETES: + print "package %s implicitely obsoletes %s provided by %s" % (source.str(), pool.dep2str(dep), target.str()) + elif type == Solver.SOLVER_RULE_RPM_PACKAGE_REQUIRES: + print "package %s requires %s, but none of the providers can be installed" % (source.str(), pool.dep2str(dep)) + elif type == Solver.SOLVER_RULE_RPM_SELF_CONFLICT: + print "package %s conflicts with %s provided by itself" % (source.str(), pool.dep2str(dep)) + else: + print "bad rule type", type + solutions = problem.solutions() + for solution in solutions: + print " Solution %d:" % solution.id + elements = solution.elements() + for element in elements: + etype = element.type + if etype == Solver.SOLVER_SOLUTION_JOB: + print " - remove job %d" % element.jobidx + elif etype == Solver.SOLVER_SOLUTION_INFARCH: + if element.solvable.isinstalled(): + print " - keep %s despite the inferior architecture" % element.solvable.str() + else: + print " - install %s despite the inferior architecture" % element.solvable.str() + elif etype == Solver.SOLVER_SOLUTION_DISTUPGRADE: + if element.solvable.isinstalled(): + print " - keep obsolete %s" % element.solvable.str() + else: + print " - install %s from excluded repository" % element.solvable.str() + elif etype == Solver.SOLVER_SOLUTION_REPLACE: + print " - allow replacement of %s with %s" % (element.solvable.str(), element.replacement.str()) + elif etype == Solver.SOLVER_SOLUTION_DEINSTALL: + print " - allow deinstallation of %s" % element.solvable.str() + sys.exit(1) + # no problems, show transaction + trans = solver.transaction() + del solver + if trans.isempty(): + print "Nothing to do." + sys.exit(0) + print + print "Transaction summary:" + print + for ctype, fromid, toid, pkgs in trans.classify(): + if ctype == Transaction.SOLVER_TRANSACTION_ERASE: + print "%d erased packages:" % len(pkgs) + elif ctype == Transaction.SOLVER_TRANSACTION_INSTALL: + print "%d installed packages:" % len(pkgs) + elif ctype == Transaction.SOLVER_TRANSACTION_REINSTALLED: + print "%d reinstalled packages:" % len(pkgs) + elif ctype == Transaction.SOLVER_TRANSACTION_DOWNGRADED: + print "%d downgraded packages:" % len(pkgs) + elif ctype == Transaction.SOLVER_TRANSACTION_CHANGED: + print "%d changed packages:" % len(pkgs) + elif ctype == Transaction.SOLVER_TRANSACTION_UPGRADED: + print "%d upgraded packages:" % len(pkgs) + elif ctype == Transaction.SOLVER_TRANSACTION_VENDORCHANGE: + print "%d vendor changes from '%s' to '%s':" % (len(pkgs), pool.id2str(fromid), pool.id2str(toid)) + elif ctype == Transaction.SOLVER_TRANSACTION_ARCHCHANGE: + print "%d arch changes from '%s' to '%s':" % (len(pkgs), pool.id2str(fromid), pool.id2str(toid)) + else: + continue + for p in pkgs: + if ctype == Transaction.SOLVER_TRANSACTION_UPGRADED or ctype == Transaction.SOLVER_TRANSACTION_DOWNGRADED: + op = trans.othersolvable(p) + print " - %s -> %s" % (p.str(), op.str()) + else: + print " - %s" % p.str() + print + print "install size change: %d K" % trans.calc_installsizechange() + print # vim: sw=4 et + while True: + sys.stdout.write("OK to continue (y/n)? ") + sys.stdout.flush() + yn = sys.stdin.readline().strip() + if yn == 'y': break + if yn == 'n': sys.exit(1) + newpkgs, keptpkgs = trans.installedresult() + newpkgsfp = {} + if newpkgs: + downloadsize = 0 + for p in newpkgs: + downloadsize += p.lookup_num(solv.SOLVABLE_DOWNLOADSIZE); + print "Downloading %d packages, %d K" % (len(newpkgs), downloadsize) + for p in newpkgs: + repo = p.repo.appdata + location, medianr = p.lookup_location() + if not location: + continue + if sysrepo['handle'].nsolvables: + pname = p.name + di = p.repo.dataiterator_new(solv.SOLVID_META, solv.DELTA_PACKAGE_NAME, pname, Dataiterator.SEARCH_STRING) + di.prepend_keyname(solv.REPOSITORY_DELTAINFO); + for d in di: + d.setpos_parent() + if pool.lookup_id(solv.SOLVID_POS, solv.DELTA_PACKAGE_EVR) != p.evrid or pool.lookup_id(solv.SOLVID_POS, solv.DELTA_PACKAGE_ARCH) != p.archid: + continue + baseevrid = pool.lookup_id(solv.SOLVID_POS, solv.DELTA_BASE_EVR) + for installedp in pool.providers(p.nameid): + if installedp.isinstalled() and installedp.nameid == p.nameid and installedp.archid == p.archid and installedp.evrid == baseevrid: + candidate = installedp + # add applydeltarpm code here... + chksum, chksumtype = p.lookup_bin_checksum(solv.SOLVABLE_CHECKSUM); + f = curlfopen(repo, location, False, chksum, chksumtype) + if not f: + sys.exit("\n%s: %s not found in repository" % (repo['alias'], location)) + newpkgsfp[p.id] = f + sys.stdout.write(".") + sys.stdout.flush() + print + print "Committing transaction:" + print + ts = rpm.TransactionSet('/') + for p in trans.steps(): + type = trans.steptype(p, Transaction.SOLVER_TRANSACTION_RPM_ONLY) + if type == Transaction.SOLVER_TRANSACTION_ERASE: + rpmdbid = p.lookup_num(solv.RPM_RPMDBID) + if not rpmdbid: + sys.exit("\ninternal error: installed package %s has no rpmdbid\n" % p.str()) + ts.addErase(rpmdbid) + elif type == Transaction.SOLVER_TRANSACTION_INSTALL: + f = newpkgsfp[p.id] + h = ts.hdrFromFdno(solv.xfileno(f)) + os.lseek(solv.xfileno(f), 0, os.SEEK_SET) + ts.addInstall(h, p, 'u') + elif type == Transaction.SOLVER_TRANSACTION_MULTIINSTALL: + f = newpkgsfp[p.id] + h = ts.hdrFromFdno(solv.xfileno(f)) + os.lseek(solv.xfileno(f), 0, os.SEEK_SET) + ts.addInstall(h, p, 'i') + checkproblems = ts.check() + if checkproblems: + print checkproblems + sys.exit("Sorry.") + ts.order() + def runCallback(reason, amount, total, p, fps): + if reason == rpm.RPMCALLBACK_INST_OPEN_FILE: + return solv.xfileno(fps[p.id]) + if reason == rpm.RPMCALLBACK_INST_START: + print "install", p.str() + runproblems = ts.run(runCallback, newpkgsfp) + if runproblems: + print runproblems + sys.exit(1) diff --git a/examples/solv.i b/examples/solv.i index 4aaeba42..c175f357 100644 --- a/examples/solv.i +++ b/examples/solv.i @@ -1,3 +1,12 @@ +# +##if defined(SWIGRUBY) +# %rename("to_s") string(); +##endif +##if defined(SWIGPYTHON) +# %rename("__str__") string(); +##endif +# + %module solv %typemap(in) (Id *idarray, int idarraylen) { @@ -90,13 +99,20 @@ #define true 1 #define false 1 +#define SOLVER_SOLUTION_DEINSTALL -100 +#define SOLVER_SOLUTION_REPLACE -101 typedef struct chksum Chksum; typedef int bool; typedef struct { Pool* pool; Id id; -} xSolvable; +} XSolvable; + +typedef struct { + Solver* solv; + Id id; +} XRule; typedef struct { Pool *pool; @@ -114,6 +130,7 @@ typedef struct { } Repo_solvable_iterator; typedef struct { + Pool *pool; Id how; Id what; } Job; @@ -123,13 +140,22 @@ typedef struct { Id id; } Problem; -static inline xSolvable *xSolvable_create(Pool *pool, Id id) -{ - xSolvable *s = sat_calloc(sizeof(*s), 1); - s->pool = pool; - s->id = id; - return s; -} +typedef struct { + Solver *solv; + Id problemid; + Id id; +} Solution; + +typedef struct { + Solver *solv; + Id problemid; + Id solutionid; + Id id; + + Id type; + Id p; + Id rp; +} Solutionelement; %} @@ -147,6 +173,16 @@ typedef int Id; %constant int REL_ARCH; +typedef struct { + Pool* const pool; + Id const id; +} XSolvable; + +typedef struct { + Solver* const solv; + Id const id; +} XRule; + # put before pool/repo so we can access the constructor %nodefaultctor Dataiterator; %nodefaultdtor Dataiterator; @@ -156,6 +192,13 @@ typedef struct _Dataiterator { const Id solvid; } Dataiterator; +typedef struct { + Pool * const pool; + Id how; + Id what; +} Job; + +%nodefaultctor Pool; %nodefaultdtor Pool; typedef struct { } Pool; @@ -166,25 +209,31 @@ typedef struct _Repo { const char * const name; int priority; int subpriority; + int const nsolvables; +#if defined(SWIGPYTHON) PyObject *appdata; +#endif +#if defined(SWIGRUBY) + VALUE appdata; +#endif +#if defined(SWIGPERL) + SV *appdata; +#endif } Repo; -%nodefaultctor xSolvable; -typedef struct { - Pool* const pool; - const Id id; -} xSolvable; - %nodefaultctor Pool_solvable_iterator; typedef struct {} Pool_solvable_iterator; + %nodefaultctor Pool_repo_iterator; typedef struct {} Pool_repo_iterator; + %nodefaultctor Repo_solvable_iterator; typedef struct {} Repo_solvable_iterator; %nodefaultctor Solver; %nodefaultdtor Solver; typedef struct { + Pool * const pool; bool ignorealreadyrecommended; bool dosplitprovides; bool fixsystem; @@ -200,6 +249,7 @@ typedef struct chksum {} Chksum; %rename(xfopen) sat_xfopen; %rename(xfopen_fd) sat_xfopen_fd; %rename(xfclose) sat_xfclose; +%rename(xfileno) sat_xfileno; FILE *sat_xfopen(const char *fn); FILE *sat_xfopen_fd(const char *fn, int fd); @@ -207,17 +257,38 @@ FILE *sat_xfopen_fd(const char *fn, int fd); int sat_xfclose(FILE *fp) { return fclose(fp); } + int sat_xfileno(FILE *fp) { + return fileno(fp); + } } -typedef struct { - Id how; - Id what; -} Job; typedef struct { - Solver *solv; - Id id; + Solver * const solv; + Id const id; } Problem; +typedef struct { + Solver * const solv; + Id const problemid; + Id const id; +} Solution; + +typedef struct { + Solver *const solv; + Id const problemid; + Id const solutionid; + Id const id; + Id const type; +} Solutionelement; + +%nodefaultctor Transaction; +%nodefaultdtor Transaction; +typedef struct { + Pool * const pool; +} Transaction; + + + %extend Job { static const Id SOLVER_SOLVABLE = SOLVER_SOLVABLE; static const Id SOLVER_SOLVABLE_NAME = SOLVER_SOLVABLE_NAME; @@ -249,8 +320,9 @@ typedef struct { static const Id SOLVER_NOAUTOSET = SOLVER_NOAUTOSET; static const Id SOLVER_SETMASK = SOLVER_SETMASK; - Job(Id how, Id what) { - Job *job = sat_calloc(sizeof(*job), 1); + Job(Pool *pool, Id how, Id what) { + Job *job = sat_calloc(1, sizeof(*job)); + job->pool = pool; job->how = how; job->what = what; return job; @@ -265,7 +337,7 @@ typedef struct { sat_chksum_free($self, 0); } void add(const char *str) { - sat_chksum_add($self, str, strlen((char *)$self)); + sat_chksum_add($self, str, strlen((char *)str)); } void addfp(FILE *fp) { char buf[4096]; @@ -369,7 +441,7 @@ typedef struct { %{ SWIGINTERN Pool_solvable_iterator * Pool_solvables_get(Pool *pool) { Pool_solvable_iterator *s; - s = sat_calloc(sizeof(*s), 1); + s = sat_calloc(1, sizeof(*s)); s->pool = pool; s->id = 0; return s; @@ -379,7 +451,7 @@ typedef struct { %{ SWIGINTERN Pool_repo_iterator * Pool_repos_get(Pool *pool) { Pool_repo_iterator *s; - s = sat_calloc(sizeof(*s), 1); + s = sat_calloc(1, sizeof(*s)); s->pool = pool; s->id = 0; return s; @@ -425,13 +497,18 @@ typedef struct { queue_push(&q, p); return q; } + Job *Job(Id how, Id what) { + return new_Job($self, how, what); + } - %pythoncode %{ +#if defined(SWIGPYTHON) + %pythoncode { def jobsolvables (self, *args): return [ self.solvables[id] for id in self.jobsolvids(*args) ] def providers(self, *args): return [ self.solvables[id] for id in self.providerids(*args) ] - %} + } +#endif Id towhatprovides(Queue q) { return pool_queuetowhatprovides($self, &q); @@ -532,7 +609,7 @@ typedef struct { %{ SWIGINTERN Repo_solvable_iterator * Repo_solvables_get(Repo *repo) { Repo_solvable_iterator *s; - s = sat_calloc(sizeof(*s), 1); + s = sat_calloc(1, sizeof(*s)); s->repo = repo; s->id = 0; return s; @@ -550,7 +627,7 @@ typedef struct { static const int SEARCH_COMPLETE_FILELIST = SEARCH_COMPLETE_FILELIST; Dataiterator(Pool *pool, Repo *repo, Id p, Id key, const char *match, int flags) { - Dataiterator *di = sat_calloc(sizeof(*di), 1); + Dataiterator *di = sat_calloc(1, sizeof(*di)); dataiterator_init(di, pool, repo, p, key, match, flags); return di; } @@ -573,7 +650,7 @@ typedef struct { if (!dataiterator_step($self)) { return 0; } - ndi = sat_calloc(sizeof(*ndi), 1); + ndi = sat_calloc(1, sizeof(*ndi)); dataiterator_init_clone(ndi, $self); return ndi; } @@ -588,10 +665,10 @@ typedef struct { } %newobject solvable; - xSolvable * const solvable; + XSolvable * const solvable; %{ - SWIGINTERN xSolvable *Dataiterator_solvable_get(Dataiterator *di) { - return di->solvid ? xSolvable_create(di->pool, di->solvid) : 0; + SWIGINTERN XSolvable *Dataiterator_solvable_get(Dataiterator *di) { + return new_XSolvable(di->pool, di->solvid); } %} Id key_id() { @@ -636,21 +713,21 @@ typedef struct { } } %newobject next; - xSolvable *next() { + XSolvable *next() { Pool *pool = $self->pool; - xSolvable *s; + XSolvable *s; if ($self->id >= pool->nsolvables) return 0; while (++$self->id < pool->nsolvables) if (pool->solvables[$self->id].repo) - return xSolvable_create(pool, $self->id); + return new_XSolvable(pool, $self->id); return 0; } %newobject __getitem__; - xSolvable *__getitem__(Id key) { + XSolvable *__getitem__(Id key) { Pool *pool = $self->pool; if (key > 0 && key < pool->nsolvables && pool->solvables[key].repo) - return xSolvable_create(pool, key); + return new_XSolvable(pool, key); return 0; } } @@ -697,37 +774,45 @@ typedef struct { } } %newobject next; - xSolvable *next() { + XSolvable *next() { Repo *repo = $self->repo; Pool *pool = repo->pool; - xSolvable *s; + XSolvable *s; if (repo->start > 0 && $self->id < repo->start) $self->id = repo->start - 1; if ($self->id >= repo->end) return 0; while (++$self->id < repo->end) if (pool->solvables[$self->id].repo == repo) - return xSolvable_create(pool, $self->id); + return new_XSolvable(pool, $self->id); return 0; } %newobject __getitem__; - xSolvable *__getitem__(Id key) { + XSolvable *__getitem__(Id key) { Repo *repo = $self->repo; Pool *pool = repo->pool; if (key > 0 && key < pool->nsolvables && pool->solvables[key].repo == repo) - return xSolvable_create(pool, key); + return new_XSolvable(pool, key); return 0; } } -%extend xSolvable { +%extend XSolvable { + XSolvable(Pool *pool, Id id) { + if (!id) + return 0; + XSolvable *s = sat_calloc(1, sizeof(*s)); + s->pool = pool; + s->id = id; + return s; + } const char *str() { return solvid2str($self->pool, $self->id); } const char *lookup_str(Id keyname) { return pool_lookup_str($self->pool, $self->id, keyname); } - Id lookup_id(Id entry, Id keyname) { + Id lookup_id(Id keyname) { return pool_lookup_id($self->pool, $self->id, keyname); } unsigned int lookup_num(Id keyname, unsigned int notfound = 0) { @@ -751,6 +836,9 @@ typedef struct { const char *b = pool_lookup_checksum($self->pool, $self->id, keyname, OUTPUT); return b; } + const char *lookup_location(int *OUTPUT) { + return solvable_get_location($self->pool->solvables + $self->id, OUTPUT); + } bool installable() { return pool_installable($self->pool, pool_id2solvable($self->pool, $self->id)); } @@ -761,46 +849,46 @@ typedef struct { const char * const name; %{ - SWIGINTERN const char *xSolvable_name_get(xSolvable *xs) { + SWIGINTERN const char *XSolvable_name_get(XSolvable *xs) { Pool *pool = xs->pool; return id2str(pool, pool->solvables[xs->id].name); } %} Id const nameid; %{ - SWIGINTERN Id xSolvable_nameid_get(xSolvable *xs) { + SWIGINTERN Id XSolvable_nameid_get(XSolvable *xs) { return xs->pool->solvables[xs->id].name; } %} const char * const evr; %{ - SWIGINTERN const char *xSolvable_evr_get(xSolvable *xs) { + SWIGINTERN const char *XSolvable_evr_get(XSolvable *xs) { Pool *pool = xs->pool; return id2str(pool, pool->solvables[xs->id].evr); } %} Id const evrid; %{ - SWIGINTERN Id xSolvable_evrid_get(xSolvable *xs) { + SWIGINTERN Id XSolvable_evrid_get(XSolvable *xs) { return xs->pool->solvables[xs->id].evr; } %} const char * const arch; %{ - SWIGINTERN const char *xSolvable_arch_get(xSolvable *xs) { + SWIGINTERN const char *XSolvable_arch_get(XSolvable *xs) { Pool *pool = xs->pool; return id2str(pool, pool->solvables[xs->id].arch); } %} Id const archid; %{ - SWIGINTERN Id xSolvable_archid_get(xSolvable *xs) { + SWIGINTERN Id XSolvable_archid_get(XSolvable *xs) { return xs->pool->solvables[xs->id].arch; } %} Repo * const repo; %{ - SWIGINTERN Repo *xSolvable_repo_get(xSolvable *xs) { + SWIGINTERN Repo *XSolvable_repo_get(XSolvable *xs) { return xs->pool->solvables[xs->id].repo; } %} @@ -809,15 +897,15 @@ typedef struct { %extend Problem { Problem(Solver *solv, Id id) { Problem *p; - p = sat_calloc(sizeof(*p), 1); + p = sat_calloc(1, sizeof(*p)); p->solv = solv; p->id = id; return p; } - Id findproblemrule() { + Id findproblemrule_helper() { return solver_findproblemrule($self->solv, $self->id); } - Queue findallproblemrules(int unfiltered=0) { + Queue findallproblemrules_helper(int unfiltered=0) { Solver *solv = $self->solv; Id probr; int i, j; @@ -838,25 +926,249 @@ typedef struct { } return q; } + int solution_count() { + return solver_solution_count($self->solv, $self->id); + } +#if defined(SWIGPYTHON) + %pythoncode { + def findproblemrule(self): + return XRule(self.solv, self.findproblemrule_helper()) + def findallproblemrules(self, unfiltered=0): + return [ XRule(self.solv, i) for i in self.findallproblemrules_helper(unfiltered) ] + def solutions(self): + return [ Solution(self, i) for i in range(1, self.solution_count() + 1) ]; + } +#endif +} + +%extend Solution { + Solution(Problem *p, Id id) { + Solution *s; + s = sat_calloc(1, sizeof(*s)); + s->solv = p->solv; + s->problemid = p->id; + s->id = id; + return s; + } + int element_count() { + return solver_solutionelement_count($self->solv, $self->problemid, $self->id); + } +#if defined(SWIGPYTHON) + %pythoncode { + def elements(self): + return [ Solutionelement(self, i) for i in range(1, self.element_count() + 1) ]; + } +#endif +} + +%extend Solutionelement { + Solutionelement(Solution *s, Id id) { + Solutionelement *e; + e = sat_calloc(1, sizeof(*e)); + e->solv = s->solv; + e->problemid = s->problemid; + e->solutionid = s->id; + e->id = id; + solver_next_solutionelement(e->solv, e->problemid, e->solutionid, e->id - 1, &e->p, &e->rp); + if (e->p > 0) { + e->type = e->rp ? SOLVER_SOLUTION_REPLACE : SOLVER_SOLUTION_DEINSTALL; + } else { + e->type = e->p; + e->p = e->rp; + e->rp = 0; + } + return e; + } + %newobject solvable; + XSolvable * const solvable; + %newobject replacement; + XSolvable * const replacement; + int const jobidx; + %{ + SWIGINTERN XSolvable *Solutionelement_solvable_get(Solutionelement *e) { + return new_XSolvable(e->solv->pool, e->p); + } + SWIGINTERN XSolvable *Solutionelement_replacement_get(Solutionelement *e) { + return new_XSolvable(e->solv->pool, e->rp); + } + SWIGINTERN int Solutionelement_jobidx_get(Solutionelement *e) { + return (e->p - 1) / 2; + } + %} } %extend Solver { + static const int SOLVER_RULE_UNKNOWN = SOLVER_RULE_UNKNOWN; + static const int SOLVER_RULE_RPM = SOLVER_RULE_RPM; + static const int SOLVER_RULE_RPM_NOT_INSTALLABLE = SOLVER_RULE_RPM_NOT_INSTALLABLE; + static const int SOLVER_RULE_RPM_NOTHING_PROVIDES_DEP = SOLVER_RULE_RPM_NOTHING_PROVIDES_DEP; + static const int SOLVER_RULE_RPM_PACKAGE_REQUIRES = SOLVER_RULE_RPM_PACKAGE_REQUIRES; + static const int SOLVER_RULE_RPM_SELF_CONFLICT = SOLVER_RULE_RPM_SELF_CONFLICT; + static const int SOLVER_RULE_RPM_PACKAGE_CONFLICT = SOLVER_RULE_RPM_PACKAGE_CONFLICT; + static const int SOLVER_RULE_RPM_SAME_NAME = SOLVER_RULE_RPM_SAME_NAME; + static const int SOLVER_RULE_RPM_PACKAGE_OBSOLETES = SOLVER_RULE_RPM_PACKAGE_OBSOLETES; + static const int SOLVER_RULE_RPM_IMPLICIT_OBSOLETES = SOLVER_RULE_RPM_IMPLICIT_OBSOLETES; + static const int SOLVER_RULE_RPM_INSTALLEDPKG_OBSOLETES = SOLVER_RULE_RPM_INSTALLEDPKG_OBSOLETES; + static const int SOLVER_RULE_UPDATE = SOLVER_RULE_UPDATE; + static const int SOLVER_RULE_FEATURE = SOLVER_RULE_FEATURE; + static const int SOLVER_RULE_JOB = SOLVER_RULE_JOB; + static const int SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP = SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP; + static const int SOLVER_RULE_DISTUPGRADE = SOLVER_RULE_DISTUPGRADE; + static const int SOLVER_RULE_INFARCH = SOLVER_RULE_INFARCH; + static const int SOLVER_RULE_CHOICE = SOLVER_RULE_CHOICE; + static const int SOLVER_RULE_LEARNT = SOLVER_RULE_LEARNT; + + static const int SOLVER_SOLUTION_JOB = SOLVER_SOLUTION_JOB; + static const int SOLVER_SOLUTION_INFARCH = SOLVER_SOLUTION_INFARCH; + static const int SOLVER_SOLUTION_DISTUPGRADE = SOLVER_SOLUTION_DISTUPGRADE; + static const int SOLVER_SOLUTION_DEINSTALL = SOLVER_SOLUTION_DEINSTALL; + static const int SOLVER_SOLUTION_REPLACE = SOLVER_SOLUTION_REPLACE; + ~Solver() { solver_free($self); } - %pythoncode %{ +#if defined(SWIGPYTHON) + %pythoncode { def solve(self, jobs): j = [] for job in jobs: j += [job.how, job.what] - nprob = self.solve_wrap(j) + nprob = self.solve_helper(j) return [ Problem(self, pid) for pid in range(1, nprob + 1) ] - %} - int solve_wrap(Queue jobs) { + } +#endif + int solve_helper(Queue jobs) { solver_solve($self, &jobs); return solver_problem_count($self); } - %apply Id *OUTPUT { Id *source, Id *target, Id *dep }; - int ruleinfo(Id ruleid, Id *source, Id *target, Id *dep) { - return solver_ruleinfo($self, ruleid, source, target, dep); + %newobject transaction; + Transaction *transaction() { + Transaction *t; + t = sat_calloc(1, sizeof(*t)); + transaction_init_clone(t, &$self->trans); + return t; + } +} + +%extend Transaction { + static const int SOLVER_TRANSACTION_IGNORE = SOLVER_TRANSACTION_IGNORE; + static const int SOLVER_TRANSACTION_ERASE = SOLVER_TRANSACTION_ERASE; + static const int SOLVER_TRANSACTION_REINSTALLED = SOLVER_TRANSACTION_REINSTALLED; + static const int SOLVER_TRANSACTION_DOWNGRADED = SOLVER_TRANSACTION_DOWNGRADED; + static const int SOLVER_TRANSACTION_CHANGED = SOLVER_TRANSACTION_CHANGED; + static const int SOLVER_TRANSACTION_UPGRADED = SOLVER_TRANSACTION_UPGRADED; + static const int SOLVER_TRANSACTION_OBSOLETED = SOLVER_TRANSACTION_OBSOLETED; + static const int SOLVER_TRANSACTION_INSTALL = SOLVER_TRANSACTION_INSTALL; + static const int SOLVER_TRANSACTION_REINSTALL = SOLVER_TRANSACTION_REINSTALL; + static const int SOLVER_TRANSACTION_DOWNGRADE = SOLVER_TRANSACTION_DOWNGRADE; + static const int SOLVER_TRANSACTION_CHANGE = SOLVER_TRANSACTION_CHANGE; + static const int SOLVER_TRANSACTION_UPGRADE = SOLVER_TRANSACTION_UPGRADE; + static const int SOLVER_TRANSACTION_OBSOLETES = SOLVER_TRANSACTION_OBSOLETES; + static const int SOLVER_TRANSACTION_MULTIINSTALL = SOLVER_TRANSACTION_MULTIINSTALL; + static const int SOLVER_TRANSACTION_MULTIREINSTALL = SOLVER_TRANSACTION_MULTIREINSTALL; + static const int SOLVER_TRANSACTION_MAXTYPE = SOLVER_TRANSACTION_MAXTYPE; + static const int SOLVER_TRANSACTION_SHOW_ACTIVE = SOLVER_TRANSACTION_SHOW_ACTIVE; + static const int SOLVER_TRANSACTION_SHOW_ALL = SOLVER_TRANSACTION_SHOW_ALL; + static const int SOLVER_TRANSACTION_SHOW_OBSOLETES = SOLVER_TRANSACTION_SHOW_OBSOLETES; + static const int SOLVER_TRANSACTION_SHOW_MULTIINSTALL = SOLVER_TRANSACTION_SHOW_MULTIINSTALL; + static const int SOLVER_TRANSACTION_CHANGE_IS_REINSTALL = SOLVER_TRANSACTION_CHANGE_IS_REINSTALL; + static const int SOLVER_TRANSACTION_MERGE_VENDORCHANGES = SOLVER_TRANSACTION_MERGE_VENDORCHANGES; + static const int SOLVER_TRANSACTION_MERGE_ARCHCHANGES = SOLVER_TRANSACTION_MERGE_ARCHCHANGES; + static const int SOLVER_TRANSACTION_RPM_ONLY = SOLVER_TRANSACTION_RPM_ONLY; + static const int SOLVER_TRANSACTION_ARCHCHANGE = SOLVER_TRANSACTION_ARCHCHANGE; + static const int SOLVER_TRANSACTION_VENDORCHANGE = SOLVER_TRANSACTION_VENDORCHANGE; + static const int SOLVER_TRANSACTION_KEEP_ORDERDATA = SOLVER_TRANSACTION_KEEP_ORDERDATA; + ~Transaction() { + transaction_free($self); + sat_free($self); + } + bool isempty() { + return $self->steps.count == 0; + } + Queue classify_helper(int mode) { + Queue q; + queue_init(&q); + transaction_classify($self, mode, &q); + return q; } + Queue classify_pkgs_helper(int mode, Id cl, Id from, Id to) { + Queue q; + queue_init(&q); + transaction_classify_pkgs($self, mode, cl, from, to, &q); + return q; + } + %newobject othersolvable; + XSolvable *othersolvable(XSolvable *s) { + Id op = transaction_obs_pkg($self, s->id); + return new_XSolvable($self->pool, op); + } +#if defined(SWIGPYTHON) + %pythoncode { + def classify(self, mode = 0): + r = [] + cr = self.classify_helper(mode) + for i in xrange(0, len(cr), 4): + if cr[i] != self.SOLVER_TRANSACTION_IGNORE: + r.append([ cr[i], cr[i + 2], cr[i + 3], [ self.pool.solvables[j] for j in self.classify_pkgs_helper(mode, cr[i], cr[i + 2], cr[i + 3]) ] ]) + return r + } +#endif + Queue installedresult_helper(int *OUTPUT) { + Queue q; + queue_init(&q); + *OUTPUT = transaction_installedresult(self, &q); + return q; + } +#if defined(SWIGPYTHON) + %pythoncode { + def installedresult(self): + r = self.installedresult_helper() + newpkgs = r.pop() + rn = [ self.pool.solvables[r[i]] for i in range(0, newpkgs) ] + rk = [ self.pool.solvables[r[i]] for i in range(newpkgs, len(r)) ] + return rn, rk + } +#endif + Queue steps_helper() { + Queue q; + queue_init_clone(&q, &$self->steps); + return q; + } + int steptype(XSolvable *s, int mode) { + return transaction_type($self, s->id, mode); + } +#if defined(SWIGPYTHON) + %pythoncode { + def steps(self): + return [ self.pool.solvables[i] for i in self.steps_helper() ] + } +#endif + int calc_installsizechange() { + return transaction_calc_installsizechange($self); + } +} + +%extend XRule { + XRule(Solver *solv, Id id) { + if (!id) + return 0; + XRule *xr = sat_calloc(1, sizeof(*xr)); + xr->solv = solv; + xr->id = id; + return xr; + } + %apply Id *OUTPUT { Id *source, Id *target, Id *dep }; + int info_helper(Id *source, Id *target, Id *dep) { + return solver_ruleinfo($self->solv, $self->id, source, target, dep); + } +#if defined(SWIGPYTHON) + %pythoncode { + def info(self): + type, source, target, dep = self.info_helper() + if source: + source = self.solv.pool.solvables[source] + if target: + target = self.solv.pool.solvables[target] + return type, source, target, dep + } +#endif } -- 2.47.3