mirror of
https://github.com/openSUSE/libsolv.git
synced 2026-02-05 12:45:46 +01:00
806 lines
22 KiB
Tcl
Executable File
806 lines
22 KiB
Tcl
Executable File
#!/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]
|
|
$repodata extend_to_repo
|
|
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]
|
|
$repodata extend_to_repo
|
|
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 cget -flags] & $solv::Selection_SELECTION_FILELIST} {
|
|
puts "\[using file list match for '$arg']"
|
|
}
|
|
if {[$sel cget -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] [$op 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]"
|
|
}
|
|
}
|