summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2016-10-27 14:54:32 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2016-10-27 14:54:33 +0900
commit9d82811ac90c5db61fca60e3e7c95ba58bc66393 (patch)
tree14fd1327bfb65babc5a84f7c719eb3c723035b6b /examples
parent1a93853889c819ac2d3c8e83e856f4775e664b00 (diff)
downloadlibsolv-9d82811ac90c5db61fca60e3e7c95ba58bc66393.tar.gz
libsolv-9d82811ac90c5db61fca60e3e7c95ba58bc66393.tar.bz2
libsolv-9d82811ac90c5db61fca60e3e7c95ba58bc66393.zip
Imported Upstream version 0.6.12upstream/0.6.12
Change-Id: I57ee1847c5c25f2602e0348213fa145f97cc3434 Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
Diffstat (limited to 'examples')
-rwxr-xr-xexamples/p5solv83
-rwxr-xr-xexamples/pysolv92
-rwxr-xr-xexamples/rbsolv82
-rw-r--r--examples/solv.c30
-rwxr-xr-xexamples/tclsolv803
5 files changed, 946 insertions, 144 deletions
diff --git a/examples/p5solv b/examples/p5solv
index 330ec63..0a1dbb0 100755
--- a/examples/p5solv
+++ b/examples/p5solv
@@ -42,9 +42,7 @@ sub calc_cookie_ext {
$chksum->add("1.1");
$chksum->add($cookie);
$chksum->add_fstat(fileno($f));
- my $extcookie = $chksum->raw();
- substr($extcookie, 0, 1) = chr(1) if ord(substr($extcookie, 0, 1)) == 0;
- return $extcookie;
+ return $chksum->raw();
}
sub cachepath {
@@ -67,6 +65,7 @@ sub load {
$dorefresh = 0 if @s && ($self->{metadata_expire} == -1 || time() - $s[9] < $self->{metadata_expire});
}
$self->{cookie} = '';
+ $self->{extcookie} = '';
if (!$dorefresh && $self->usecachedrepo()) {
print "repo: '$self->{alias}' cached\n";
return 1;
@@ -88,7 +87,7 @@ sub download {
$url =~ s!/$!!;
$url .= "/$file";
open(my $f, '+>', undef) || die;
- fcntl($f, Fcntl::F_SETFD, 0);
+ fcntl($f, Fcntl::F_SETFD, 0); # turn off CLOEXEC
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;
@@ -145,7 +144,7 @@ sub usecachedrepo {
}
sub writecachedrepo {
- my ($self, $ext, $info) = @_;
+ my ($self, $ext, $repodata) = @_;
return if $self->{incomplete};
mkdir("/var/cache/solv", 0755) unless -d "/var/cache/solv";
my ($f, $tmpname);
@@ -155,10 +154,10 @@ sub writecachedrepo {
return unless $f;
chmod 0444, $f;
my $ff = solv::xfopen_fd(undef, fileno($f));
- if (!$info) {
+ if (!$repodata) {
$self->{handle}->write($ff);
} elsif ($ext) {
- $info->write($ff);
+ $repodata->write($ff);
} else {
$self->{handle}->write_first_repodata($ff);
}
@@ -174,12 +173,12 @@ sub writecachedrepo {
if ($f) {
if (!$ext) {
$self->{handle}->empty();
- die("internal error, cannot reload solv file\n") unless $self->{handle}->add_solv($f, $solv::Repo::SOLV_ADD_NO_STUBS);
+ die("internal error, cannot reload solv file\n") unless $self->{handle}->add_solv($f, $repodata ? 0 : $solv::Repo::SOLV_ADD_NO_STUBS);
} else {
- $info->extend_to_repo();
+ $repodata->extend_to_repo();
my $flags = $solv::Repo::REPO_EXTEND_SOLVABLES;
$flags |= $solv::Repo::REPO_LOCALPOOL if $ext ne 'DL';
- $info->add_solv($f, $flags);
+ $repodata->add_solv($f, $flags);
}
}
}
@@ -191,6 +190,34 @@ sub packagespath {
return '';
}
+my %langtags = (
+ $solv::SOLVABLE_SUMMARY => $solv::REPOKEY_TYPE_STR,
+ $solv::SOLVABLE_DESCRIPTION => $solv::REPOKEY_TYPE_STR,
+ $solv::SOLVABLE_EULA => $solv::REPOKEY_TYPE_STR,
+ $solv::SOLVABLE_MESSAGEINS => $solv::REPOKEY_TYPE_STR,
+ $solv::SOLVABLE_MESSAGEDEL => $solv::REPOKEY_TYPE_STR,
+ $solv::SOLVABLE_CATEGORY => $solv::REPOKEY_TYPE_ID,
+);
+
+sub add_ext_keys {
+ my ($self, $ext, $repodata, $handle) = @_;
+ if ($ext eq 'DL') {
+ $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $solv::REPOSITORY_DELTAINFO);
+ $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $solv::REPOKEY_TYPE_FLEXARRAY);
+ } elsif ($ext eq 'DU') {
+ $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $solv::SOLVABLE_DISKUSAGE);
+ $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $solv::REPOKEY_TYPE_DIRNUMNUMARRAY);
+ } elsif ($ext eq 'FL') {
+ $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $solv::SOLVABLE_FILELIST);
+ $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $solv::REPOKEY_TYPE_DIRSTRARRAY);
+ } else {
+ for my $langid (sort { $a <=> $b } keys %langtags) {
+ $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $self->{handle}->{pool}->id2langid($langid, $ext, 1));
+ $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $langtags{$langid});
+ }
+ }
+}
+
package Repo::rpmmd;
our @ISA = ('Repo::generic');
@@ -222,13 +249,7 @@ sub add_ext {
$repodata->set_poolstr($handle, $solv::REPOSITORY_REPOMD_TYPE, $what);
$repodata->set_str($handle, $solv::REPOSITORY_REPOMD_LOCATION, $filename);
$repodata->set_checksum($handle, $solv::REPOSITORY_REPOMD_CHECKSUM, $chksum);
- if ($ext eq 'DL') {
- $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $solv::REPOSITORY_DELTAINFO);
- $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $solv::REPOKEY_TYPE_FLEXARRAY);
- } elsif ($ext eq 'FL') {
- $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $solv::SOLVABLE_FILELIST);
- $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $solv::REPOKEY_TYPE_DIRSTRARRAY);
- }
+ $self->add_ext_keys($ext, $repodata, $handle);
$repodata->add_flexarray($solv::SOLVID_META, $solv::REPOSITORY_EXTERNAL, $handle);
}
@@ -328,36 +349,15 @@ sub find {
return (undef, undef);
}
-my %langtags = (
- $solv::SOLVABLE_SUMMARY => $solv::REPOKEY_TYPE_STR,
- $solv::SOLVABLE_DESCRIPTION => $solv::REPOKEY_TYPE_STR,
- $solv::SOLVABLE_EULA => $solv::REPOKEY_TYPE_STR,
- $solv::SOLVABLE_MESSAGEINS => $solv::REPOKEY_TYPE_STR,
- $solv::SOLVABLE_MESSAGEDEL => $solv::REPOKEY_TYPE_STR,
- $solv::SOLVABLE_CATEGORY => $solv::REPOKEY_TYPE_ID,
-);
sub add_ext {
my ($self, $repodata, $what, $ext) = @_;
my ($filename, $chksum) = $self->find($what);
+ return unless $filename;
my $handle = $repodata->new_handle();
$repodata->set_str($handle, $solv::SUSETAGS_FILE_NAME, $filename);
$repodata->set_checksum($handle, $solv::SUSETAGS_FILE_CHECKSUM, $chksum);
- if ($ext eq 'DL') {
- $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $solv::REPOSITORY_DELTAINFO);
- $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $solv::REPOKEY_TYPE_FLEXARRAY);
- } elsif ($ext eq 'DU') {
- $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $solv::SOLVABLE_DISKUSAGE);
- $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $solv::REPOKEY_TYPE_DIRNUMNUMARRAY);
- } elsif ($ext eq 'FL') {
- $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $solv::SOLVABLE_FILELIST);
- $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $solv::REPOKEY_TYPE_DIRSTRARRAY);
- } else {
- for my $langid (sort { $a <=> $b } keys %langtags) {
- $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $self->{handle}->{pool}->id2langid($langid, $ext, 1));
- $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $langtags{$langid});
- }
- }
+ $self->add_ext_keys($ext, $repodata, $handle);
$repodata->add_flexarray($solv::SOLVID_META, $solv::REPOSITORY_EXTERNAL, $handle);
}
@@ -710,7 +710,7 @@ 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;
+ printf "Downloading %d packages, %d K\n", scalar(@newpkgs), $downloadsize / 1024;
for my $p (@newpkgs) {
my $repo = $p->{repo}->{appdata};
my ($location) = $p->lookup_location();
@@ -740,6 +740,7 @@ for my $p ($trans->steps()) {
print "install ".$p->str()."\n";
my $f = $newpkgsfps{$p->{id}};
my $mode = $steptype == $solv::Transaction::SOLVER_TRANSACTION_INSTALL ? '-U' : '-i';
+ $f->cloexec(0);
system('rpm', $mode, '--force', '--nodeps', '--nodigest', '--nosignature', "/dev/fd/".$f->fileno()) && die("rpm failed: $?\n");
delete $newpkgsfps{$p->{id}};
}
diff --git a/examples/pysolv b/examples/pysolv
index 22ae209..3d6ca07 100755
--- a/examples/pysolv
+++ b/examples/pysolv
@@ -68,16 +68,7 @@ class repo_generic(dict):
chksum.add("1.1");
chksum.add(cookie)
chksum.add_fstat(f.fileno())
- extcookie = chksum.raw()
- if sys.version > '3':
- # compatibility to c code
- if extcookie[0] == 0:
- extcookie[0] = 1
- else:
- # compatibility to c code
- if ord(extcookie[0]) == 0:
- extcookie[0] = chr(1)
- return extcookie
+ return chksum.raw()
def cachepath(self, ext = None):
path = re.sub(r'^\.', '_', self.name)
@@ -100,6 +91,7 @@ class repo_generic(dict):
except OSError:
pass
self['cookie'] = ''
+ self['extcookie'] = ''
if not dorefresh and self.usecachedrepo(None):
print("repo: '%s': cached" % self.name)
return True
@@ -237,7 +229,7 @@ class repo_generic(dict):
return False
return True
- def writecachedrepo(self, ext, info=None):
+ def writecachedrepo(self, ext, repodata=None):
if 'incomplete' in self:
return
tmpname = None
@@ -248,21 +240,21 @@ class repo_generic(dict):
os.fchmod(fd, 0o444)
f = os.fdopen(fd, 'wb+')
f = solv.xfopen_fd(None, f.fileno())
- if not info:
+ if not repodata:
self.handle.write(f)
elif ext:
- info.write(f)
- else: # rewrite_repos case
+ repodata.write(f)
+ else: # rewrite_repos case, do not write stubs
self.handle.write_first_repodata(f)
f.flush()
if self.type != 'system' and not ext:
- if 'extcookie' not in self:
+ if not self['extcookie']:
self['extcookie'] = self.calc_cookie_ext(f, self['cookie'])
- os.write(f.fileno(), self['extcookie'])
+ f.write(self['extcookie'])
if not ext:
- os.write(f.fileno(), self['cookie'])
+ f.write(self['cookie'])
else:
- os.write(f.fileno(), self['extcookie'])
+ f.write(self['extcookie'])
f.close
if self.handle.iscontiguous():
# switch to saved repo to activate paging and save memory
@@ -270,17 +262,20 @@ class repo_generic(dict):
if not ext:
# main repo
self.handle.empty()
- if not self.handle.add_solv(nf, solv.Repo.SOLV_ADD_NO_STUBS):
+ flags = solv.Repo.SOLV_ADD_NO_STUBS
+ if repodata:
+ flags = 0 # rewrite repos case, recreate stubs
+ if not self.handle.add_solv(nf, flags):
sys.exit("internal error, cannot reload solv file")
else:
# extension repodata
# need to extend to repo boundaries, as this is how
- # info.write() has written the data
- info.extend_to_repo()
+ # repodata.write() has written the data
+ repodata.extend_to_repo()
flags = solv.Repo.REPO_EXTEND_SOLVABLES
if ext != 'DL':
flags |= solv.Repo.REPO_LOCALPOOL
- info.add_solv(nf, flags)
+ repodata.add_solv(nf, flags)
os.rename(tmpname, self.cachepath(ext))
except (OSError, IOError):
if tmpname:
@@ -307,6 +302,29 @@ class repo_generic(dict):
def packagespath(self):
return ''
+ def add_ext_keys(self, ext, repodata, handle):
+ if ext == 'DL':
+ repodata.add_idarray(handle, solv.REPOSITORY_KEYS, solv.REPOSITORY_DELTAINFO)
+ repodata.add_idarray(handle, solv.REPOSITORY_KEYS, solv.REPOKEY_TYPE_FLEXARRAY)
+ elif ext == 'DU':
+ repodata.add_idarray(handle, solv.REPOSITORY_KEYS, solv.SOLVABLE_DISKUSAGE)
+ repodata.add_idarray(handle, solv.REPOSITORY_KEYS, solv.REPOKEY_TYPE_DIRNUMNUMARRAY)
+ elif ext == 'FL':
+ repodata.add_idarray(handle, solv.REPOSITORY_KEYS, solv.SOLVABLE_FILELIST)
+ repodata.add_idarray(handle, solv.REPOSITORY_KEYS, solv.REPOKEY_TYPE_DIRSTRARRAY)
+ else:
+ for langtag, langtagtype in [
+ (solv.SOLVABLE_SUMMARY, solv.REPOKEY_TYPE_STR),
+ (solv.SOLVABLE_DESCRIPTION, solv.REPOKEY_TYPE_STR),
+ (solv.SOLVABLE_EULA, solv.REPOKEY_TYPE_STR),
+ (solv.SOLVABLE_MESSAGEINS, solv.REPOKEY_TYPE_STR),
+ (solv.SOLVABLE_MESSAGEDEL, solv.REPOKEY_TYPE_STR),
+ (solv.SOLVABLE_CATEGORY, solv.REPOKEY_TYPE_ID)
+ ]:
+ repodata.add_idarray(handle, solv.REPOSITORY_KEYS, self.handle.pool.id2langid(langtag, ext, 1))
+ repodata.add_idarray(handle, solv.REPOSITORY_KEYS, langtagtype)
+
+
class repo_repomd(repo_generic):
def load(self, pool):
if super(repo_repomd, self).load(pool):
@@ -368,12 +386,7 @@ class repo_repomd(repo_generic):
repodata.set_poolstr(handle, solv.REPOSITORY_REPOMD_TYPE, what)
repodata.set_str(handle, solv.REPOSITORY_REPOMD_LOCATION, filename)
repodata.set_checksum(handle, solv.REPOSITORY_REPOMD_CHECKSUM, chksum)
- if ext == 'DL':
- repodata.add_idarray(handle, solv.REPOSITORY_KEYS, solv.REPOSITORY_DELTAINFO)
- repodata.add_idarray(handle, solv.REPOSITORY_KEYS, solv.REPOKEY_TYPE_FLEXARRAY)
- elif ext == 'FL':
- repodata.add_idarray(handle, solv.REPOSITORY_KEYS, solv.SOLVABLE_FILELIST)
- repodata.add_idarray(handle, solv.REPOSITORY_KEYS, solv.REPOKEY_TYPE_DIRSTRARRAY)
+ self.add_ext_keys(ext, repodata, handle)
repodata.add_flexarray(solv.SOLVID_META, solv.REPOSITORY_EXTERNAL, handle)
def add_exts(self):
@@ -469,23 +482,7 @@ class repo_susetags(repo_generic):
repodata.set_str(handle, solv.SUSETAGS_FILE_NAME, filename)
if chksum:
repodata.set_checksum(handle, solv.SUSETAGS_FILE_CHECKSUM, chksum)
- if ext == 'DU':
- repodata.add_idarray(handle, solv.REPOSITORY_KEYS, solv.SOLVABLE_DISKUSAGE)
- repodata.add_idarray(handle, solv.REPOSITORY_KEYS, solv.REPOKEY_TYPE_DIRNUMNUMARRAY)
- elif ext == 'FL':
- repodata.add_idarray(handle, solv.REPOSITORY_KEYS, solv.SOLVABLE_FILELIST)
- repodata.add_idarray(handle, solv.REPOSITORY_KEYS, solv.REPOKEY_TYPE_DIRSTRARRAY)
- else:
- for langtag, langtagtype in [
- (solv.SOLVABLE_SUMMARY, solv.REPOKEY_TYPE_STR),
- (solv.SOLVABLE_DESCRIPTION, solv.REPOKEY_TYPE_STR),
- (solv.SOLVABLE_EULA, solv.REPOKEY_TYPE_STR),
- (solv.SOLVABLE_MESSAGEINS, solv.REPOKEY_TYPE_STR),
- (solv.SOLVABLE_MESSAGEDEL, solv.REPOKEY_TYPE_STR),
- (solv.SOLVABLE_CATEGORY, solv.REPOKEY_TYPE_ID)
- ]:
- repodata.add_idarray(handle, solv.REPOSITORY_KEYS, self.handle.pool.id2langid(langtag, ext, 1))
- repodata.add_idarray(handle, solv.REPOSITORY_KEYS, langtagtype)
+ self.add_ext_keys(ext, repodata, handle)
repodata.add_flexarray(solv.SOLVID_META, solv.REPOSITORY_EXTERNAL, handle)
def add_exts(self):
@@ -852,7 +849,7 @@ if newpkgs:
downloadsize = 0
for p in newpkgs:
downloadsize += p.lookup_num(solv.SOLVABLE_DOWNLOADSIZE)
- print("Downloading %d packages, %d K" % (len(newpkgs), downloadsize))
+ print("Downloading %d packages, %d K" % (len(newpkgs), downloadsize / 1024))
for p in newpkgs:
repo = p.repo.appdata
location, medianr = p.lookup_location()
@@ -866,7 +863,7 @@ if newpkgs:
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, solv.Dataiterator.SEARCH_STRING)
+ di = p.repo.Dataiterator_meta(solv.DELTA_PACKAGE_NAME, pname, solv.Dataiterator.SEARCH_STRING)
di.prepend_keyname(solv.REPOSITORY_DELTAINFO)
for d in di:
dp = d.parentpos()
@@ -893,6 +890,7 @@ if newpkgs:
continue
nf = tempfile.TemporaryFile()
nf = os.dup(nf.fileno()) # get rid of CLOEXEC
+ f.cloexec(0)
st = subprocess.call(['/usr/bin/applydeltarpm', '-a', p.arch, "/dev/fd/%d" % f.fileno(), "/dev/fd/%d" % nf])
if st:
os.close(nf)
diff --git a/examples/rbsolv b/examples/rbsolv
index 470438d..be633f3 100755
--- a/examples/rbsolv
+++ b/examples/rbsolv
@@ -44,9 +44,7 @@ class Repo_generic
chksum.add("1.1")
chksum.add(cookie)
chksum.add_fstat(f.fileno)
- extcookie = chksum.raw()
- extcookie[0] = 1 if extcookie[0] == 0
- return extcookie
+ return chksum.raw()
end
def cachepath(ext = nil)
@@ -68,6 +66,7 @@ class Repo_generic
end
end
@cookie = nil
+ @extcookie = nil
if !dorefresh && usecachedrepo(nil)
puts "repo: '#{@name}' cached"
return true
@@ -152,17 +151,17 @@ class Repo_generic
return true
end
- def writecachedrepo(ext, info = nil)
+ def writecachedrepo(ext, repodata = nil)
return if @incomplete
begin
Dir::mkdir("/var/cache/solv", 0755) unless FileTest.directory?("/var/cache/solv")
f = Tempfile.new('.newsolv-', '/var/cache/solv')
f.chmod(0444)
sf = Solv::xfopen_fd('', f.fileno)
- if !info
+ if !repodata
@handle.write(sf)
elsif ext
- info.write(sf)
+ repodata.write(sf)
else
@handle.write_first_repodata(sf)
end
@@ -179,12 +178,12 @@ class Repo_generic
if sf
if !ext
@handle.empty()
- abort("internal error, cannot reload solv file") unless @handle.add_solv(sf, Solv::Repo::SOLV_ADD_NO_STUBS)
+ abort("internal error, cannot reload solv file") unless @handle.add_solv(sf, repodata ? 0 : Solv::Repo::SOLV_ADD_NO_STUBS)
else
- info.extend_to_repo()
+ repodata.extend_to_repo()
flags = Solv::Repo::REPO_EXTEND_SOLVABLES
flags |= Solv::Repo::REPO_LOCALPOOL if ext != 'DL'
- info.add_solv(sf, flags)
+ repodata.add_solv(sf, flags)
end
sf.close
end
@@ -214,6 +213,33 @@ class Repo_generic
def packagespath()
return ''
end
+
+ @@langtags = {
+ Solv::SOLVABLE_SUMMARY => Solv::REPOKEY_TYPE_STR,
+ Solv::SOLVABLE_DESCRIPTION => Solv::REPOKEY_TYPE_STR,
+ Solv::SOLVABLE_EULA => Solv::REPOKEY_TYPE_STR,
+ Solv::SOLVABLE_MESSAGEINS => Solv::REPOKEY_TYPE_STR,
+ Solv::SOLVABLE_MESSAGEDEL => Solv::REPOKEY_TYPE_STR,
+ Solv::SOLVABLE_CATEGORY => Solv::REPOKEY_TYPE_ID,
+ }
+
+ def add_ext_keys(ext, repodata, h)
+ if ext == 'DL'
+ repodata.add_idarray(h, Solv::REPOSITORY_KEYS, Solv::REPOSITORY_DELTAINFO)
+ repodata.add_idarray(h, Solv::REPOSITORY_KEYS, Solv::REPOKEY_TYPE_FLEXARRAY)
+ elsif ext == 'DU'
+ repodata.add_idarray(h, Solv::REPOSITORY_KEYS, Solv::SOLVABLE_DISKUSAGE)
+ repodata.add_idarray(h, Solv::REPOSITORY_KEYS, Solv::REPOKEY_TYPE_DIRNUMNUMARRAY)
+ elsif ext == 'FL'
+ repodata.add_idarray(h, Solv::REPOSITORY_KEYS, Solv::SOLVABLE_FILELIST)
+ repodata.add_idarray(h, Solv::REPOSITORY_KEYS, Solv::REPOKEY_TYPE_DIRSTRARRAY)
+ else
+ @@langtags.sort.each do |langid, langtype|
+ repodata.add_idarray(h, Solv::REPOSITORY_KEYS, @handle.pool.id2langid(langid, ext, true))
+ repodata.add_idarray(h, Solv::REPOSITORY_KEYS, langtype)
+ end
+ end
+ end
end
class Repo_rpmmd < Repo_generic
@@ -285,13 +311,7 @@ class Repo_rpmmd < Repo_generic
repodata.set_poolstr(h, Solv::REPOSITORY_REPOMD_TYPE, what)
repodata.set_str(h, Solv::REPOSITORY_REPOMD_LOCATION, filename)
repodata.set_checksum(h, Solv::REPOSITORY_REPOMD_CHECKSUM, filechksum)
- if ext == 'DL'
- repodata.add_idarray(h, Solv::REPOSITORY_KEYS, Solv::REPOSITORY_DELTAINFO)
- repodata.add_idarray(h, Solv::REPOSITORY_KEYS, Solv::REPOKEY_TYPE_FLEXARRAY)
- elsif ext == 'FL'
- repodata.add_idarray(h, Solv::REPOSITORY_KEYS, Solv::SOLVABLE_FILELIST)
- repodata.add_idarray(h, Solv::REPOSITORY_KEYS, Solv::REPOKEY_TYPE_DIRSTRARRAY)
- end
+ add_ext_keys(ext, repodata, h)
repodata.add_flexarray(Solv::SOLVID_META, Solv::REPOSITORY_EXTERNAL, h)
end
@@ -394,35 +414,12 @@ class Repo_susetags < Repo_generic
return true
end
- @@langtags = {
- Solv::SOLVABLE_SUMMARY => Solv::REPOKEY_TYPE_STR,
- Solv::SOLVABLE_DESCRIPTION => Solv::REPOKEY_TYPE_STR,
- Solv::SOLVABLE_EULA => Solv::REPOKEY_TYPE_STR,
- Solv::SOLVABLE_MESSAGEINS => Solv::REPOKEY_TYPE_STR,
- Solv::SOLVABLE_MESSAGEDEL => Solv::REPOKEY_TYPE_STR,
- Solv::SOLVABLE_CATEGORY => Solv::REPOKEY_TYPE_ID,
- }
-
def add_ext(repodata, what, ext)
(filename, filechksum) = find(what)
h = repodata.new_handle()
repodata.set_str(h, Solv::SUSETAGS_FILE_NAME, filename)
repodata.set_checksum(h, Solv::SUSETAGS_FILE_CHECKSUM, filechksum)
- if ext == 'DL'
- repodata.add_idarray(h, Solv::REPOSITORY_KEYS, Solv::REPOSITORY_DELTAINFO)
- repodata.add_idarray(h, Solv::REPOSITORY_KEYS, Solv::REPOKEY_TYPE_FLEXARRAY)
- elsif ext == 'DU'
- repodata.add_idarray(h, Solv::REPOSITORY_KEYS, Solv::SOLVABLE_DISKUSAGE)
- repodata.add_idarray(h, Solv::REPOSITORY_KEYS, Solv::REPOKEY_TYPE_DIRNUMNUMARRAY)
- elsif ext == 'FL'
- repodata.add_idarray(h, Solv::REPOSITORY_KEYS, Solv::SOLVABLE_FILELIST)
- repodata.add_idarray(h, Solv::REPOSITORY_KEYS, Solv::REPOKEY_TYPE_DIRSTRARRAY)
- else
- @@langtags.sort.each do |langid, langtype|
- repodata.add_idarray(h, Solv::REPOSITORY_KEYS, @handle.pool.id2langid(langid, ext, true))
- repodata.add_idarray(h, Solv::REPOSITORY_KEYS, langtype)
- end
- end
+ add_ext_keys(ext, repodata, h)
repodata.add_flexarray(Solv::SOLVID_META, Solv::REPOSITORY_EXTERNAL, h)
end
@@ -494,7 +491,7 @@ class Repo_system < Repo_generic
end
f = Solv::xfopen(cachepath())
@handle.add_rpmdb_reffp(f, Solv::Repo::REPO_REUSE_REPODATA)
- f.close
+ f.close if f
writecachedrepo(nil)
return true
end
@@ -727,7 +724,7 @@ if !newpkgs.empty?
for p in newpkgs
downloadsize += p.lookup_num(Solv::SOLVABLE_DOWNLOADSIZE)
end
- puts "Downloading #{newpkgs.length} packages, #{downloadsize} K"
+ puts "Downloading #{newpkgs.length} packages, #{downloadsize / 1024} K"
for p in newpkgs
repo = p.repo.appdata
location, medianr = p.lookup_location()
@@ -758,6 +755,7 @@ for p in trans.steps
f = newpkgsfp.delete(p.id)
next unless f
mode = steptype == Solv::Transaction::SOLVER_TRANSACTION_INSTALL ? '-U' : '-i'
+ f.cloexec(0)
system('rpm', mode, '--force', '--nodeps', '--nodigest', '--nosignature', "/dev/fd/#{f.fileno().to_s}") || abort("rpm failed: #{$? >> 8}")
f.close
end
diff --git a/examples/solv.c b/examples/solv.c
index 8b0d6cc..fc420b3 100644
--- a/examples/solv.c
+++ b/examples/solv.c
@@ -124,8 +124,8 @@ struct repoinfo {
int metadata_expire;
char **components;
int ncomponents;
-
unsigned char cookie[32];
+ int extcookieset;
unsigned char extcookie[32];
int incomplete;
};
@@ -1133,7 +1133,7 @@ usecachedrepo(Repo *repo, const char *repoext, unsigned char *cookie, int mark)
fclose(fp);
return 0;
}
- if (cookie && memcmp(cookie, mycookie, sizeof(mycookie)))
+ if (cookie && memcmp(cookie, mycookie, sizeof(mycookie)) != 0)
{
fclose(fp);
return 0;
@@ -1165,6 +1165,7 @@ usecachedrepo(Repo *repo, const char *repoext, unsigned char *cookie, int mark)
{
memcpy(cinfo->cookie, mycookie, sizeof(mycookie));
memcpy(cinfo->extcookie, myextcookie, sizeof(myextcookie));
+ cinfo->extcookieset = 1;
}
if (mark)
futimens(fileno(fp), 0); /* try to set modification time */
@@ -1173,7 +1174,7 @@ usecachedrepo(Repo *repo, const char *repoext, unsigned char *cookie, int mark)
}
void
-writecachedrepo(Repo *repo, Repodata *info, const char *repoext, unsigned char *cookie)
+writecachedrepo(Repo *repo, Repodata *repodata, const char *repoext, unsigned char *cookie)
{
FILE *fp;
int i, fd;
@@ -1211,22 +1212,22 @@ writecachedrepo(Repo *repo, Repodata *info, const char *repoext, unsigned char *
if (i < repo->end)
onepiece = 0;
- if (!info)
+ if (!repodata)
repo_write(repo, fp);
else if (repoext)
- repodata_write(info, fp);
+ repodata_write(repodata, fp);
else
{
int oldnrepodata = repo->nrepodata;
repo->nrepodata = oldnrepodata > 2 ? 2 : oldnrepodata; /* XXX: do this right */
repo_write(repo, fp);
repo->nrepodata = oldnrepodata;
- onepiece = 0;
+ onepiece = 0; /* don't bother for the added file provides */
}
if (!repoext && cinfo)
{
- if (!cinfo->extcookie[0])
+ if (!cinfo->extcookieset)
{
/* create the ext cookie and append it */
/* we just need some unique ID */
@@ -1234,8 +1235,7 @@ writecachedrepo(Repo *repo, Repodata *info, const char *repoext, unsigned char *
if (!fstat(fileno(fp), &stb))
memset(&stb, 0, sizeof(stb));
calc_checksum_stat(&stb, REPOKEY_TYPE_SHA256, cookie, cinfo->extcookie);
- if (cinfo->extcookie[0] == 0)
- cinfo->extcookie[0] = 1;
+ cinfo->extcookieset = 1;
}
if (fwrite(cinfo->extcookie, 32, 1, fp) != 1)
{
@@ -1281,12 +1281,12 @@ writecachedrepo(Repo *repo, Repodata *info, const char *repoext, unsigned char *
int flags = REPO_USE_LOADING|REPO_EXTEND_SOLVABLES;
/* make sure repodata contains complete repo */
/* (this is how repodata_write saves it) */
- repodata_extend_block(info, repo->start, repo->end - repo->start);
- info->state = REPODATA_LOADING;
+ repodata_extend_block(repodata, repo->start, repo->end - repo->start);
+ repodata->state = REPODATA_LOADING;
if (strcmp(repoext, "DL") != 0)
flags |= REPO_LOCALPOOL;
repo_add_solv(repo, fp, flags);
- info->state = REPODATA_AVAILABLE; /* in case the load failed */
+ repodata->state = REPODATA_AVAILABLE; /* in case the load failed */
}
fclose(fp);
}
@@ -1400,7 +1400,8 @@ repomd_load_ext(Repo *repo, Repodata *data)
printf("%s\n", pool_errstr(repo->pool));
return 0;
}
- writecachedrepo(repo, data, ext, cinfo->extcookie);
+ if (cinfo->extcookieset)
+ writecachedrepo(repo, data, ext, cinfo->extcookie);
return 1;
}
@@ -1546,7 +1547,8 @@ susetags_load_ext(Repo *repo, Repodata *data)
return 0;
}
fclose(fp);
- writecachedrepo(repo, data, ext, cinfo->extcookie);
+ if (cinfo->extcookieset)
+ writecachedrepo(repo, data, ext, cinfo->extcookie);
return 1;
}
#endif
diff --git a/examples/tclsolv b/examples/tclsolv
new file mode 100755
index 0000000..6f819aa
--- /dev/null
+++ b/examples/tclsolv
@@ -0,0 +1,803 @@
+#!/usr/bin/tclsh
+
+package require solv
+package require inifile
+package require fileutil
+
+set reposdir /etc/zypp/repos.d
+
+### some helpers
+
+proc fileno {file} {
+ if [regexp -- {^file(\d+)$} $file match fd] {
+ return $fd
+ }
+ error "file not open"
+}
+
+set ::globalarray_cnt 0
+
+proc globalarray {} {
+ set name "::globalarray_[incr ::globalarray_cnt]"
+ array set $name [list varName $name]
+ return $name
+}
+
+### generic repo handling (cache reading/writing)
+
+proc repo_calc_cookie_file {selfName filename} {
+ upvar $selfName self
+ set chksum [solv::new_Chksum $solv::REPOKEY_TYPE_SHA256]
+ $chksum add "1.1"
+ $chksum add_stat $filename
+ return [$chksum raw]
+}
+
+proc repo_calc_cookie_fp {selfName fp} {
+ upvar $selfName self
+ set chksum [solv::new_Chksum $solv::REPOKEY_TYPE_SHA256]
+ $chksum add "1.1"
+ $chksum add_fp $fp
+ return [$chksum raw]
+}
+
+proc repo_calc_cookie_ext {selfName f cookie} {
+ upvar $selfName self
+ set chksum [solv::new_Chksum $solv::REPOKEY_TYPE_SHA256]
+ $chksum add "1.1"
+ $chksum add $cookie
+ $chksum add_fstat [$f fileno]
+ return [$chksum raw]
+}
+
+proc repo_cachepath {selfName {ext "-"}} {
+ upvar $selfName self
+ regsub {^\.} $self(name) _ path
+ if {$ext ne "-"} {
+ set path "${path}_$ext.solvx"
+ } else {
+ set path "${path}.solv"
+ }
+ regsub -all / $path _ path
+ return "/var/cache/solv/$path"
+}
+
+proc repo_generic_load {selfName pool} {
+ upvar $selfName self
+ set handle [ $pool add_repo $self(name) ]
+ set self(handle) $handle
+ $handle configure -priority [expr 99 - $self(priority)] -appdata $self(varName)
+ set dorefresh $self(autorefresh)
+ set metadata_expire $self(metadata_expire)
+ catch {
+ if {$metadata_expire == -1 || [clock seconds] - [file mtime [repo_cachepath self]] < $metadata_expire} {
+ set dorefresh 0
+ }
+ }
+ set self(cookie) {}
+ set self(extcookie) {}
+ if { !$dorefresh && [repo_usecachedrepo self] } {
+ puts "repo $self(name): cached"
+ return 1
+ }
+ return 0
+}
+
+proc repo_free_handle {selfName} {
+ upvar $selfName self
+ set handle $self(handle)
+ unset self(handle)
+ $handle free 1
+}
+
+proc repo_usecachedrepo {selfName {ext "-"} {mark 0}} {
+ upvar $selfName self
+ set repopath [repo_cachepath self $ext]
+ set code [catch {
+ set f [open $repopath "rb"]
+ seek $f -32 end
+ set fcookie [read $f 32]
+ set cookie [expr {$ext eq "-" ? $self(cookie) : $self(extcookie)}]
+ if {$cookie ne {} && $cookie ne $fcookie} {
+ close $f
+ return 0
+ }
+ set fextcookie {}
+ if {$ext eq "-" && $self(type) ne "system"} {
+ seek $f -64 end
+ set fextcookie [read $f 32]
+ }
+ seek $f 0 start
+ set ff [solv::xfopen_fd {} [fileno $f]]
+ close $f
+ set flags 0
+ if {$ext ne "-"} {
+ set flags [expr $solv::Repo_REPO_USE_LOADING | $solv::Repo_REPO_EXTEND_SOLVABLES]
+ if {$ext ne "DL"} {
+ set flags [expr $flags | $solv::Repo_REPO_LOCALPOOL]
+ }
+ }
+ if {! [$self(handle) add_solv $ff $flags]} {
+ $ff close
+ return 0
+ }
+ $ff close
+ if {$self(type) ne "system" && $ext eq "-"} {
+ set self(cookie) $fcookie
+ set self(extcookie) $fextcookie
+ }
+ if {$mark} {
+ catch {
+ ::fileutil::touch -c -m -t [clock seconds] $repopath
+ }
+ }
+ return 1
+ } res]
+ return [expr {$code == 2 ? $res : 0}]
+}
+
+proc repo_writecachedrepo {selfName {ext "-"} {repodata "NULL"}} {
+ upvar $selfName self
+ if [info exists self(incomplete)] {
+ return
+ }
+ file mkdir "/var/cache/solv"
+ ::fileutil::tempdir "/var/cache/solv"
+ set tempfilename [::fileutil::tempfile ".newsolv-"]
+ ::fileutil::tempdirReset
+ set f [solv::xfopen $tempfilename "w+"]
+ file attributes $tempfilename -permissions 0444
+ if {$repodata eq {NULL}} {
+ $self(handle) write $f
+ } else {
+ $repodata write $f
+ }
+ $f flush
+ if {$self(type) ne "system" && $ext eq "-"} {
+ if {$self(extcookie) eq {}} {
+ set self(extcookie) [repo_calc_cookie_ext self $f $self(cookie)]
+ }
+ $f write $self(extcookie)
+ }
+ $f write [expr {$ext eq "-" ? $self(cookie) : $self(extcookie)}]
+ $f close
+ file rename -force -- $tempfilename [repo_cachepath self $ext]
+}
+
+proc repo_download {selfName file uncompress chksum {markincomplete 0}} {
+ upvar $selfName self
+ regsub {/$} $self(baseurl) {} url
+ set url "$url/$file"
+ set tempfilename [::fileutil::tempfile]
+ set f [open $tempfilename rb+]
+ file delete -- $tempfilename
+ if [catch {
+ exec -ignorestderr -- curl -f -s -L $url ">@$f"
+ }] {
+ seek $f 0 end
+ if {($chksum ne "" && $chksum ne "NULL") || [tell $f] != 0} {
+ puts "$file: download error"
+ }
+ close $f
+ return {NULL}
+ }
+ seek $f 0 start
+ if {$chksum ne "" && $chksum ne "NULL"} {
+ set fchksum [solv::new_Chksum [$chksum cget -type]]
+ if {$fchksum eq "" || $fchksum eq "NULL"} {
+ puts "$file: unknown checksum type"
+ if {$markincomplete} {
+ set self(incomplete) 1
+ }
+ close $f
+ return {NULL}
+ }
+ $fchksum add_fd [fileno $f]
+ if {[$fchksum != $chksum]} {
+ puts "$file: checksum mismatch"
+ if {$markincomplete} {
+ set self(incomplete) 1
+ }
+ close $f
+ return {NULL}
+ }
+ }
+ set ff [solv::xfopen_fd [expr {$uncompress ? $file : ""}] [fileno $f]]
+ close $f
+ return $ff
+}
+
+proc repo_generic_add_ext_keys {selfName ext repodata h} {
+ upvar $selfName self
+ if {$ext eq "DL"} {
+ $repodata add_idarray $h $solv::REPOSITORY_KEYS $solv::REPOSITORY_DELTAINFO
+ $repodata add_idarray $h $solv::REPOSITORY_KEYS $solv::REPOKEY_TYPE_FLEXARRAY
+ } elseif {$ext eq "DU"} {
+ $repodata add_idarray $h $solv::REPOSITORY_KEYS $solv::SOLVABLE_DISKUSAGE
+ $repodata add_idarray $h $solv::REPOSITORY_KEYS $solv::REPOKEY_TYPE_DIRNUMNUMARRAY
+ } elseif {$ext eq "FL"} {
+ $repodata add_idarray $h $solv::REPOSITORY_KEYS $solv::SOLVABLE_FILELIST
+ $repodata add_idarray $h $solv::REPOSITORY_KEYS $solv::REPOKEY_TYPE_DIRSTRARRAY
+ }
+}
+
+### system
+
+proc repo_system_load {selfName pool} {
+ upvar $selfName self
+ set handle [ $pool add_repo $self(name) ]
+ set self(handle) $handle
+ $handle configure -appdata $self(varName)
+ $pool configure -installed $handle
+ puts -nonewline "rpm database: "
+ set self(cookie) [repo_calc_cookie_file self "/var/lib/rpm/Packages"]
+ if [repo_usecachedrepo self] {
+ puts "cached"
+ return 1
+ }
+ puts "reading"
+ set f [solv::xfopen [repo_cachepath self]]
+ $handle add_rpmdb_reffp $f $solv::Repo_REPO_REUSE_REPODATA
+ repo_writecachedrepo self
+}
+
+### repomd
+
+proc repo_repomd_add_ext {selfName repodata what ext} {
+ upvar $selfName self
+ set where [repo_repomd_find self $what]
+ if {$where eq {}} {
+ return
+ }
+ set h [$repodata new_handle]
+ $repodata set_poolstr $h $solv::REPOSITORY_REPOMD_TYPE $what
+ $repodata set_str $h $solv::REPOSITORY_REPOMD_LOCATION [lindex $where 0]
+ $repodata set_checksum $h $solv::REPOSITORY_REPOMD_CHECKSUM [lindex $where 1]
+ repo_generic_add_ext_keys self $ext $repodata $h
+ $repodata add_flexarray $solv::SOLVID_META $solv::REPOSITORY_EXTERNAL $h
+}
+
+proc repo_repomd_add_exts {selfName} {
+ upvar $selfName self
+ set repodata [$self(handle) add_repodata 0]
+ repo_repomd_add_ext self $repodata "filelists" "FL"
+ $repodata internalize
+}
+
+proc repo_repomd_find {selfName what} {
+ upvar $selfName self
+ set di [$self(handle) Dataiterator_meta $solv::REPOSITORY_REPOMD_TYPE $what $solv::Dataiterator_SEARCH_STRING]
+ $di prepend_keyname $solv::REPOSITORY_REPOMD
+ solv::iter d $di {
+ set dp [$d parentpos]
+ set filename [$dp lookup_str $solv::REPOSITORY_REPOMD_LOCATION]
+ set checksum [$dp lookup_checksum $solv::REPOSITORY_REPOMD_CHECKSUM]
+ if {$filename ne "" && $checksum eq "NULL"} {
+ puts "no $filename file checksum"
+ } elseif {$filename ne ""} {
+ return [list $filename $checksum]
+ }
+ }
+ return {}
+}
+
+proc repo_repomd_load {selfName pool} {
+ upvar $selfName self
+ if [repo_generic_load self $pool] {
+ return 1
+ }
+ puts -nonewline "rpmmd repo '$self(name)': "
+ set f [repo_download self {repodata/repomd.xml} 0 {}]
+ if {$f eq {NULL}} {
+ puts "no repomd.xml file, skipped"
+ repo_free_handle self
+ return 0
+ }
+ set self(cookie) [repo_calc_cookie_fp self $f]
+ if [repo_usecachedrepo self "-" 1] {
+ puts "cached"
+ return 1
+ }
+ set handle $self(handle)
+ $handle add_repomdxml $f
+ puts "fetching"
+ set primary [repo_repomd_find self primary]
+ if {$primary ne {}} {
+ set f [repo_download self [lindex $primary 0] 1 [lindex $primary 1] 1]
+ if {$f ne {NULL}} {
+ $handle add_rpmmd $f {}
+ $f close
+ }
+ if [info exists self(incomplete)] {
+ return 0
+ }
+ }
+ set updateinfo [repo_repomd_find self primary]
+ if {$updateinfo ne {}} {
+ set f [repo_download self [lindex $updateinfo 0] 1 [lindex $updateinfo 1] 1]
+ if {$f ne {NULL}} {
+ $handle add_updateinfoxml $f
+ $f close
+ }
+ }
+ repo_repomd_add_exts self
+ repo_writecachedrepo self
+ $self(handle) create_stubs
+ return 1
+}
+
+proc repo_repomd_packagespath {selfName} {
+ return ""
+}
+
+proc repo_repomd_load_ext {selfName repodata} {
+ upvar $selfName self
+ switch -- [$repodata lookup_str $solv::SOLVID_META $solv::REPOSITORY_REPOMD_TYPE] {
+ "deltainfo" {
+ set ext DL
+ }
+ "filelists" {
+ set ext FL
+ }
+ default {
+ return 0
+ }
+ }
+ puts -nonewline "\[$self(name):$ext: "
+ flush stdout
+ if [repo_usecachedrepo self $ext] {
+ puts "cached]"
+ return 1
+ }
+ puts "fetching]"
+ set handle $self(handle)
+ set filename [$repodata lookup_str $solv::SOLVID_META $solv::REPOSITORY_REPOMD_LOCATION]
+ set filechecksum [$repodata lookup_checksum $solv::SOLVID_META $solv::REPOSITORY_REPOMD_CHECKSUM]
+ set f [repo_download self $filename 1 $filechecksum]
+ if {$f eq {NULL}} {
+ return 0
+ }
+ if {$ext eq "FL"} {
+ $handle add_rpmmd $f "FL" [ expr $solv::Repo_REPO_USE_LOADING | $solv::Repo_REPO_EXTEND_SOLVABLES | $solv::Repo_REPO_LOCALPOOL]
+ }
+ $f close
+ repo_writecachedrepo self $ext $repodata
+ return 1
+}
+
+### susetags
+
+proc repo_susetags_add_ext {selfName repodata what ext} {
+ upvar $selfName self
+ set where [repo_susetags_find self $what]
+ if {$where eq {}} {
+ return
+ }
+ set h [$repodata new_handle]
+ $repodata set_str $h $solv::SUSETAGS_FILE_NAME [lindex $where 0]
+ $repodata set_checksum $h $solv::SUSETAGS_FILE_CHECKSUM [lindex $where 1]
+ repo_generic_add_ext_keys self $ext $repodata $h
+ $repodata add_flexarray $solv::SOLVID_META $solv::REPOSITORY_EXTERNAL $h
+}
+
+proc repo_susetags_add_exts {selfName} {
+ upvar $selfName self
+ set repodata [$self(handle) add_repodata 0]
+ repo_susetags_add_ext self $repodata "packages.FL" "FL"
+ repo_susetags_add_ext self $repodata "packages.FL.gz" "FL"
+ $repodata internalize
+}
+
+proc repo_susetags_find {selfName what} {
+ upvar $selfName self
+ set di [$self(handle) Dataiterator_meta $solv::SUSETAGS_FILE_NAME $what $solv::Dataiterator_SEARCH_STRING]
+ $di prepend_keyname $solv::SUSETAGS_FILE
+ solv::iter d $di {
+ set dp [$d parentpos]
+ set checksum [$dp lookup_checksum $solv::SUSETAGS_FILE_CHECKSUM]
+ return [list $what $checksum]
+ }
+ return {}
+}
+
+proc repo_susetags_load {selfName pool} {
+ upvar $selfName self
+ if [repo_generic_load self $pool] {
+ return 1
+ }
+ puts -nonewline "susetags repo '$self(name)': "
+ set f [repo_download self {content} 0 {}]
+ if {$f eq {NULL}} {
+ puts "no content file, skipped"
+ repo_free_handle self
+ return 0
+ }
+ set self(cookie) [repo_calc_cookie_fp self $f]
+ if [repo_usecachedrepo self "-" 1] {
+ puts "cached"
+ return 1
+ }
+ set handle $self(handle)
+ $handle add_content $f
+ puts "fetching"
+ set defvendorid [[$handle cget -meta] lookup_id $solv::SUSETAGS_DEFAULTVENDOR]
+ set descrdir [[$handle cget -meta] lookup_str $solv::SUSETAGS_DESCRDIR]
+ if {$descrdir eq {NULL}} {
+ set descrdir "suse/setup/descr"
+ }
+ set packages [repo_susetags_find self "packages.gz"]
+ if {$packages eq {}} {
+ set packages [repo_susetags_find self "packages"]
+ }
+ if {$packages ne {}} {
+ set f [repo_download self "$descrdir/[lindex $packages 0]" 1 [lindex $packages 1] 1]
+ if {$f ne {NULL}} {
+ $handle add_susetags $f $defvendorid {} [expr $solv::Repo_REPO_NO_INTERNALIZE | $solv::Repo_SUSETAGS_RECORD_SHARES]
+ $f close
+ set packages [repo_susetags_find self "packages.en.gz"]
+ if {$packages eq {}} {
+ set packages [repo_susetags_find self "packages.en"]
+ }
+ if {$packages ne {}} {
+ set f [repo_download self "$descrdir/[lindex $packages 0]" 1 [lindex $packages 1] 1]
+ if {$f ne {NULL}} {
+ $handle add_susetags $f $defvendorid {} [expr $solv::Repo_REPO_NO_INTERNALIZE | $solv::Repo_REPO_REUSE_REPODATA | $solv::Repo_REPO_EXTEND_SOLVABLES ]
+ $f close
+ }
+ }
+ $handle internalize
+ }
+ }
+ repo_susetags_add_exts self
+ repo_writecachedrepo self
+ $self(handle) create_stubs
+ return 1
+}
+
+proc repo_susetags_packagespath {selfName} {
+ upvar $selfName self
+ set datadir [[$self(handle) cget -meta] lookup_str $solv::SUSETAGS_DATADIR]
+ return [expr {$datadir ne {} ? "$datadir/" : "suse/"}]
+}
+
+proc repo_susetags_load_ext {selfName repodata} {
+ upvar $selfName self
+ set filename [$repodata lookup_str $solv::SOLVID_META $solv::SUSETAGS_FILE_NAME]
+ set ext [string range $filename 9 10]
+ puts -nonewline "\[$self(name):$ext: "
+ flush stdout
+ if [repo_usecachedrepo self $ext] {
+ puts "cached]"
+ return 1
+ }
+ puts "fetching]"
+ set handle $self(handle)
+ set defvendorid [[$handle cget -meta] lookup_id $solv::SUSETAGS_DEFAULTVENDOR]
+ set descrdir [[$handle cget -meta] lookup_str $solv::SUSETAGS_DESCRDIR]
+ if {$descrdir eq {NULL}} {
+ set descrdir "suse/setup/descr"
+ }
+ set filechecksum [$repodata lookup_checksum $solv::SOLVID_META $solv::SUSETAGS_FILE_CHECKSUM]
+ set f [repo_download self "$descrdir/$filename" 1 $filechecksum]
+ if {$f eq {NULL}} {
+ return 0
+ }
+ set flags [expr $solv::Repo_REPO_USE_LOADING | $solv::Repo_REPO_EXTEND_SOLVABLES]
+ if {$ext ne "DL"} {
+ set flags [expr $flags | $solv::Repo_REPO_LOCALPOOL]
+ }
+ $handle add_susetags $f $defvendorid $ext $flags
+ $f close
+ repo_writecachedrepo self $ext $repodata
+ return 1
+}
+
+### unknown
+
+proc repo_unknown_load {selfName pool} {
+ upvar $selfName self
+ puts "unsupported repo '$self(name)': skipped"
+ return 0
+}
+
+### poor man's OO
+
+proc repo_load {selfName pool} {
+ upvar $selfName self
+ "repo_$self(type)_load" self $pool
+}
+
+proc repo_packagespath {selfName} {
+ upvar $selfName self
+ "repo_$self(type)_packagespath" self
+}
+
+proc repo_load_ext {selfName repodata} {
+ upvar $selfName self
+ "repo_$self(type)_load_ext" self $repodata
+}
+
+###
+
+proc load_stub {repodata} {
+ set code [catch {
+ upvar #0 [[$repodata cget -repo] cget -appdata] repo
+ if [info exists repo(handle)] {
+ return [repo_load_ext repo $repodata]
+ }
+ return 0
+ } res]
+ if {$code == 2} {
+ return $res
+ }
+ puts stderr $res
+ return 0
+}
+
+###
+
+set repoNames {}
+foreach reponame [lsort [glob -nocomplain -directory $reposdir *.repo]] {
+ set ini [::ini::open $reponame r]
+ foreach alias [::ini::sections $ini] {
+ upvar #0 [globalarray] repo
+ array set repo {enabled 0 priority 99 autorefresh 1 type rpm-md metadata_expire 900}
+ array set repo [::ini::get $ini $alias]
+ set repo(name) $alias
+ switch -exact -- $repo(type) {
+ rpm-md { set repo(type) repomd }
+ yast2 { set repo(type) susetags }
+ default { set repo(type) unknown }
+ }
+ lappend repoNames $repo(varName)
+ }
+ ::ini::close $ini
+}
+
+set pool [solv::new_Pool]
+$pool setarch
+$pool set_loadcallback load_stub
+
+upvar #0 [globalarray] sysrepo
+array set sysrepo [list name {@System} type system]
+repo_load sysrepo $pool
+
+foreach repoName $repoNames {
+ upvar 0 $repoName repo
+ if {$repo(enabled)} {
+ repo_load repo $pool
+ }
+}
+
+
+set cmd [lindex $::argv 0]
+set ::argv [lreplace $::argv 0 0]
+
+array set cmdabbrev [ list \
+ in install \
+ rm erase \
+ ls list \
+ ve verify \
+ se search \
+]
+if [info exists cmdabbrev($cmd)] {
+ set cmd $cmdabbrev($cmd)
+}
+
+if {$cmd eq "search"} {
+ set arg [lindex $::argv 0]
+ $pool createwhatprovides
+ set sel [$pool Selection]
+ set di [$pool Dataiterator $solv::SOLVABLE_NAME $arg [ expr $solv::Dataiterator_SEARCH_SUBSTRING | $solv::Dataiterator_SEARCH_NOCASE ]]
+ solv::iter d $di {
+ $sel add_raw $solv::Job_SOLVER_SOLVABLE [$d cget -solvid]
+ }
+ foreach s [$sel solvables] {
+ puts [format { - %s [%s]: %s} [$s str] [[$s cget -repo] cget -name] [$s lookup_str $solv::SOLVABLE_SUMMARY]]
+ }
+ exit
+}
+
+$pool addfileprovides
+$pool createwhatprovides
+
+array set cmdactionmap [ list \
+ install $solv::Job_SOLVER_INSTALL \
+ erase $solv::Job_SOLVER_ERASE \
+ up $solv::Job_SOLVER_UPDATE \
+ dup $solv::Job_SOLVER_DISTUPGRADE \
+ verify $solv::Job_SOLVER_VERIFY \
+ list 0 \
+ info 0 \
+]
+
+set jobs {}
+foreach arg $::argv {
+ set flags [expr $solv::Selection_SELECTION_NAME | $solv::Selection_SELECTION_PROVIDES | $solv::Selection_SELECTION_GLOB | \
+ $solv::Selection_SELECTION_CANON | $solv::Selection_SELECTION_DOTARCH | $solv::Selection_SELECTION_REL ]
+ switch -glob -- $arg {
+ "/*" {
+ set flags [expr $flags | $solv::Selection_SELECTION_FILELIST ]
+ if {$cmd eq "erase"} {
+ set flags [expr $flags | $solv::Selection_SELECTION_INSTALLED_ONLY ]
+ }
+ }
+ }
+ set sel [$pool select $arg $flags]
+ if [$sel isempty] {
+ set sel [$pool select $arg [expr $flags | $solv::Selection_SELECTION_NOCASE]]
+ if {![$sel isempty]} {
+ puts "\[ignoring case for '$arg']"
+ }
+ }
+ if [$sel isempty] {
+ puts "nothing matches '$arg'"
+ exit 1
+ }
+ if {[$sel flags] & $solv::Selection_SELECTION_FILELIST} {
+ puts "\[using file list match for '$arg']"
+ }
+ if {[$sel flags] & $solv::Selection_SELECTION_PROVIDES} {
+ puts "\[using capability match for '$arg']"
+ }
+ lappend jobs {*}[$sel jobs $cmdactionmap($cmd)]
+}
+
+if {$jobs eq {} && ($cmd eq "up" || $cmd eq "dup" || $cmd eq "verify") } {
+ set sel [$pool Selection_all]
+ lappend jobs {*}[$sel jobs $cmdactionmap($cmd)]
+}
+
+if {$jobs eq {}} {
+ puts "no package matched."
+ exit 1
+}
+
+if {$cmd eq "list" || $cmd eq "info"} {
+ foreach job $jobs {
+ foreach s [$job solvables] {
+ if {$cmd eq "info"} {
+ puts [format {Name: %s} [$s str]]
+ puts [format {Repo: %s} [[$s cget -repo] cget -name]]
+ puts [format {Summary: %s} [$s lookup_str $solv::SOLVABLE_SUMMARY]]
+ set str [$s lookup_str $solv::SOLVABLE_URL]
+ if {$str ne {}} {
+ puts [format {Url: %s} $str]
+ }
+ set str [$s lookup_str $solv::SOLVABLE_LICENSE]
+ if {$str ne {}} {
+ puts [format {License %s} $str]
+ }
+ puts [format {Description: %s} [$s lookup_str $solv::SOLVABLE_DESCRIPTION]]
+ puts {}
+ } else {
+ puts [format { - %s [%s]} [$s str] [[$s cget -repo] cget -name]]
+ puts [format { %s} [$s lookup_str $solv::SOLVABLE_SUMMARY]]
+ }
+ }
+ }
+ exit
+}
+
+#$pool set_debuglevel 1
+set solver [$pool Solver]
+$solver set_flag $solv::Solver_SOLVER_FLAG_SPLITPROVIDES 1
+if {$cmd eq "erase"} {
+ $solver set_flag $solv::Solver_SOLVER_FLAG_ALLOW_UNINSTALL 1
+}
+
+set problems [$solver solve $jobs]
+if {$problems ne {}} {
+ set pcnt 1
+ foreach problem $problems {
+ puts [format {Problem %d/%d:} $pcnt [llength $problems]]
+ puts [$problem str]
+ incr pcnt
+ }
+ exit 1
+}
+
+set trans [$solver transaction]
+
+if [$trans isempty] {
+ puts "Nothing to do."
+ exit
+}
+
+puts {}
+puts "Transaction summary:"
+puts {}
+foreach cl [$trans classify [expr $solv::Transaction_SOLVER_TRANSACTION_SHOW_OBSOLETES | $solv::Transaction_SOLVER_TRANSACTION_OBSOLETE_IS_UPGRADE]] {
+ switch -- [$cl cget -type] \
+ $solv::Transaction_SOLVER_TRANSACTION_ERASE {
+ puts [format {%d erased packages:} [$cl cget -count]]
+ } \
+ $solv::Transaction_SOLVER_TRANSACTION_INSTALL {
+ puts [format {%d installed packages:} [$cl cget -count]]
+ } \
+ $solv::Transaction_SOLVER_TRANSACTION_REINSTALLED {
+ puts [format {%d reinstalled packages:} [$cl cget -count]]
+ } \
+ $solv::Transaction_SOLVER_TRANSACTION_DOWNGRADED {
+ puts [format {%d downgraded packages:} [$cl cget -count]]
+ } \
+ $solv::Transaction_SOLVER_TRANSACTION_CHANGED {
+ puts [format {%d changed packages:} [$cl cget -count]]
+ } \
+ $solv::Transaction_SOLVER_TRANSACTION_UPGRADED {
+ puts [format {%d upgraded packages:} [$cl cget -count]]
+ } \
+ $solv::Transaction_SOLVER_TRANSACTION_VENDORCHANGE {
+ puts [format {%d vendor changes from '%s' to '%s':} [$cl cget -count] [$cl cget -fromstr] [$cl cget -tostr]]
+ } \
+ $solv::Transaction_SOLVER_TRANSACTION_ARCHCHANGE {
+ puts [format {%d archchanges from '%s' to '%s':} [$cl cget -count] [$cl cget -fromstr] [$cl cget -tostr]]
+ } \
+ default continue
+ foreach p [$cl solvables] {
+ set cltype [$cl cget -type]
+ if {$cltype == $solv::Transaction_SOLVER_TRANSACTION_UPGRADED || $cltype ==$solv::Transaction_SOLVER_TRANSACTION_DOWNGRADED} {
+ set op [$trans othersolvable $p]
+ puts [format { - %s -> %s} [$p str] [$p str]]
+ } else {
+ puts [format { - %s} [$p str]]
+ }
+ }
+ puts {}
+}
+puts [format {install size change: %d K} [$trans calc_installsizechange]]
+puts {}
+
+while 1 {
+ puts -nonewline "OK to continue (y/n)? "
+ flush stdout
+ set yn [gets stdin]
+ if {$yn eq "y"} {
+ break
+ }
+ if {$yn eq "n" || $yn eq "q"} {
+ exit
+ }
+}
+
+set newpkgs [$trans newsolvables]
+array set newpkgs_f {}
+if {$newpkgs ne {}} {
+ set downloadsize 0
+ foreach p $newpkgs {
+ set downloadsize [expr $downloadsize + [$p lookup_num $solv::SOLVABLE_DOWNLOADSIZE]]
+ }
+ puts [format {Downloading %d packages, %d K} [llength $newpkgs] [expr $downloadsize / 1024]]
+ foreach p $newpkgs {
+ upvar #0 [[$p cget -repo] cget -appdata] repo
+ set location [$p lookup_location]
+ if {$location eq {}} {
+ continue
+ }
+ set location "[repo_packagespath repo][lindex $location 0]"
+ set checksum [$p lookup_checksum $solv::SOLVABLE_CHECKSUM]
+ set f [repo_download repo $location 0 $checksum]
+ set newpkgs_f([$p cget -id]) $f
+ puts -nonewline "."
+ flush stdout
+ }
+ puts {}
+}
+
+puts "Committing transaction:"
+$trans order
+foreach p [$trans steps] {
+ set steptype [$trans steptype $p $solv::Transaction_SOLVER_TRANSACTION_RPM_ONLY]
+ if {$steptype == $solv::Transaction_SOLVER_TRANSACTION_ERASE} {
+ puts "erase [$p str]"
+ regsub {^[0-9]+:} [$p cget -evr] {} nvr
+ set nvr "[$p cget -name]-$nvr.[$p cget -arch]"
+ exec -ignorestderr -- rpm -e --nodeps --nodigest --nosignature $nvr
+ } elseif {$steptype == $solv::Transaction_SOLVER_TRANSACTION_INSTALL || $steptype == $solv::Transaction_SOLVER_TRANSACTION_MULTIINSTALL} {
+ puts "install [$p str]"
+ set f $newpkgs_f([$p cget -id])
+ set mode [expr {$steptype == $solv::Transaction_SOLVER_TRANSACTION_INSTALL ? "-U" : "-i"}]
+ $f cloexec 0
+ exec -ignorestderr -- rpm $mode --force --nodeps --nodigest --nosignature "/dev/fd/[$f fileno]"
+ }
+}