#!/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]"
}
}