-#!/usr/bin/perl
+#!/usr/bin/perl -w
use POSIX;
+use Fcntl;
use Config::IniFiles;
use File::FnMatch;
use Data::Dumper;
use solv;
+use Devel::Peek;
+use FileHandle;
use strict;
package Repo::generic;
$self->usecachedrepo();
}
+sub download {
+ my ($self, $file, $uncompress, $chksum, $markincomplete) = @_;
+ if (!$self->{'baseurl'}) {
+ print "$self->{'alias'}: no baseurl\n";
+ return undef;
+ }
+ my $url = $self->{'baseurl'};
+ $url =~ s/\/$//;
+ $url .= "/$file";
+ open(my $f, '+>', undef) || die;
+ fcntl($f, Fcntl::F_SETFD, 0);
+ my $st = system('curl', '-f', '-s', '-L', '-o', "/dev/fd/".fileno($f), '--', $url);
+ if (POSIX::lseek(fileno($f), 0, POSIX::SEEK_END) == 0 && ($st == 0 || !$chksum)) {
+ return undef;
+ }
+ POSIX::lseek(fileno($f), 0, POSIX::SEEK_SET);
+ if ($st) {
+ print "$file: download error #$st\n";
+ $self->{'incomplete'} = 1 if $markincomplete;
+ return undef;
+ }
+ if ($chksum) {
+ my $fchksum = solv::Chksum->new($chksum->{'type'});
+ $fchksum->add_fd(fileno($f));
+ if (!$fchksum->matches($chksum)) {
+ print "$file: checksum error\n";
+ $self->{'incomplete'} = 1 if $markincomplete;
+ return undef;
+ }
+ }
+ if ($uncompress) {
+ return solv::xfopen_fd($file, POSIX::dup(fileno($f)));
+ } else {
+ return solv::xfopen_fd('', POSIX::dup(fileno($f)));
+ }
+}
+
sub usecachedrepo {
my ($self, $ext, $mark) = @_;
my $cookie = $ext ? $self->{'extcookie'} : $self->{'cookie'};
solv::xfclose($f);
return undef;
}
+ solv::xfclose($f);
return 1;
}
return undef;
our @ISA = ('Repo::generic');
+package Repo::susetags;
+
+our @ISA = ('Repo::generic');
+
+package Repo::unknown;
+
+our @ISA = ('Repo::generic');
+
+sub load {
+ my ($self, $pool) = @_;
+ print "unsupported repo '$self->{'alias'}': skipped\n";
+ return 0;
+}
+
package Repo::system;
our @ISA = ('Repo::generic');
return unless $name =~ /[[*?]/;
if ($globname) {
my %idmatches;
- for my $s (@{$pool->{'solvables_iter'}}) {
- $idmatches{$s->{'nameid'}} = 1 if $s->installable() && File::FnMatch::fnmatch($name, $s->{'name'}, 0);
+ for my $d (@{$pool->dataiterator_new(0, $solv::SOLVABLE_NAME, $name, $solv::Dataiterator::SEARCH_GLOB)}) {
+ my $s = $d->{'solvable'};
+ $idmatches{$s->{'nameid'}} = 1 if $s->installable();
}
if (%idmatches) {
return map {$pool->Job($solv::Job::SOLVER_SOLVABLE_NAME, $_)} sort(keys %idmatches);
}
}
if ($globdep) {
- my %idmatches;
- for $id (@{$pool->allprovidingids()}) {
- $idmatches{$id} = 1 if File::FnMatch::fnmatch($name, $pool->id2str($id), 0);
- }
- if (%idmatches) {
+ my @idmatches = $pool->matchprovidingids($name, $solv::Dataiterator::SEARCH_GLOB);
+ if (@idmatches) {
print "[using capability match for '$name']\n";
- return map {$pool->Job($solv::Job::SOLVER_SOLVABLE_PROVIDES, $_)} sort(keys %idmatches);
+ return map {$pool->Job($solv::Job::SOLVER_SOLVABLE_PROVIDES, $_)} sort(@idmatches);
}
}
return;
my ($pool, $jobs, $flags, $evrstr) = @_;
if ($evrstr =~ /^(.+)\.(.+?)$/ && validarch($pool, $2)) {
my $evr = $pool->str2id($1);
- my @jobs = limitjobs($pool, $jobs, $solv::solv::REL_ARCH, $pool->str2id($2));
+ my @jobs = limitjobs($pool, $jobs, $solv::REL_ARCH, $pool->str2id($2));
return limitjobs($pool, \@jobs, $flags, $evr);
}
return limitjobs($pool, $jobs, $flags, $pool->str2id($evrstr));
my $arch = $2;
@jobs = depglob($pool, $1, 1, 1);
if (@jobs) {
- @jobs = limitjobs($pool, \@jobs, $solv::solv::REL_ARCH, $pool->str2id($arch));
+ @jobs = limitjobs($pool, \@jobs, $solv::REL_ARCH, $pool->str2id($arch));
return limitjobs($pool, \@jobs, $flags, $pool->str2id($evr));
}
}
if (@matches > 1) {
return $pool->Job($solv::Job::SOLVER_SOLVABLE_ONE_OF, $pool->towhatprovides(\@matches));
} else {
- return $pool->Job($solv::Job::SOLVER_SOLVABLE | $solv::Job::NOAUTOSET, $matches[0]);
+ return $pool->Job($solv::Job::SOLVER_SOLVABLE | $solv::Job::SOLVER_NOAUTOSET, $matches[0]);
}
}
$repoattr->{$p} = $cfg->val($alias, $p);
}
my $repo;
- if ($repoattr->{'type'} == 'rpm-md') {
+ if ($repoattr->{'type'} eq 'rpm-md') {
$repo = Repo::rpmmd->new($repoattr);
+ } elsif ($repoattr->{'type'} eq 'yast2') {
+ $repo = Repo::susetags->new($repoattr);
+ } else {
+ $repo = Repo::unknown->new($repoattr);
}
push @repos, $repo;
}
exit(0);
}
-my $addedprovides = $pool->addfileprovides_ids();
+my @addedprovides = $pool->addfileprovides_ids();
$pool->createwhatprovides();
my @jobs;
printf "Summary: %s\n", $s->lookup_str($solv::SOLVABLE_SUMMARY);
my $str = $s->lookup_str($solv::SOLVABLE_URL);
printf "Url: %s\n", $str if $str;
- my $str = $s->lookup_str($solv::SOLVABLE_LICENSE);
+ $str = $s->lookup_str($solv::SOLVABLE_LICENSE);
printf "License: %s\n", $str if $str;
printf "Description:\n%s\n", $s->lookup_str($solv::SOLVABLE_DESCRIPTION);
} else {
}
for my $job (@jobs) {
if ($cmd eq 'up') {
- if ($job->{'how'} == $solv::Job::SOLVER_SOLVABLE_ALL || grep {$_->isinstalled()} @{$pool->jobsolvables($job)}) {
+ if ($job->{'how'} == $solv::Job::SOLVER_SOLVABLE_ALL || grep {$_->isinstalled()} $pool->jobsolvables($job)) {
$job->{'how'} |= $solv::Job::SOLVER_UPDATE;
} else {
$job->{'how'} |= $solv::Job::SOLVER_INSTALL;
my @problems = $solver->solve(\@jobs);
last unless @problems;
for my $problem (@problems) {
- print "Problem $problem->{'id'}:\n";
+ print "Problem $problem->{'id'}/".@problems.":\n";
my $r = $problem->findproblemrule();
- my ($type, $source, $target, $dep) = $r->info();
- if ($type == $solv::Solver::SOLVER_RULE_RPM_PACKAGE_CONFLICT) {
- printf "package %s conflicts with %s provided by %s\n", $source->str(), $pool->dep2str($dep), $target->str();
+ my $ri = $r->info();
+ print $ri->problemstr()."\n";
+ my @solutions = $problem->solutions();
+ for my $solution (@solutions) {
+ print " Solution $solution->{'id'}:\n";
+ for my $element ($solution->elements()) {
+ my $etype = $element->{'type'};
+ if ($etype == $solv::Solver::SOLVER_SOLUTION_JOB) {
+ print " - do not ask to ".$jobs[$element->{'jobidx'}]->str()."\n";
+ } elsif ($etype == $solv::Solver::SOLVER_SOLUTION_INFARCH) {
+ if ($element->{'solvable'}->isinstalled()) {
+ print " - keep ".$element->{'solvable'}->str()." despite the inferior architecture\n";
+ } else {
+ print " - install ".$element->{'solvable'}->str()." despite the inferior architecture\n";
+ }
+ } elsif ($etype == $solv::Solver::SOLVER_SOLUTION_DISTUPGRADE) {
+ if ($element->{'solvable'}->isinstalled()) {
+ print " - keep obsolete ".$element->{'solvable'}->str()."\n";
+ } else {
+ print " - install ".$element->{'solvable'}->str()." from excluded repository\n";
+ }
+ } elsif ($etype == $solv::Solver::SOLVER_SOLUTION_REPLACE) {
+ print " - allow replacement of ".$element->{'solvable'}->str()." with ".$element->{'replacement'}->str()."\n";
+ } elsif ($etype == $solv::Solver::SOLVER_SOLUTION_ERASE) {
+ print " - allow deinstallation of ".$element->{'solvable'}->str()."\n";
+ } else {
+ print " - allow something else\n";
+ }
+ }
+ }
+ my $sol;
+ while (1) {
+ print "Please choose a solution: ";
+ $sol = <STDIN>;
+ chomp $sol;
+ last if $sol eq 's' || $sol eq 'q' || ($sol =~ /^\d+$/ && $sol >= 1 && $sol <= @solutions);
+ }
+ next if $sol eq 's';
+ exit(1) if $sol eq 'q';
+ my $solution = $solutions[$sol - 1];
+ for my $element ($solution->elements()) {
+ my $etype = $element->{'type'};
+ if ($etype == $solv::Solver::SOLVER_SOLUTION_JOB) {
+ $jobs[$element->{'jobidx'}] = $pool->Job($solv::Job::SOLVER_NOOP, 0);
+ } else {
+ my $newjob = $element->Job();
+ push @jobs, $newjob if $newjob && !grep {$_->{'how'} == $newjob->{'how'} && $_->{'what'} == $newjob->{'what'}} @jobs;
+ }
+ }
+ }
+ }
+ my $trans = $solver->transaction();
+ undef $solver;
+ if ($trans->isempty()) {
+ print "Nothing to do.\n";
+ exit 0;
+ }
+ print "\nTransaction summary:\n\n";
+ for my $c ($trans->classify()) {
+ my ($ctype, $pkgs, $fromid, $toid) = @$c;
+ if ($ctype == $solv::Transaction::SOLVER_TRANSACTION_ERASE) {
+ printf "%d erased packages:\n", scalar(@$pkgs);
+ } elsif ($ctype == $solv::Transaction::SOLVER_TRANSACTION_INSTALL) {
+ printf "%d installed packages:\n", scalar(@$pkgs);
+ } elsif ($ctype == $solv::Transaction::SOLVER_TRANSACTION_REINSTALLED) {
+ printf "%d reinstalled packages:\n", scalar(@$pkgs);
+ } elsif ($ctype == $solv::Transaction::SOLVER_TRANSACTION_DOWNGRADED) {
+ printf "%d downgraded packages:\n", scalar(@$pkgs);
+ } elsif ($ctype == $solv::Transaction::SOLVER_TRANSACTION_CHANGED) {
+ printf "%d changed packages:\n", scalar(@$pkgs);
+ } elsif ($ctype == $solv::Transaction::SOLVER_TRANSACTION_UPGRADED) {
+ printf "%d upgraded packages:\n", scalar(@$pkgs);
+ } elsif ($ctype == $solv::Transaction::SOLVER_TRANSACTION_VENDORCHANGE) {
+ printf "%d vendor changes from '%s' to '%s':\n", scalar(@$pkgs), $pool->id2str($fromid), $pool->id2str($toid);
+ } elsif ($ctype == $solv::Transaction::SOLVER_TRANSACTION_ARCHCHANGE) {
+ printf "%d arch changes from '%s' to '%s':\n", scalar(@$pkgs), $pool->id2str($fromid), $pool->id2str($toid);
+ } else {
+ next;
+ }
+ for my $p (@$pkgs) {
+ if ($ctype == $solv::Transaction::SOLVER_TRANSACTION_UPGRADED || $ctype == $solv::Transaction::SOLVER_TRANSACTION_DOWNGRADED) {
+ my $other = $trans->othersolvable($p);
+ printf " - %s -> %s\n", $p->str(), $other->str();
+ } else {
+ printf " - %s\n", $p->str();
+ }
+ }
+ print "\n";
+ }
+ printf "install size change: %d K\n\n", $trans->calc_installsizechange();
+ while (1) {
+ print("OK to continue (y/n)? ");
+ my $yn = <STDIN>;
+ chomp $yn;
+ last if $yn eq 'y';
+ exit(1) if $yn eq 'n';
+ }
+ my @newpkgs = $trans->newpackages();
+ my %newpkgsfps;
+ if (@newpkgs) {
+ my $downloadsize = 0;
+ $downloadsize += $_->lookup_num($solv::SOLVABLE_DOWNLOADSIZE) for @newpkgs;
+ printf "Downloading %d packages, %d K\n", scalar(@newpkgs), $downloadsize;
+ for my $p (@newpkgs) {
+ my $repo = $p->{'repo'}->{'appdata'};
+ my ($location, $medianr) = $p->lookup_location();
+ next unless $location;
+ if ($repo->{'type'} eq 'yast2') {
+ $location = ($repo->{'handle'}->lookup_str($solv::SOLVID_META, $solv::SUSETAGS_DATADIR) || 'suse') ."/$location";
}
- print "TYPE: $type\n";
- printf "SOURCE: %s\n", $source->str() if $source;
- printf "TARGET: %s\n", $target->str() if $target;
- printf "DEP: %s\n", $pool->dep2str($dep) if $dep;
+ my $chksum = $p->lookup_checksum($solv::SOLVABLE_CHECKSUM);
+ my $f = $repo->download($location, 0, $chksum);
+ die("\n$repo->{'alias'}: $location not found in repository\n") unless $f;
+ $newpkgsfps{$p->{'id'}} = $f;
+ print ".";
+ STDOUT->flush();
+ }
+ print "\n";
+ }
+ print "Committing transaction:\n\n";
+ $trans->order(0);
+ for my $p ($trans->steps()) {
+ my $steptype = $trans->steptype($p, $solv::Transaction::SOLVER_TRANSACTION_RPM_ONLY);
+ if ($steptype == $solv::Transaction::SOLVER_TRANSACTION_ERASE) {
+ print "erase ".$p->str()."\n";
+ next unless $p->lookup_num($solv::RPM_RPMDBID);
+ my $evr = $p->{'evr'};
+ $evr =~ s/^[0-9]+://; # strip epoch
+ system('rpm', '-e', '--nodeps', '--nodigest', '--nosignature', "$p->{'name'}-$evr.$p->{'arch'}") && die("rpm failed: $?\n");
+ } elsif ($steptype == $solv::Transaction::SOLVER_TRANSACTION_INSTALL || $steptype == $solv::Transaction::SOLVER_TRANSACTION_MULTIINSTALL) {
+ print "install ".$p->str()."\n";
+ my $f = $newpkgsfps{$p->{'id'}};
+ my $mode = $steptype == $solv::Transaction::SOLVER_TRANSACTION_INSTALL ? '-U' : '-i';
+ system('rpm', $mode, '--force', '--nodeps', '--nodigest', '--nosignature', "/dev/fd/".solv::xfileno($f)) && die("rpm failed: $?\n");
+ solv::xfclose($f);
+ delete $newpkgsfps{$p->{'id'}};
}
- exit(0);
}
}
if globname:
# try name glob
idmatches = {}
- for s in pool.solvables:
- if s.installable() and fnmatch.fnmatch(s.name, name):
+ for d in pool.dataiterator_new(0, solv.SOLVABLE_NAME, name, Dataiterator.SEARCH_GLOB):
+ s = d.solvable
+ if s.installable():
idmatches[s.nameid] = True
if idmatches:
return [ pool.Job(Job.SOLVER_SOLVABLE_NAME, id) for id in sorted(idmatches.keys()) ]
if globdep:
# try dependency glob
- idmatches = {}
- for id in pool.allprovidingids():
- if fnmatch.fnmatch(pool.id2str(id), name):
- idmatches[id] = True
+ idmatches = pool.matchprovidingids(name, Dataiterator.SEARCH_GLOB)
if idmatches:
print "[using capability match for '%s']" % name
- return [ pool.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) ]
return []
for problem in problems:
print "Problem %d:" % problem.id
r = problem.findproblemrule()
- 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
+ ri = r.info()
+ print ri.problemstr()
solutions = problem.solutions()
for solution in solutions:
print " Solution %d:" % solution.id
print " - allow vendor change from '%s' (%s) to no vendor (%s)" % (element.solvable.vendor, element.solvable.str(), element.replacement.str())
if illegal == 0:
print " - allow replacement of %s with %s" % (element.solvable.str(), element.replacement.str())
- elif etype == Solver.SOLVER_SOLUTION_DEINSTALL:
+ elif etype == Solver.SOLVER_SOLUTION_ERASE:
print " - allow deinstallation of %s" % element.solvable.str()
sol = ''
while not (sol == 's' or sol == 'q' or (sol.isdigit() and int(sol) >= 1 and int(sol) <= len(solutions))):
solution = solutions[int(sol) - 1]
for element in solution.elements():
etype = element.type
- newjob = None
if etype == Solver.SOLVER_SOLUTION_JOB:
jobs[element.jobidx] = pool.Job(Job.SOLVER_NOOP, 0)
- elif etype == Solver.SOLVER_SOLUTION_INFARCH or etype == Solver.SOLVER_SOLUTION_DISTUPGRADE:
- newjob = pool.Job(Job.SOLVER_INSTALL|Job.SOLVER_SOLVABLE, element.solvable.id)
- elif etype == Solver.SOLVER_SOLUTION_REPLACE:
- newjob = pool.Job(Job.SOLVER_INSTALL|Job.SOLVER_SOLVABLE, element.replacement.id)
- elif etype == Solver.SOLVER_SOLUTION_DEINSTALL:
- newjob = pool.Job(Job.SOLVER_ERASE|Job.SOLVER_SOLVABLE, element.solvable.id)
- if newjob:
- for job in jobs:
- if job.how == newjob.how and job.what == newjob.what:
- newjob = None
- break
+ else:
+ newjob = element.Job()
if newjob:
- jobs.append(newjob)
+ for job in jobs:
+ if job.how == newjob.how and job.what == newjob.what:
+ newjob = None
+ break
+ if newjob:
+ jobs.append(newjob)
# no problems, show transaction
trans = solver.transaction()
del solver
yn = sys.stdin.readline().strip()
if yn == 'y': break
if yn == 'n': sys.exit(1)
- newpkgs, keptpkgs = trans.installedresult()
+ newpkgs = trans.newpackages()
newpkgsfp = {}
if newpkgs:
downloadsize = 0
queue_push(&$1, v);
}
}
+# AV *o = newAV();
+# av_push(o, SvREFCNT_inc(SWIG_From_int($1.elements[i])));
+# $result = newRV_noinc((SV*)o); argvi++;
+#
%typemap(out) Queue {
int i;
- AV *o = newAV();
+ if (argvi + $1.count + 1>= items) {
+ EXTEND(sp, items - (argvi + $1.count + 1) + 1);
+ }
for (i = 0; i < $1.count; i++)
- av_push(o, SvREFCNT_inc(SWIG_From_int($1.elements[i])));
+ ST(argvi++) = SvREFCNT_inc(SWIG_From_int($1.elements[i]));
queue_free(&$1);
- $result = newRV_noinc((SV*)o); argvi++;
+ $result = 0;
}
#endif
%typemap(arginit) Queue {
}
#if defined(SWIGPERL)
-%define perlmkarray(class,accessor,constructor)
+
+# work around a swig bug
+%{
+#undef SWIG_CALLXS
+#ifdef PERL_OBJECT
+# define SWIG_CALLXS(_name) TOPMARK=MARK-PL_stack_base;_name(cv,pPerl)
+#else
+# ifndef MULTIPLICITY
+# define SWIG_CALLXS(_name) TOPMARK=MARK-PL_stack_base;_name(cv)
+# else
+# define SWIG_CALLXS(_name) TOPMARK=MARK-PL_stack_base;_name(PERL_GET_THX, cv)
+# endif
+#endif
+%}
+
+
+%define perliter(class)
%perlcode {
- *solv::##class##::array::TIEARRAY = sub { bless $_[1], 'solv::class::array' };
- *solv::##class##::array::FETCHSIZE = *solv::##class##::__len__;
- *solv::##class##::array::FETCH = *solv::##class##::__getitem__;
- undef *solv::##accessor##;
- *solv::##accessor = sub { my @a; tie(@a, 'solv::class::array', ##constructor##(@_)); \@a };
+ sub class##::FETCH {
+ my $i = ${##class##::ITERATORS}{$_[0]};
+ if ($i) {
+ $_[1] == $i->[0] - 1 ? $i->[1] : undef;
+ } else {
+ $_[0]->__getitem__($_[1]);
+ }
+ }
+ sub class##::FETCHSIZE {
+ my $i = ${##class##::ITERATORS}{$_[0]};
+ if ($i) {
+ ($i->[1] = $_[0]->__next__()) ? ++$i->[0] : 0;
+ } else {
+ $_[0]->__len__();
+ }
+ }
}
%enddef
-%define perlmkiter(class,accessor,constructor)
- %perlcode {
- *solv::##class##::iter::TIEARRAY = sub { bless [$_[1], 0], 'solv::class::iter' };
- *solv::##class##::iter::FETCHSIZE = sub { ($_[0]->[2] = $_[0]->[0]->__next__()) ? ++$_[0]->[1] : 0 };
- *solv::##class##::iter::FETCH = sub { $_[1] == $_[0]->[1] - 1 ? $_[0]->[2] : undef };
- *solv::##class##::iter::iter = sub { return $_[0]->[0] };
- undef *solv::##accessor##;
- *solv::##accessor = sub { my @a; tie(@a, 'solv::class::iter', ##constructor##(@_)); \@a };
+
+%{
+
+#define SWIG_PERL_ITERATOR 0x80
+
+SWIGRUNTIMEINLINE SV *
+SWIG_Perl_NewArrayObj(SWIG_MAYBE_PERL_OBJECT void *ptr, swig_type_info *t, int flags) {
+ SV *result = sv_newmortal();
+ if (ptr && (flags & (SWIG_SHADOW | SWIG_POINTER_OWN))) {
+ SV *self;
+ SV *obj=newSV(0);
+ AV *array=newAV();
+ HV *stash;
+ sv_setref_pv(obj, (char *) SWIG_Perl_TypeProxyName(t), ptr);
+ stash=SvSTASH(SvRV(obj));
+ if (flags & SWIG_POINTER_OWN) {
+ HV *hv;
+ GV *gv=*(GV**)hv_fetch(stash, "OWNER", 5, TRUE);
+ if (!isGV(gv))
+ gv_init(gv, stash, "OWNER", 5, FALSE);
+ hv=GvHVn(gv);
+ hv_store_ent(hv, obj, newSViv(1), 0);
+ }
+ if (flags & SWIG_PERL_ITERATOR) {
+ HV *hv;
+ GV *gv=*(GV**)hv_fetch(stash, "ITERATORS", 9, TRUE);
+ AV *av=newAV();
+ if (!isGV(gv))
+ gv_init(gv, stash, "ITERATORS", 9, FALSE);
+ hv=GvHVn(gv);
+ hv_store_ent(hv, obj, newRV_inc((SV *)av), 0);
+ }
+ sv_magic((SV *)array, (SV *)obj, 'P', Nullch, 0);
+ SvREFCNT_dec(obj);
+ self=newRV_noinc((SV *)array);
+ sv_setsv(result, self);
+ SvREFCNT_dec((SV *)self);
+ sv_bless(result, stash);
+ } else {
+ sv_setref_pv(result, (char *) SWIG_Perl_TypeProxyName(t), ptr);
}
-%enddef
+ return result;
+}
+
+%}
+
+%typemap(out) Perlarray {
+ ST(argvi) = SWIG_Perl_NewArrayObj(SWIG_PERL_OBJECT_CALL SWIG_as_voidptr(result), $1_descriptor, $owner | $shadow); argvi++;
+}
+%typemap(out) Perliterator {
+ ST(argvi) = SWIG_Perl_NewArrayObj(SWIG_PERL_OBJECT_CALL SWIG_as_voidptr(result), $1_descriptor, $owner | $shadow | SWIG_PERL_ITERATOR); argvi++;
+}
+
+%typemap(out) Pool_solvable_iterator * = Perlarray;
+%typemap(out) Pool_solvable_iterator * solvables_iter = Perliterator;
+%typemap(out) Pool_repo_iterator * = Perlarray;
+%typemap(out) Pool_repo_iterator * repos_iter = Perliterator;
+%typemap(out) Repo_solvable_iterator * = Perlarray;
+%typemap(out) Repo_solvable_iterator * solvables_iter = Perliterator;
+%typemap(out) Dataiterator * = Perliterator;
+
#endif
+
#if defined(SWIGPYTHON)
typedef PyObject *AppObjectPtr;
%typemap(out) AppObjectPtr {
#endif
#if defined(SWIGPERL)
typedef SV *AppObjectPtr;
+%typemap(in) AppObjectPtr {
+ $1 = SvROK($input) ? SvRV($input) : 0;
+}
%typemap(out) AppObjectPtr {
- $result = $1;
- SvREFCNT_inc($result);
+ $result = $1 ? newRV_inc($1) : newSV(0);
+ argvi++;
}
#endif
#if defined(SWIGRUBY)
#define true 1
#define false 1
-#define SOLVER_SOLUTION_DEINSTALL -100
+#define SOLVER_SOLUTION_ERASE -100
#define SOLVER_SOLUTION_REPLACE -101
typedef struct chksum Chksum;
typedef int bool;
Id rp;
} Solutionelement;
+typedef struct {
+ Solver *solv;
+ Id rid;
+ Id type;
+ Id source;
+ Id target;
+ Id dep;
+} Ruleinfo;
+
+typedef Dataiterator Datamatch;
+
%}
typedef int Id;
Id const id;
} XSolvable;
+%nodefaultctor Ruleinfo;
+typedef struct {
+ Solver* const solv;
+ Id const type;
+ Id const dep;
+} Ruleinfo;
+
typedef struct {
Solver* const solv;
Id const id;
} XRepodata;
# put before pool/repo so we can access the constructor
-%nodefaultctor Dataiterator;
%nodefaultdtor Dataiterator;
-typedef struct _Dataiterator {
+typedef struct {} Dataiterator;
+typedef struct {} Pool_solvable_iterator;
+typedef struct {} Pool_repo_iterator;
+typedef struct {} Repo_solvable_iterator;
+
+%nodefaultctor Datamatch;
+%nodefaultdtor Datamatch;
+typedef struct {
Pool * const pool;
Repo * const repo;
const Id solvid;
-} Dataiterator;
+} Datamatch;
typedef struct {
Pool * const pool;
AppObjectPtr appdata;
} Repo;
-%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;
- bool allowuninstall;
- bool distupgrade;
bool allowdowngrade;
bool allowarchchange;
bool allowvendorchange;
+ bool allowuninstall;
+ bool updatesystem;
+ bool noupdateprovide;
+ bool dosplitprovides;
+ bool dontinstallrecommended;
+ bool ignorealreadyrecommended;
+ bool dontshowinstalledrecommended;
+ bool distupgrade;
+ bool distupgrade_removeunsupported;
+ bool noinfarchcheck;
} Solver;
typedef struct chksum {
%rename(xfclose) sat_xfclose;
%rename(xfileno) sat_xfileno;
-FILE *sat_xfopen(const char *fn);
-FILE *sat_xfopen_fd(const char *fn, int fd);
+FILE *sat_xfopen(const char *fn, const char *mode = 0);
+FILE *sat_xfopen_fd(const char *fn, int fd, const char *mode = 0);
%inline {
int sat_xfclose(FILE *fp) {
return fclose(fp);
}
const char *str() {
- Pool *pool = $self->pool;
- Id select = $self->how & SOLVER_SELECTMASK;
- char *strstart = 0, *strend = 0;
- switch ($self->how & SOLVER_JOBMASK) {
- case SOLVER_INSTALL:
- if (select == SOLVER_SOLVABLE && pool->installed && pool->solvables[$self->what].repo == pool->installed)
- strstart = "keep ", strend = "installed";
- else if (select == SOLVER_SOLVABLE_PROVIDES)
- strstart = "install a solvable ";
- else
- strstart = "install ";
- break;
- case SOLVER_ERASE:
- if (select == SOLVER_SOLVABLE && !(pool->installed && pool->solvables[$self->what].repo == pool->installed))
- strstart = "keep ", strend = "uninstalled";
- else if (select == SOLVER_SOLVABLE_PROVIDES)
- strstart = "deinstall all solvables ";
- else
- strstart = "deinstall ";
- break;
- case SOLVER_UPDATE:
- strstart = "install the most recent version of ";
- break;
- case SOLVER_LOCK:
- strstart = "lock ";
- break;
- default:
- return "unknwon job";
- }
- return pool_tmpjoin(pool, strstart, solver_select2str(pool, select, $self->what), strend);
+ return pool_job2str($self->pool, $self->how, $self->what, 0);
}
}
return sat_chksum_create_from_bin(type, b);
}
-#ifdef SWIGPERL
- perlmkiter(Dataiterator, Pool::dataiterator_new, solvc::Pool_dataiterator_new)
-#endif
%newobject dataiterator_new;
Dataiterator *dataiterator_new(Id p, Id key, const char *match, int flags) {
return new_Dataiterator($self, 0, p, key, match, flags);
pool_createwhatprovides($self);
}
-
-#if defined(SWIGPERL)
- perlmkarray(Pool_solvable_iterator, Pool::swig_solvables_get, solvc::Pool_solvables_get)
- perlmkiter(Pool_solvable_iterator, Pool::swig_solvables_iter_get, solvc::Pool_solvables_get)
-#endif
-
%newobject solvables;
Pool_solvable_iterator * const solvables;
%{
SWIGINTERN Pool_solvable_iterator * Pool_solvables_get(Pool *pool) {
- Pool_solvable_iterator *s;
- s = sat_calloc(1, sizeof(*s));
- s->pool = pool;
- s->id = 0;
- return s;
+ return new_Pool_solvable_iterator(pool);
}
%}
-
-#if defined(SWIGPERL)
- perlmkarray(Pool_repo_iterator, Pool::swig_repos_get, solvc::Pool_repos_get)
- perlmkiter(Pool_repo_iterator, Pool::swig_repos_iter_get, solvc::Pool_repos_get)
-#endif
+ %newobject solvables_iter;
+ Pool_solvable_iterator * solvables_iter() {
+ return new_Pool_solvable_iterator($self);
+ }
%newobject repos;
Pool_repo_iterator * const repos;
%{
SWIGINTERN Pool_repo_iterator * Pool_repos_get(Pool *pool) {
- Pool_repo_iterator *s;
- s = sat_calloc(1, sizeof(*s));
- s->pool = pool;
- s->id = 0;
- return s;
+ return new_Pool_repo_iterator(pool);
}
%}
+ %newobject repos_iter;
+ Pool_repo_iterator * repos_iter() {
+ return new_Pool_repo_iterator($self);
+ }
Repo *installed;
%{
queue_push(&q, p);
return q;
}
- Queue allprovidingids() {
+ Queue matchprovidingids(const char *match, int flags) {
Pool *pool = $self;
Queue q;
Id id;
queue_init(&q);
- for (id = 1; id < pool->ss.nstrings; id++)
- if (pool->whatprovides[id])
- queue_push(&q, id);
+ if (!flags) {
+ for (id = 1; id < pool->ss.nstrings; id++)
+ if (pool->whatprovides[id])
+ queue_push(&q, id);
+ } else {
+ Datamatcher ma;
+ if (!datamatcher_init(&ma, match, flags)) {
+ for (id = 1; id < pool->ss.nstrings; id++)
+ if (pool->whatprovides[id] && datamatcher_match(&ma, id2str(pool, id)))
+ queue_push(&q, id);
+ datamatcher_free(&ma);
+ }
+ }
return q;
}
# move to job?
%perlcode {
sub solv::Pool::jobsolvables {
my ($self, @args) = @_;
- return map {$self->{'solvables'}->[$_]} @{$self->jobsolvids(@args)};
+ return map {$self->{'solvables'}->[$_]} $self->jobsolvids(@args);
}
sub solv::Pool::providers {
my ($self, @args) = @_;
- return map {$self->{'solvables'}->[$_]} @{$self->providerids(@args)};
+ return map {$self->{'solvables'}->[$_]} $self->providerids(@args);
}
}
#endif
return 1;
}
-#ifdef SWIGPERL
- perlmkiter(Dataiterator, Repo::dataiterator_new, solvc::Repo_dataiterator_new)
-#endif
-
%newobject dataiterator_new;
Dataiterator *dataiterator_new(Id p, Id key, const char *match, int flags) {
return new_Dataiterator($self->pool, $self, p, key, match, flags);
Repo_solvable_iterator * const solvables;
%{
SWIGINTERN Repo_solvable_iterator * Repo_solvables_get(Repo *repo) {
- Repo_solvable_iterator *s;
- s = sat_calloc(1, sizeof(*s));
- s->repo = repo;
- s->id = 0;
- return s;
+ return new_Repo_solvable_iterator(repo);
}
%}
+ %newobject solvables_iter;
+ Repo_solvable_iterator *solvables_iter() {
+ return new_Repo_solvable_iterator($self);
+ }
XRepodata *add_repodata(int flags = 0) {
Repodata *rd = repo_add_repodata($self, flags);
}
}
#endif
+
+#ifdef SWIGPERL
+ perliter(solv::Dataiterator)
+#endif
+
%newobject __next__;
- Dataiterator *__next__() {
+ Datamatch *__next__() {
Dataiterator *ndi;
if (!dataiterator_step($self)) {
return 0;
dataiterator_init_clone(ndi, $self);
return ndi;
}
- void setpos_parent() {
- dataiterator_setpos_parent($self);
- }
void prepend_keyname(Id key) {
dataiterator_prepend_keyname($self, key);
}
void skip_solvable() {
dataiterator_skip_solvable($self);
}
+}
+%extend Datamatch {
+ ~Datamatch() {
+ dataiterator_free($self);
+ sat_free($self);
+ }
%newobject solvable;
XSolvable * const solvable;
%{
- SWIGINTERN XSolvable *Dataiterator_solvable_get(Dataiterator *di) {
+ SWIGINTERN XSolvable *Datamatch_solvable_get(Dataiterator *di) {
return new_XSolvable(di->pool, di->solvid);
}
%}
int match_num2() {
return $self->kv.num2;
}
+ void setpos_parent() {
+ dataiterator_setpos_parent($self);
+ }
}
%extend Pool_solvable_iterator {
+ Pool_solvable_iterator(Pool *pool) {
+ Pool_solvable_iterator *s;
+ s = sat_calloc(1, sizeof(*s));
+ s->pool = pool;
+ return s;
+ }
#if defined(SWIGPYTHON)
%newobject __iter__;
Pool_solvable_iterator *__iter__() {
}
}
#endif
+
+#ifdef SWIGPERL
+ perliter(solv::Pool_solvable_iterator)
+#endif
%newobject __next__;
XSolvable *__next__() {
Pool *pool = $self->pool;
}
%extend Pool_repo_iterator {
+ Pool_repo_iterator(Pool *pool) {
+ Pool_repo_iterator *s;
+ s = sat_calloc(1, sizeof(*s));
+ s->pool = pool;
+ return s;
+ }
#if defined(SWIGPYTHON)
%newobject __iter__;
Pool_repo_iterator *__iter__() {
}
%extend Repo_solvable_iterator {
+ Repo_solvable_iterator(Repo *repo) {
+ Repo_solvable_iterator *s;
+ s = sat_calloc(1, sizeof(*s));
+ s->repo = repo;
+ return s;
+ }
#if defined(SWIGPYTHON)
%newobject __iter__;
Repo_solvable_iterator *__iter__() {
}
sub solv::Problem::findallproblemrule {
my ($self, $unfiltered) = @_;
- return map {solv::XRule->new($self->{'solv'}, $_)} @{$self->findallproblemrule_helper($unfiltered)};
+ return map {solv::XRule->new($self->{'solv'}, $_)} $self->findallproblemrule_helper($unfiltered);
}
sub solv::Problem::solutions {
my ($self) = @_;
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;
+ e->type = e->rp ? SOLVER_SOLUTION_REPLACE : SOLVER_SOLUTION_ERASE;
} else {
e->type = e->p;
e->p = e->rp;
return (e->p - 1) / 2;
}
%}
+ %newobject Job;
+ Job *Job() {
+ if ($self->type == SOLVER_SOLUTION_INFARCH || $self->type == SOLVER_SOLUTION_DISTUPGRADE)
+ return new_Job($self->solv->pool, SOLVER_INSTALL|SOLVER_SOLVABLE, $self->p);
+ if ($self->type == SOLVER_SOLUTION_REPLACE)
+ return new_Job($self->solv->pool, SOLVER_INSTALL|SOLVER_SOLVABLE, $self->rp);
+ if ($self->type == SOLVER_SOLUTION_ERASE)
+ return new_Job($self->solv->pool, SOLVER_ERASE|SOLVER_SOLVABLE, $self->p);
+ return 0;
+ }
}
%extend Solver {
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_ERASE = SOLVER_SOLUTION_ERASE;
static const int SOLVER_SOLUTION_REPLACE = SOLVER_SOLUTION_REPLACE;
static const int POLICY_ILLEGAL_DOWNGRADE = POLICY_ILLEGAL_DOWNGRADE;
return r
}
#endif
- Queue installedresult_helper(int *OUTPUT) {
+#if defined(SWIGPERL)
+ %perlcode {
+ sub solv::Transaction::classify {
+ my ($self, $mode) = @_;
+ $mode ||= 0;
+ my @r = $self->classify_helper($mode);
+ my @res;
+ while (@r) {
+ my ($type, $cnt, $fromid, $toid) = splice(@r, 0, 4);
+ next if $type == $solv::Transaction::SOLVER_TRANSACTION_IGNORE;
+ push @res, [$type, [ map {$self->{'pool'}->{'solvables'}->[$_]} $self->classify_pkgs_helper($mode, $type, $fromid, $toid) ], $fromid, $toid];
+ }
+ return @res;
+ }
+ }
+#endif
+ Queue newpackages_helper() {
Queue q;
+ int cut;
queue_init(&q);
- *OUTPUT = transaction_installedresult(self, &q);
+ cut = transaction_installedresult(self, &q);
+ queue_truncate(&q, cut);
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
+ Queue keptpackages_helper() {
+ Queue q;
+ int cut;
+ queue_init(&q);
+ cut = transaction_installedresult(self, &q);
+ if (cut)
+ queue_deleten(&q, 0, cut);
+ return q;
}
-#endif
Queue steps_helper() {
Queue q;
queue_init_clone(&q, &$self->steps);
}
#if defined(SWIGPYTHON)
%pythoncode {
+ def newpackages(self):
+ return [ self.pool.solvables[i] for i in self.newpackages_helper() ]
+ def keptpackages(self):
+ return [ self.pool.solvables[i] for i in self.keptpackages_helper() ]
def steps(self):
return [ self.pool.solvables[i] for i in self.steps_helper() ]
}
#endif
+#if defined(SWIGPERL)
+ %perlcode {
+ sub solv::Transaction::newpackages {
+ my ($self) = @_;
+ return map {$self->{'pool'}->{'solvables'}->[$_]} $self->newpackages_helper();
+ }
+ sub solv::Transaction::keptpackages {
+ my ($self) = @_;
+ return map {$self->{'pool'}->{'solvables'}->[$_]} $self->newpackages_helper();
+ }
+ sub solv::Transaction::steps {
+ my ($self) = @_;
+ return map {$self->{'pool'}->{'solvables'}->[$_]} $self->steps_helper();
+ }
+ }
+#endif
int calc_installsizechange() {
return transaction_calc_installsizechange($self);
}
+ void order(int flags) {
+ transaction_order($self, flags);
+ }
}
%extend XRule {
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);
+ Ruleinfo *info() {
+ Ruleinfo *ri = sat_calloc(1, sizeof(*ri));
+ ri->solv = $self->solv;
+ ri->type = solver_ruleinfo($self->solv, $self->id, &ri->source, &ri->target, &ri->dep);
+ return ri;
}
-#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
-#if defined(SWIGPERL)
- %perlcode {
- sub solv::XRule::info {
- my ($self) = @_;
- my ($type, $source, $target, $dep) = $self->info_helper();
- $source = $self->{'solv'}->{'pool'}->{'solvables'}->[$source] if $source;
- $target = $self->{'solv'}->{'pool'}->{'solvables'}->[$target] if $target;
- return ($type, $source, $target, $dep);
+}
+
+%extend Ruleinfo {
+ XSolvable * const solvable;
+ XSolvable * const othersolvable;
+ %{
+ SWIGINTERN XSolvable *Ruleinfo_solvable_get(Ruleinfo *ri) {
+ return new_XSolvable(ri->solv->pool, ri->source);
+ }
+ SWIGINTERN XSolvable *Ruleinfo_othersolvable_get(Ruleinfo *ri) {
+ return new_XSolvable(ri->solv->pool, ri->target);
}
+ %}
+ const char *problemstr() {
+ return solver_problemruleinfo2str($self->solv, $self->type, $self->source, $self->target, $self->dep);
}
-#endif
}
-
%extend XRepodata {
XRepodata(Repo *repo, Id id) {
XRepodata *xr = sat_calloc(1, sizeof(*xr));