-if cmd == 'install' or cmd == 'erase' or cmd == 'up' or cmd == 'dup' or cmd == 'verify':
- if not jobs:
- if cmd == 'up' or cmd == 'verify':
- jobs = [ pool.Job(Job.SOLVER_SOLVABLE_ALL, 0) ]
- elif cmd == 'dup':
- pass
- else:
- print "no package matched."
- sys.exit(1)
- for job in jobs:
- if cmd == 'up':
- # up magic: use install instead of update if no installed package matches
- if job.how == Job.SOLVER_SOLVABLE_ALL or filter(lambda s: s.isinstalled(), job.solvables()):
- job.how |= Job.SOLVER_UPDATE
- else:
- job.how |= Job.SOLVER_INSTALL
- elif cmd == 'install':
- job.how |= Job.SOLVER_INSTALL
- elif cmd == 'erase':
- job.how |= Job.SOLVER_ERASE
- elif cmd == 'dup':
- job.how |= Job.SOLVER_DISTUPGRADE
- elif cmd == 'verify':
- job.how |= Job.SOLVER_VERIFY
-
- #pool.set_debuglevel(2)
- solver = None
- while True:
- solver = pool.Solver()
- solver.ignorealreadyrecommended = True
- if cmd == 'erase':
- solver.allowuninstall = True
- if cmd == 'dup' and not jobs:
- solver.distupgrade = True
- solver.updatesystem = True
- solver.allowdowngrade = True
- solver.allowvendorchange = True
- solver.allowarchchange = True
- solver.dosplitprovides = True
- if cmd == 'up' and len(jobs) == 1 and jobs[0].how == (Job.SOLVER_UPDATE | Job.SOLVER_SOLVABLE_ALL):
- solver.dosplitprovides = True
- problems = solver.solve(jobs)
- if not problems:
- break
- for problem in problems:
- print "Problem %d:" % problem.id
- r = problem.findproblemrule()
- ri = r.info()
- print ri.problemstr()
- 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 " - do not ask to", jobs[element.jobidx]
- elif etype == Solver.SOLVER_SOLUTION_INFARCH:
- if element.solvable.isinstalled():
- print " - keep %s despite the inferior architecture" % element.solvable
- else:
- print " - install %s despite the inferior architecture" % element.solvable
- elif etype == Solver.SOLVER_SOLUTION_DISTUPGRADE:
- if element.solvable.isinstalled():
- print " - keep obsolete %s" % element.solvable
- else:
- print " - install %s from excluded repository" % element.solvable
- elif etype == Solver.SOLVER_SOLUTION_REPLACE:
- illegal = element.illegalreplace()
- if illegal & solver.POLICY_ILLEGAL_DOWNGRADE:
- print " - allow downgrade of %s to %s" % (element.solvable, element.replacement)
- if illegal & solver.POLICY_ILLEGAL_ARCHCHANGE:
- print " - allow architecture change of %s to %s" % (element.solvable, element.replacement)
- if illegal & solver.POLICY_ILLEGAL_VENDORCHANGE:
- if element.replacement.vendorid:
- print " - allow vendor change from '%s' (%s) to '%s' (%s)" % (element.solvable.vendor, element.solvable, element.replacement.vendor, element.replacement)
- else:
- print " - allow vendor change from '%s' (%s) to no vendor (%s)" % (element.solvable.vendor, element.solvable, element.replacement)
- if illegal == 0:
- print " - allow replacement of %s with %s" % (element.solvable, element.replacement)
- elif etype == Solver.SOLVER_SOLUTION_ERASE:
- print " - allow deinstallation of %s" % element.solvable
- print
- sol = ''
- while not (sol == 's' or sol == 'q' or (sol.isdigit() and int(sol) >= 1 and int(sol) <= len(solutions))):
- sys.stdout.write("Please choose a solution: ")
- sys.stdout.flush()
- sol = sys.stdin.readline().strip()
- if sol == 's':
- continue # skip problem
- if sol == 'q':
- sys.exit(1)
- solution = solutions[int(sol) - 1]
- for element in solution.elements():
- etype = element.type
- if etype == Solver.SOLVER_SOLUTION_JOB:
- jobs[element.jobidx] = pool.Job(Job.SOLVER_NOOP, 0)
- else:
- newjob = element.Job()
- if newjob and newjob not in jobs:
- jobs.append(newjob)
-
- # 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 cl in trans.classify():
- if cl.type == Transaction.SOLVER_TRANSACTION_ERASE:
- print "%d erased packages:" % cl.count
- elif cl.type == Transaction.SOLVER_TRANSACTION_INSTALL:
- print "%d installed packages:" % cl.count
- elif cl.type == Transaction.SOLVER_TRANSACTION_REINSTALLED:
- print "%d reinstalled packages:" % cl.count
- elif cl.type == Transaction.SOLVER_TRANSACTION_DOWNGRADED:
- print "%d downgraded packages:" % cl.count
- elif cl.type == Transaction.SOLVER_TRANSACTION_CHANGED:
- print "%d changed packages:" % cl.count
- elif cl.type == Transaction.SOLVER_TRANSACTION_UPGRADED:
- print "%d upgraded packages:" % cl.count
- elif cl.type == Transaction.SOLVER_TRANSACTION_VENDORCHANGE:
- print "%d vendor changes from '%s' to '%s':" % (cl.count, pool.id2str(cl.fromid), pool.id2str(cl.toid))
- elif cl.type == Transaction.SOLVER_TRANSACTION_ARCHCHANGE:
- print "%d arch changes from '%s' to '%s':" % (cl.count, pool.id2str(cl.fromid), pool.id2str(cl.toid))
- else:
- continue
- for p in cl.solvables():
- if cl.type == Transaction.SOLVER_TRANSACTION_UPGRADED or cl.type == Transaction.SOLVER_TRANSACTION_DOWNGRADED:
- op = trans.othersolvable(p)
- print " - %s -> %s" % (p, op)
- else:
- print " - %s" % p
- 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 = trans.newpackages()
- 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 repo.type == 'commandline':
- f = solv.xfopen(location)
- if not f:
- sys.exit("\n%s: %s not found" % location)
- newpkgsfp[p.id] = f
- continue
- if not sysrepo.handle.isempty() and os.access('/usr/bin/applydeltarpm', os.X_OK):
- pname = p.name
- di = p.repo.Dataiterator(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)
- candidate = None
- for installedp in pool.whatprovides(p.nameid):
- if installedp.isinstalled() and installedp.nameid == p.nameid and installedp.archid == p.archid and installedp.evrid == baseevrid:
- candidate = installedp
- if not candidate:
- continue
- seq = pool.lookup_str(solv.SOLVID_POS, solv.DELTA_SEQ_NAME) + '-' + pool.lookup_str(solv.SOLVID_POS, solv.DELTA_SEQ_EVR) + '-' + pool.lookup_str(solv.SOLVID_POS, solv.DELTA_SEQ_NUM)
- st = subprocess.call(['/usr/bin/applydeltarpm', '-a', p.arch, '-c', '-s', seq])
- if st:
- continue
- chksum = pool.lookup_checksum(solv.SOLVID_POS, solv.DELTA_CHECKSUM)
- if not chksum:
- continue
- dloc = pool.lookup_str(solv.SOLVID_POS, solv.DELTA_LOCATION_DIR) + '/' + pool.lookup_str(solv.SOLVID_POS, solv.DELTA_LOCATION_NAME) + '-' + pool.lookup_str(solv.SOLVID_POS, solv.DELTA_LOCATION_EVR) + '.' + pool.lookup_str(solv.SOLVID_POS, solv.DELTA_LOCATION_SUFFIX)
- f = repo.download(dloc, False, chksum)
- if not f:
- continue
- nf = tempfile.TemporaryFile()
- nf = os.dup(nf.fileno())
- st = subprocess.call(['/usr/bin/applydeltarpm', '-a', p.arch, "/dev/fd/%d" % solv.xfileno(f), "/dev/fd/%d" % nf])
- solv.xfclose(f)
- os.lseek(nf, 0, os.SEEK_SET)
- newpkgsfp[p.id] = solv.xfopen_fd("", nf)
- break
- if p.id in newpkgsfp:
- sys.stdout.write("d")
- sys.stdout.flush()
- continue
-
- if repo.type == 'susetags':
- datadir = repo.handle.lookup_str(solv.SOLVID_META, solv.SUSETAGS_DATADIR)
- if not datadir:
- datadir = 'suse'
- location = datadir + '/' + location
- chksum = p.lookup_checksum(solv.SOLVABLE_CHECKSUM)
- f = repo.download(location, False, chksum)
- if not f:
- sys.exit("\n%s: %s not found in repository" % (repo.name, location))
- newpkgsfp[p.id] = f
- sys.stdout.write(".")
- sys.stdout.flush()
- print
- print "Committing transaction:"
- print
- ts = rpm.TransactionSet('/')
- ts.setVSFlags(rpm._RPMVSF_NOSIGNATURES)
- erasenamehelper = {}
- 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)
- erasenamehelper[p.name] = p
- if not rpmdbid:
- sys.exit("\ninternal error: installed package %s has no rpmdbid\n" % p)
- 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, d):
- if reason == rpm.RPMCALLBACK_INST_OPEN_FILE:
- return solv.xfileno(newpkgsfp[p.id])
- if reason == rpm.RPMCALLBACK_INST_START:
- print "install", p
- if reason == rpm.RPMCALLBACK_UNINST_START:
- # argh, p is just the name of the package
- if p in erasenamehelper:
- p = erasenamehelper[p]
- print "erase", p
- runproblems = ts.run(runCallback, '')
- if runproblems:
- print runproblems
- sys.exit(1)