#!/usr/bin/ruby
-# bool: method?
-# inplace mod: method!
-# set method: method=
-
-# map => collect
-# grep => find_all
-
require 'solv'
require 'rubygems'
require 'inifile'
return @attribs['autorefresh'].to_i != 0
end
+ def id
+ return @handle ? @handle.id : 0
+ end
+
def calc_cookie_fp(f)
chksum = Solv::Chksum.new(Solv::REPOKEY_TYPE_SHA256)
+ chksum.add("1.1")
chksum.add_fp(f)
return chksum.raw
end
return chksum.raw
end
+ def calc_cookie_ext(f, cookie)
+ chksum = Solv::Chksum.new(Solv::REPOKEY_TYPE_SHA256)
+ chksum.add("1.1")
+ chksum.add(cookie)
+ chksum.add_fstat(f.fileno)
+ return chksum.raw()
+ end
+
def cachepath(ext = nil)
path = @name.sub(/^\./, '_')
path += ext ? "_#{ext}.solvx" : '.solv'
dorefresh = autorefresh?
if dorefresh
begin
- s = File.stat(cachepath)
- dorefresh = false if s && Time.now - s.mtime < @attribs['metadata_expire'].to_i
+ s = File.stat(cachepath)
+ dorefresh = false if s && (@attribs['metadata_expire'].to_i == -1 || Time.now - s.mtime < @attribs['metadata_expire'].to_i)
rescue SystemCallError
end
end
@cookie = nil
+ @extcookie = nil
if !dorefresh && usecachedrepo(nil)
puts "repo: '#{@name}' cached"
return true
end
- return load_if_changed()
- end
-
- def load_ext(repodata)
return false
end
- def load_if_changed
+ def load_ext(repodata)
return false
end
return nil if f.stat.size == 0 && (st || !chksum)
if !st
puts "#{file}: download error #{$? >> 8}"
- @incomplete = true if markincomplete
- return nil
+ @incomplete = true if markincomplete
+ return nil
end
if chksum
fchksum = Solv::Chksum.new(chksum.type)
fchksum.add_fd(f.fileno)
- if !fchksum.matches(chksum)
+ if !fchksum == chksum
puts "#{file}: checksum error"
- @incomplete = true if markincomplete
- return nil
+ @incomplete = true if markincomplete
+ return nil
end
end
+ rf = nil
if uncompress
- return Solv::xfopen_dup(file, f.fileno)
+ rf = Solv::xfopen_fd(file, f.fileno)
else
- return Solv::xfopen_dup('', f.fileno)
+ rf = Solv::xfopen_fd('', f.fileno)
end
+ f.close
+ return rf
end
def usecachedrepo(ext, mark = false)
return false if fcookie.length != 32
return false if cookie && fcookie != cookie
if !ext && @type != 'system'
- f.sysseek(-32 * 2, IO::SEEK_END)
- fextcookie = f.sysread(32)
- return false if fextcookie.length != 32
+ f.sysseek(-32 * 2, IO::SEEK_END)
+ fextcookie = f.sysread(32)
+ return false if fextcookie.length != 32
end
f.sysseek(0, IO::SEEK_SET)
- f = Solv::xfopen_dup('', f.fileno)
+ nf = Solv::xfopen_fd('', f.fileno)
+ f.close
flags = ext ? Solv::Repo::REPO_USE_LOADING|Solv::Repo::REPO_EXTEND_SOLVABLES : 0
flags |= Solv::Repo::REPO_LOCALPOOL if ext && ext != 'DL'
- if ! @handle.add_solv(f, flags)
- Solv::xfclose(f)
- return false
+ if ! @handle.add_solv(nf, flags)
+ nf.close
+ return false
end
- Solv::xfclose(f)
+ nf.close()
@cookie = fcookie unless ext
@extcookie = fextcookie if !ext && @type != 'system'
now = Time.now
begin
- File::utime(now, now, repopath) if mark
+ File::utime(now, now, repopath) if mark
rescue SystemCallError
end
return true
return true
end
- def genextcookie(f)
- chksum = Solv::Chksum.new(Solv::REPOKEY_TYPE_SHA256)
- chksum.add(@cookie)
- if f
- s = f.stat()
- chksum.add(s.dev.to_s);
- chksum.add(s.ino.to_s);
- chksum.add(s.size.to_s);
- chksum.add(s.mtime.to_s);
- end
- @extcookie = chksum.raw()
- @extcookie[0] = 1 if @extcookie[0] == 0
- 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_dup('', f.fileno)
- if !info
+ sf = Solv::xfopen_fd('', f.fileno)
+ if !repodata
@handle.write(sf)
elsif ext
- info.write(sf)
+ repodata.write(sf)
else
@handle.write_first_repodata(sf)
end
- Solv::xfclose(sf)
+ sf.close
f.sysseek(0, IO::SEEK_END)
if @type != 'system' && !ext
- genextcookie(f) unless @extcookie
- f.syswrite(@extcookie)
+ @extcookie = calc_cookie_ext(f, @cookie) unless @extcookie
+ f.syswrite(@extcookie)
end
f.syswrite(ext ? @extcookie : @cookie)
- f.close(false)
+ f.close
if @handle.iscontiguous?
sf = Solv::xfopen(f.path)
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()
- info.add_solv(sf, Solv::Repo::REPO_EXTEND_SOLVABLES)
+ repodata.extend_to_repo()
+ flags = Solv::Repo::REPO_EXTEND_SOLVABLES
+ flags |= Solv::Repo::REPO_LOCALPOOL if ext != 'DL'
+ repodata.add_solv(sf, flags)
end
- Solv::xfclose(sf)
+ sf.close
end
end
File.rename(f.path, cachepath(ext))
repodata.internalize()
writecachedrepo(nil, repodata)
end
+
+ 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
def find(what)
- di = @handle.Dataiterator(Solv::SOLVID_META, Solv::REPOSITORY_REPOMD_TYPE, what, Solv::Dataiterator::SEARCH_STRING)
+ di = @handle.Dataiterator_meta(Solv::REPOSITORY_REPOMD_TYPE, what, Solv::Dataiterator::SEARCH_STRING)
di.prepend_keyname(Solv::REPOSITORY_REPOMD)
for d in di
- d.setpos_parent()
- filename = d.pool.lookup_str(Solv::SOLVID_POS, Solv::REPOSITORY_REPOMD_LOCATION)
+ dp = d.parentpos()
+ filename = dp.lookup_str(Solv::REPOSITORY_REPOMD_LOCATION)
next unless filename
- checksum = d.pool.lookup_checksum(Solv::SOLVID_POS, Solv::REPOSITORY_REPOMD_CHECKSUM)
+ checksum = dp.lookup_checksum(Solv::REPOSITORY_REPOMD_CHECKSUM)
if !checksum
puts "no #{filename} checksum!"
return nil, nil
return nil, nil
end
- def load_if_changed
+ def load(pool)
+ return true if super(pool)
print "rpmmd repo '#{@name}: "
f = download("repodata/repomd.xml", false, nil, nil)
if !f
@cookie = calc_cookie_fp(f)
if usecachedrepo(nil, true)
puts "cached"
- Solv.xfclose(f)
+ f.close
return true
end
@handle.add_repomdxml(f, 0)
- Solv::xfclose(f)
+ f.close
puts "fetching"
filename, filechksum = find('primary')
if filename
f = download(filename, true, filechksum, true)
if f
- @handle.add_rpmmd(f, nil, 0)
- Solv::xfclose(f)
+ @handle.add_rpmmd(f, nil, 0)
+ f.close
end
return false if @incomplete
end
if filename
f = download(filename, true, filechksum, true)
if f
- @handle.add_updateinfoxml(f, 0)
- Solv::xfclose(f)
+ @handle.add_updateinfoxml(f, 0)
+ f.close
end
end
add_exts()
- writecachedrepo(nil) unless @incomplete
+ writecachedrepo(nil)
@handle.create_stubs()
return true
end
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
def add_exts
repodata = @handle.add_repodata(0)
+ repodata.extend_to_repo()
add_ext(repodata, 'deltainfo', 'DL')
add_ext(repodata, 'filelists', 'FL')
repodata.internalize()
f = download(filename, true, filechksum)
return false unless f
if ext == 'FL'
- @handle.add_rpmmd(f, 'FL', Solv::Repo::REPO_USE_LOADING|Solv::Repo::REPO_EXTEND_SOLVABLES)
+ @handle.add_rpmmd(f, 'FL', Solv::Repo::REPO_USE_LOADING|Solv::Repo::REPO_EXTEND_SOLVABLES|Solv::Repo::REPO_LOCALPOOL)
elsif ext == 'DL'
@handle.add_deltainfoxml(f, Solv::Repo::REPO_USE_LOADING)
end
- Solv::xfclose(f)
+ f.close
writecachedrepo(ext, repodata)
return true
end
class Repo_susetags < Repo_generic
def find(what)
- di = @handle.Dataiterator(Solv::SOLVID_META, Solv::SUSETAGS_FILE_NAME, what, Solv::Dataiterator::SEARCH_STRING)
+ di = @handle.Dataiterator_meta(Solv::SUSETAGS_FILE_NAME, what, Solv::Dataiterator::SEARCH_STRING)
di.prepend_keyname(Solv::SUSETAGS_FILE)
for d in di
- d.setpos_parent()
- checksum = d.pool.lookup_checksum(Solv::SOLVID_POS, Solv::SUSETAGS_FILE_CHECKSUM)
+ dp = d.parentpos()
+ checksum = dp.lookup_checksum(Solv::SUSETAGS_FILE_CHECKSUM)
return what, checksum
end
return nil, nil
end
- def load_if_changed
+ def load(pool)
+ return true if super(pool)
print "susetags repo '#{@name}: "
f = download("content", false, nil, nil)
if !f
@cookie = calc_cookie_fp(f)
if usecachedrepo(nil, true)
puts "cached"
- Solv.xfclose(f)
+ f.close
return true
end
@handle.add_content(f, 0)
- Solv::xfclose(f)
+ f.close
puts "fetching"
- defvendorid = @handle.lookup_id(Solv::SOLVID_META, Solv::SUSETAGS_DEFAULTVENDOR)
- descrdir = @handle.lookup_str(Solv::SOLVID_META, Solv::SUSETAGS_DESCRDIR)
+ defvendorid = @handle.meta.lookup_id(Solv::SUSETAGS_DEFAULTVENDOR)
+ descrdir = @handle.meta.lookup_str(Solv::SUSETAGS_DESCRDIR)
descrdir = "suse/setup/descr" unless descrdir
(filename, filechksum) = find('packages.gz')
(filename, filechksum) = find('packages') unless filename
if filename
f = download("#{descrdir}/#{filename}", true, filechksum, true)
if f
- @handle.add_susetags(f, defvendorid, nil, Solv::Repo::REPO_NO_INTERNALIZE|Solv::Repo::SUSETAGS_RECORD_SHARES)
- Solv::xfclose(f)
+ @handle.add_susetags(f, defvendorid, nil, Solv::Repo::REPO_NO_INTERNALIZE|Solv::Repo::SUSETAGS_RECORD_SHARES)
+ f.close
(filename, filechksum) = find('packages.en.gz')
(filename, filechksum) = find('packages.en') unless filename
- if filename
- f = download("#{descrdir}/#{filename}", true, filechksum, true)
- if f
- @handle.add_susetags(f, defvendorid, nil, Solv::Repo::REPO_NO_INTERNALIZE|Solv::Repo::REPO_REUSE_REPODATA|Solv::Repo::REPO_EXTEND_SOLVABLES)
- Solv::xfclose(f)
- end
- end
+ if filename
+ f = download("#{descrdir}/#{filename}", true, filechksum, true)
+ if f
+ @handle.add_susetags(f, defvendorid, nil, Solv::Repo::REPO_NO_INTERNALIZE|Solv::Repo::REPO_REUSE_REPODATA|Solv::Repo::REPO_EXTEND_SOLVABLES)
+ f.close
+ end
+ end
@handle.internalize()
end
end
add_exts()
- writecachedrepo(nil) unless @incomplete
+ writecachedrepo(nil)
@handle.create_stubs()
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
def add_exts
repodata = @handle.add_repodata(0)
- di = @handle.Dataiterator(Solv::SOLVID_META, Solv::SUSETAGS_FILE_NAME, nil, 0)
+ di = @handle.Dataiterator_meta(Solv::SUSETAGS_FILE_NAME, nil, 0)
di.prepend_keyname(Solv::SUSETAGS_FILE)
for d in di
- filename = d.match_str
+ filename = d.str
next unless filename && filename =~ /^packages\.(..)(?:\..*)$/
next if $1 == 'en' || $1 == 'gz'
add_ext(repodata, filename, $1)
return true
end
puts "fetching]\n"
- defvendorid = @handle.lookup_id(Solv::SOLVID_META, Solv::SUSETAGS_DEFAULTVENDOR)
- descrdir = @handle.lookup_str(Solv::SOLVID_META, Solv::SUSETAGS_DESCRDIR)
+ defvendorid = @handle.meta.lookup_id(Solv::SUSETAGS_DEFAULTVENDOR)
+ descrdir = @handle.meta.lookup_str(Solv::SUSETAGS_DESCRDIR)
descrdir = "suse/setup/descr" unless descrdir
filechksum = repodata.lookup_checksum(Solv::SOLVID_META, Solv::SUSETAGS_FILE_CHECKSUM)
f = download("#{descrdir}/#{filename}", true, filechksum)
return false unless f
- @handle.add_susetags(f, defvendorid, ext, Solv::Repo::REPO_USE_LOADING|Solv::Repo::REPO_EXTEND_SOLVABLES)
- Solv::xfclose(f)
+ flags = Solv::Repo::REPO_USE_LOADING|Solv::Repo::REPO_EXTEND_SOLVABLES
+ flags |= Solv::Repo::REPO_LOCALPOOL if ext != 'DL'
+ @handle.add_susetags(f, defvendorid, ext, flags)
+ f.close
writecachedrepo(ext, repodata)
return true
end
+ def packagespath()
+ datadir = @handle.meta.lookup_str(Solv::SUSETAGS_DATADIR)
+ datadir = "suse" unless datadir
+ return datadir + '/'
+ end
end
class Repo_unknown < Repo_generic
return true
end
puts "reading"
- @handle.add_products("/etc/products.d", Solv::Repo::REPO_NO_INTERNALIZE)
- @handle.add_rpmdb(nil, Solv::Repo::REPO_REUSE_REPODATA)
+ if @handle.respond_to? :add_products
+ @handle.add_products("/etc/products.d", Solv::Repo::REPO_NO_INTERNALIZE)
+ end
+ f = Solv::xfopen(cachepath())
+ @handle.add_rpmdb_reffp(f, Solv::Repo::REPO_REUSE_REPODATA)
+ f.close if f
writecachedrepo(nil)
return true
end
end
-
-def validarch?(pool, arch)
- return false unless arch && arch != ''
- id = pool.str2id(arch, false)
- return id != 0 && pool.isknownarch?(id)
-end
-
-def depglob(pool, name, globname, globdep)
- id = pool.str2id(name, false)
- if id != 0
- match = false
- providers = pool.providers(id)
- if globname && providers.find {|s| s.nameid == id }
- return [ pool.Job(Solv::Job::SOLVER_SOLVABLE_NAME, id) ]
- end
- if !providers.empty?
- puts "[using capability match for '#{name}']" if globname && globdep
- return [ pool.Job(Solv::Job::SOLVER_SOLVABLE_PROVIDES, id) ]
- end
- end
- return [] unless name =~ /[\[*?]/;
- if globname
- idmatches = {}
- for d in pool.Dataiterator(0, Solv::SOLVABLE_NAME, name, Solv::Dataiterator::SEARCH_GLOB)
- s = d.solvable
- idmatches[s.nameid] = 1 if s.installable?
- end
- if !idmatches.empty?
- return idmatches.keys.sort.collect { |id| pool.Job(Solv::Job::SOLVER_SOLVABLE_NAME, id) }
- end
- end
- if globdep
- idmatches = pool.matchprovidingids(name, Solv::Dataiterator::SEARCH_GLOB);
- if !idmatches.empty?
- puts "[using capability match for '#{name}']"
- return idmatches.sort.collect { |id| pool.Job(Solv::Job::SOLVER_SOLVABLE_PROVIDES, id) }
- end
- end
- return []
-end
-
-def limitjobs(pool, jobs, flags, evrstr)
- njobs = []
- evr = pool.str2id(evrstr)
- for j in jobs
- how = j.how
- sel = how & Solv::Job::SOLVER_SELECTMASK
- what = pool.rel2id(j.what, evr, flags)
- if flags == Solv::REL_ARCH
- how |= Solv::Job::SOLVER_SETARCH
- elsif flags == Solv::REL_EQ && sel == Solv::Job::SOLVER_SOLVABLE_NAME
- how |= evrstr.include?(?-) ? Solv::Job::SOLVER_SETEVR : Solv::Job::SOLVER_SETEV
- end
- njobs << pool.Job(how, what)
- end
- return njobs
-end
-
-def limitjobs_evrarch(pool, jobs, flags, evrstr)
- if evrstr =~ /^(.+)\.(.+?)$/ && validarch?(pool, $2)
- evrstr = $1
- jobs = limitjobs(pool, jobs, Solv::REL_ARCH, $2)
- end
- return limitjobs(pool, jobs, flags, evrstr)
-end
-
-def mkjobs_rel(pool, cmd, name, rel, evr)
- flags = 0
- flags |= Solv::REL_LT if rel.include?(?<)
- flags |= Solv::REL_EQ if rel.include?(?=)
- flags |= Solv::REL_GT if rel.include?(?>)
- jobs = depglob(pool, name, true, true)
- return limitjobs(pool, jobs, flags, evr) unless jobs.empty?
- if (name =~ /^(.+)\.(.+?)$/) && validarch?(pool, $2)
- arch = $2
- jobs = depglob(pool, name, true, true)
- return [] if jobs.empty?
- jobs = limitjobs(pool, jobs, Solv::REL_ARCH, arch)
- return limitjobs(pool, jobs, flags, evr)
- end
- return []
-end
-
-def mkjobs_nevra(pool, cmd, arg)
- jobs = depglob(pool, arg, true, true)
- return jobs unless jobs.empty?
- if ((arg =~ /^(.+)\.(.+?)$/) && validarch?(pool, $2))
- arch = $2
- jobs = depglob(pool, $1, true, true)
- return limitjobs(pool, jobs, Solv::REL_ARCH, arch) unless jobs.empty?
- end
- if (arg =~ /^(.+)-(.+?)$/)
- evr = $2
- jobs = depglob(pool, $1, true, false)
- return limitjobs_evrarch(pool, jobs, Solv::REL_EQ, evr) unless jobs.empty?
- end
- if (arg =~ /^(.+)-(.+?-.+?)$/)
- evr = $2
- jobs = depglob(pool, $1, true, false)
- return limitjobs_evrarch(pool, jobs, Solv::REL_EQ, evr) unless jobs.empty?
- end
- return []
-end
-
-def mkjobs_filelist(pool, cmd, arg)
- type = Solv::Dataiterator::SEARCH_STRING
- type = Solv::Dataiterator::SEARCH_GLOB if arg =~ /[\[*?]/
- if cmd == 'erase'
- di = pool.installed.Dataiterator(0, Solv::SOLVABLE_FILELIST, arg, type | Solv::Dataiterator::SEARCH_FILES|Solv::Dataiterator::SEARCH_COMPLETE_FILELIST)
- else
- di = pool.Dataiterator(0, Solv::SOLVABLE_FILELIST, arg, type | Solv::Dataiterator::SEARCH_FILES|Solv::Dataiterator::SEARCH_COMPLETE_FILELIST)
- end
- matches = []
- for d in di
- s = d.solvable
- next unless s && s.installable?
- matches.push(s.id)
- di.skip_solvable()
- end
- return [] if matches.empty?
- puts "[using file list match for '#{arg}']"
- if matches.length > 1
- return [ pool.Job(Solv::Job::SOLVER_SOLVABLE_ONE_OF, pool.towhatprovides(matches)) ]
- else
- return [ pool.Job(Solv::Job::SOLVER_SOLVABLE | Solv::Job::SOLVER_NOAUTOSET, matches[0]) ]
- end
-end
-
-def mkjobs(pool, cmd, arg)
- if arg =~ /^\//
- jobs = mkjobs_filelist(pool, cmd, arg)
- return jobs unless jobs.empty?
- end
- if (arg =~ /^(.+?)\s*([<=>]+)\s*(.+?)$/)
- return mkjobs_rel(pool, cmd, $1, $2, $3)
- else
- return mkjobs_nevra(pool, cmd, arg)
- end
-end
-
args = ARGV
cmd = args.shift
-cmd = 'list' if cmd == 'li'
-cmd = 'install' if cmd == 'in'
-cmd = 'erase' if cmd == 'rm'
-cmd = 'verify' if cmd == 've'
-cmd = 'search' if cmd == 'se'
+
+cmdabbrev = { 'ls' => 'list', 'in' => 'install', 'rm' => 'erase',
+ 've' => 'verify', 'se' => 'search' }
+cmd = cmdabbrev[cmd] if cmdabbrev.has_key?(cmd)
+
+cmdactionmap = {
+ '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,
+}
repos = []
-for reposdir in [ '/etc/zypp/repos.d' ] do
+reposdirs = []
+if FileTest.directory?('/etc/zypp/repos.d')
+ reposdirs = [ '/etc/zypp/repos.d' ]
+else
+ reposdirs = [ '/etc/yum/repos.d' ]
+end
+for reposdir in reposdirs do
next unless FileTest.directory?(reposdir)
for reponame in Dir["#{reposdir}/*.repo"].sort do
- cfg = IniFile.new(reponame)
+ cfg = IniFile.load(reponame)
cfg.each_section do |ali|
repoattr = { 'alias' => ali, 'enabled' => 0, 'priority' => 99, 'autorefresh' => 1, 'type' => 'rpm-md', 'metadata_expire' => 900}
repoattr.update(cfg[ali])
if repoattr['type'] == 'rpm-md'
- repo = Repo_rpmmd.new(ali, 'repomd', repoattr)
+ repo = Repo_rpmmd.new(ali, 'repomd', repoattr)
elsif repoattr['type'] == 'yast2'
- repo = Repo_susetags.new(ali, 'susetags', repoattr)
+ repo = Repo_susetags.new(ali, 'susetags', repoattr)
else
- repo = Repo_unknown.new(ali, 'unknown', repoattr)
+ repo = Repo_unknown.new(ali, 'unknown', repoattr)
end
repos.push(repo)
end
end
pool = Solv::Pool.new()
-# require 'sys/uname' ; sysarch = Sys::Uname.machine
-sysarch = `uname -p`.strip
-pool.setarch(sysarch)
+pool.setarch()
pool.set_loadcallback { |repodata|
repo = repodata.repo.appdata
end
if cmd == 'search'
- matches = {}
- for di in pool.Dataiterator(0, Solv::SOLVABLE_NAME, args[0], Solv::Dataiterator::SEARCH_SUBSTRING | Solv::Dataiterator::SEARCH_NOCASE)
- matches[di.solvid] = true
+ pool.createwhatprovides()
+ sel = pool.Selection
+ for di in pool.Dataiterator(Solv::SOLVABLE_NAME, args[0], Solv::Dataiterator::SEARCH_SUBSTRING | Solv::Dataiterator::SEARCH_NOCASE)
+ sel.add_raw(Solv::Job::SOLVER_SOLVABLE, di.solvid)
end
- for solvid in matches.keys.sort
- s = pool.solvables[solvid]
- puts "- #{s.str} [#{s.repo.name}]"
+ for s in sel.solvables
+ puts "- #{s.str} [#{s.repo.name}]: #{s.lookup_str(Solv::SOLVABLE_SUMMARY)}"
end
exit
end
-addedprovides = pool.addfileprovides_ids()
+abort("unknown command '#{cmd}'\n") unless cmdactionmap.has_key?(cmd)
+
+addedprovides = pool.addfileprovides_queue()
if !addedprovides.empty?
sysrepo.updateaddedprovides(addedprovides)
for repo in repos
jobs = []
for arg in args
- njobs = mkjobs(pool, cmd, ARGV[0])
- abort("nothing matches '#{arg}'") if njobs.empty?
- jobs += njobs
+ flags = Solv::Selection::SELECTION_NAME | Solv::Selection::SELECTION_PROVIDES | Solv::Selection::SELECTION_GLOB
+ flags |= Solv::Selection::SELECTION_CANON | Solv::Selection::SELECTION_DOTARCH | Solv::Selection::SELECTION_REL
+ if arg =~ /^\//
+ flags |= Solv::Selection::SELECTION_FILELIST
+ flags |= Solv::Selection::SELECTION_INSTALLED_ONLY if cmd == 'erase'
+ end
+ sel = pool.select(arg, flags)
+ if sel.isempty?
+ sel = pool.select(arg, flags | Solv::Selection::SELECTION_NOCASE)
+ puts "[ignoring case for '#{arg}']" unless sel.isempty?
+ end
+ puts "[using file list match for '#{arg}']" if sel.flags & Solv::Selection::SELECTION_FILELIST != 0
+ puts "[using capability match for '#{arg}']" if sel.flags & Solv::Selection::SELECTION_PROVIDES != 0
+ jobs += sel.jobs(cmdactionmap[cmd])
+end
+
+if jobs.empty? && (cmd == 'up' || cmd == 'dup' || cmd == 'verify')
+ sel = pool.Selection_all()
+ jobs += sel.jobs(cmdactionmap[cmd])
end
+abort("no package matched.") if jobs.empty?
+
if cmd == 'list' || cmd == 'info'
- abort("no package matched.") if jobs.empty?
- for job in jobs
- for s in job.solvables()
- if cmd == 'info'
- puts "Name: #{s.str}"
- puts "Repo: #{s.repo.name}"
- puts "Summary: #{s.lookup_str(Solv::SOLVABLE_SUMMARY)}"
- str = s.lookup_str(Solv::SOLVABLE_URL)
- puts "Url: #{str}" if str
- str = s.lookup_str(Solv::SOLVABLE_LICENSE)
- puts "License: #{str}" if str
- puts "Description:\n#{s.lookup_str(Solv::SOLVABLE_DESCRIPTION)}"
- puts
- else
- puts " - #{s.str} [#{s.repo.name}]"
- puts " #{s.lookup_str(Solv::SOLVABLE_SUMMARY)}"
- end
+ for job in jobs
+ for s in job.solvables()
+ if cmd == 'info'
+ puts "Name: #{s.str}"
+ puts "Repo: #{s.repo.name}"
+ puts "Summary: #{s.lookup_str(Solv::SOLVABLE_SUMMARY)}"
+ str = s.lookup_str(Solv::SOLVABLE_URL)
+ puts "Url: #{str}" if str
+ str = s.lookup_str(Solv::SOLVABLE_LICENSE)
+ puts "License: #{str}" if str
+ puts "Description:\n#{s.lookup_str(Solv::SOLVABLE_DESCRIPTION)}"
+ puts
+ else
+ puts " - #{s.str} [#{s.repo.name}]"
+ puts " #{s.lookup_str(Solv::SOLVABLE_SUMMARY)}"
end
end
+ end
exit
end
-if cmd == 'install' || cmd == 'erase' || cmd == 'up' || cmd == 'dup' || cmd == 'verify'
- if jobs.empty?
- if cmd == 'up' || cmd == 'verify'
- jobs = [ pool.Job(Solv::Job::SOLVER_SOLVABLE_ALL, 0) ]
- elsif cmd != 'dup'
- abort("no package matched.")
- end
- end
- for job in jobs
- if cmd == 'up'
- if job.how == Solv::Job::SOLVER_SOLVABLE_ALL || job.solvables.any? {|s| s.isinstalled?}
- job.how |= Solv::Job::SOLVER_UPDATE
- else
- job.how |= Solv::Job::SOLVER_INSTALL
- end
- elsif cmd == 'install'
- job.how |= Solv::Job::SOLVER_INSTALL
- elsif cmd == 'erase'
- job.how |= Solv::Job::SOLVER_ERASE
- elsif cmd == 'dup'
- job.how |= Solv::Job::SOLVER_DISTUPGRADE
- elsif cmd == 'verify'
- job.how |= Solv::Job::SOLVER_VERIFY
- end
- end
-
- solver = nil
- #pool.set_debuglevel(1)
- while true
- solver = pool.Solver
- solver.ignorealreadyrecommended = true
- solver.allowuninstall = true if cmd == 'erase'
- if cmd == 'dup' && jobs.empty?
- solver.distupgrade = true
- solver.updatesystem = true
- solver.allowdowngrade = true
- solver.allowvendorchange = true
- solver.allowarchchange = true
- solver.dosplitprovides = true
- elsif cmd == 'up' && jobs.length == 1 && jobs[0].how == (Solv::Job::SOLVER_UPDATE | Solv::Job::SOLVER_SOLVABLE_ALL)
- solver.dosplitprovides = true
- end
- problems = solver.solve(jobs)
- break if problems.empty?
- for problem in problems
- puts "Problem #{problem.id}:"
- puts problem.findproblemrule.info.problemstr
- solutions = problem.solutions
- for solution in solutions
- puts " Solution #{solution.id}:"
- elements = solution.elements(true)
- for element in elements
- puts " - #{element.str}"
- end
+for job in jobs
+ job.how ^= Solv::Job::SOLVER_UPDATE ^ Solv::Job::SOLVER_INSTALL if cmd == 'up' and job.isemptyupdate?
+end
+
+solver = pool.Solver
+solver.set_flag(Solv::Solver::SOLVER_FLAG_SPLITPROVIDES, 1)
+solver.set_flag(Solv::Solver::SOLVER_FLAG_ALLOW_UNINSTALL, 1) if cmd == 'erase'
+#pool.set_debuglevel(1)
+
+while true
+ problems = solver.solve(jobs)
+ break if problems.empty?
+ for problem in problems
+ puts "Problem #{problem.id}/#{problems.count}:"
+ puts problem
+ solutions = problem.solutions
+ for solution in solutions
+ puts " Solution #{solution.id}:"
+ elements = solution.elements(true)
+ for element in elements
+ puts " - #{element.str}"
end
- exit
- end
- end
- trans = solver.transaction
- solver = nil
- if trans.isempty?
- puts "Nothing to do."
- exit
- end
- puts "\nTransaction summary:\n"
- for cl in trans.classify()
- if cl.type == Solv::Transaction::SOLVER_TRANSACTION_ERASE
- puts "#{cl.count} erased packages:"
- elsif cl.type == Solv::Transaction::SOLVER_TRANSACTION_INSTALL
- puts "#{cl.count} installed packages:"
- elsif cl.type == Solv::Transaction::SOLVER_TRANSACTION_REINSTALLED
- puts "#{cl.count} reinstalled packages:"
- elsif cl.type == Solv::Transaction::SOLVER_TRANSACTION_DOWNGRADED
- puts "#{cl.count} downgraded packages:"
- elsif cl.type == Solv::Transaction::SOLVER_TRANSACTION_CHANGED
- puts "#{cl.count} changed packages:"
- elsif cl.type == Solv::Transaction::SOLVER_TRANSACTION_UPGRADED
- puts "#{cl.count} upgraded packages:"
- elsif cl.type == Solv::Transaction::SOLVER_TRANSACTION_VENDORCHANGE
- puts "#{cl.count} vendor changes from '#{pool.id2str(cl.fromid)}' to '#{pool.id2str(cl.toid)}':"
- elsif cl.type == Solv::Transaction::SOLVER_TRANSACTION_ARCHCHANGE
- puts "#{cl.count} arch changes from '#{pool.id2str(cl.fromid)}' to '#{pool.id2str(cl.toid)}':"
- else
- next
- end
- for p in cl.solvables
- if cl.type == Solv::Transaction::SOLVER_TRANSACTION_UPGRADED || cl.type == Solv::Transaction::SOLVER_TRANSACTION_DOWNGRADED
- puts " - #{p.str} -> #{trans.othersolvable(p).str}"
+ puts
+ end
+ sol = nil
+ while true
+ print "Please choose a solution: "
+ STDOUT.flush
+ sol = STDIN.gets.strip
+ break if sol == 's' || sol == 'q'
+ break if sol =~ /^\d+$/ && sol.to_i >= 1 && sol.to_i <= solutions.length
+ end
+ next if sol == 's'
+ abort if sol == 'q'
+ solution = solutions[sol.to_i - 1]
+ for element in solution.elements
+ newjob = element.Job()
+ if element.type == Solv::Solver::SOLVER_SOLUTION_JOB
+ jobs[element.jobidx] = newjob
else
- puts " - #{p.str}"
+ jobs.push(newjob) if newjob && !jobs.include?(newjob)
end
end
- puts
end
- puts "install size change: #{trans.calc_installsizechange()} K\n\n"
+end
+
+trans = solver.transaction
+solver = nil
+if trans.isempty?
+ puts "Nothing to do."
+ exit
+end
+
+puts "\nTransaction summary:\n"
+for cl in trans.classify(Solv::Transaction::SOLVER_TRANSACTION_SHOW_OBSOLETES | Solv::Transaction::SOLVER_TRANSACTION_OBSOLETE_IS_UPGRADE)
+ if cl.type == Solv::Transaction::SOLVER_TRANSACTION_ERASE
+ puts "#{cl.count} erased packages:"
+ elsif cl.type == Solv::Transaction::SOLVER_TRANSACTION_INSTALL
+ puts "#{cl.count} installed packages:"
+ elsif cl.type == Solv::Transaction::SOLVER_TRANSACTION_REINSTALLED
+ puts "#{cl.count} reinstalled packages:"
+ elsif cl.type == Solv::Transaction::SOLVER_TRANSACTION_DOWNGRADED
+ puts "#{cl.count} downgraded packages:"
+ elsif cl.type == Solv::Transaction::SOLVER_TRANSACTION_CHANGED
+ puts "#{cl.count} changed packages:"
+ elsif cl.type == Solv::Transaction::SOLVER_TRANSACTION_UPGRADED
+ puts "#{cl.count} upgraded packages:"
+ elsif cl.type == Solv::Transaction::SOLVER_TRANSACTION_VENDORCHANGE
+ puts "#{cl.count} vendor changes from '#{cl.fromstr}' to '#{cl.tostr}':"
+ elsif cl.type == Solv::Transaction::SOLVER_TRANSACTION_ARCHCHANGE
+ puts "#{cl.count} arch changes from '#{cl.fromstr}' to '#{cl.tostr}':"
+ else
+ next
+ end
+ for p in cl.solvables
+ if cl.type == Solv::Transaction::SOLVER_TRANSACTION_UPGRADED || cl.type == Solv::Transaction::SOLVER_TRANSACTION_DOWNGRADED
+ puts " - #{p.str} -> #{trans.othersolvable(p).str}"
+ else
+ puts " - #{p.str}"
+ end
+ end
+ puts
+end
+puts "install size change: #{trans.calc_installsizechange()} K\n\n"
+
+while true
+ print("OK to continue (y/n)? ")
+ STDOUT.flush
+ yn = STDIN.gets.strip
+ break if yn == 'y'
+ abort if yn == 'n' || yn == 'q'
+end
+
+newpkgs = trans.newsolvables()
+newpkgsfp = {}
+if !newpkgs.empty?
+ downloadsize = 0
+ for p in newpkgs
+ downloadsize += p.lookup_num(Solv::SOLVABLE_DOWNLOADSIZE)
+ end
+ puts "Downloading #{newpkgs.length} packages, #{downloadsize / 1024} K"
+ for p in newpkgs
+ repo = p.repo.appdata
+ location, medianr = p.lookup_location()
+ next unless location
+ location = repo.packagespath + location
+ chksum = p.lookup_checksum(Solv::SOLVABLE_CHECKSUM)
+ f = repo.download(location, false, chksum)
+ abort("\n#{@name}: #{location} not found in repository\n") unless f
+ newpkgsfp[p.id] = f
+ print "."
+ STDOUT.flush()
+ end
+ puts
+end
+
+puts "Committing transaction:"
+puts
+trans.order()
+for p in trans.steps
+ steptype = trans.steptype(p, Solv::Transaction::SOLVER_TRANSACTION_RPM_ONLY)
+ if steptype == Solv::Transaction::SOLVER_TRANSACTION_ERASE
+ puts "erase #{p.str}"
+ next unless p.lookup_num(Solv::RPM_RPMDBID)
+ evr = p.evr.sub(/^[0-9]+:/, '')
+ system('rpm', '-e', '--nodeps', '--nodigest', '--nosignature', "#{p.name}-#{evr}.#{p.arch}") || abort("rpm failed: #{$? >> 8}")
+ elsif (steptype == Solv::Transaction::SOLVER_TRANSACTION_INSTALL || steptype == Solv::Transaction::SOLVER_TRANSACTION_MULTIINSTALL)
+ puts "install #{p.str}"
+ 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
end