<pre style='margin:0'>
Joshua Root (jmroot) pushed a commit to branch release-2.10
in repository macports-base.
</pre>
<p><a href="https://github.com/macports/macports-base/commit/ad5b94d4c1efd39aeb97992c781c5d9692ba1e92">https://github.com/macports/macports-base/commit/ad5b94d4c1efd39aeb97992c781c5d9692ba1e92</a></p>
<pre style="white-space: pre; background: #F8F8F8"><span style='display:block; white-space:pre;color:#808000;'>commit ad5b94d4c1efd39aeb97992c781c5d9692ba1e92
</span>Author: Joshua Root <jmr@macports.org>
AuthorDate: Mon Aug 12 12:28:07 2024 +1000
<span style='display:block; white-space:pre;color:#404040;'> _activate_contents: find all conflicts in one query
</span><span style='display:block; white-space:pre;color:#404040;'>
</span><span style='display:block; white-space:pre;color:#404040;'> (cherry picked from commit ef2bc782b789f94e07537ff59cd078763eeb4dfa)
</span>---
src/registry2.0/portimage.tcl | 159 ++++++++++++++++++++++++++++++------------
1 file changed, 116 insertions(+), 43 deletions(-)
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/registry2.0/portimage.tcl b/src/registry2.0/portimage.tcl
</span><span style='display:block; white-space:pre;color:#808080;'>index 1da893500..66da39c49 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/registry2.0/portimage.tcl
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/registry2.0/portimage.tcl
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -634,6 +634,57 @@ proc _progress {args} {
</span> ui_progress_generic {*}${args}
}
<span style='display:block; white-space:pre;background:#e0ffe0;'>+proc _get_port_conflicts {port} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ global registry::tdbc_connection
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if {![info exists tdbc_connection]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ registry::tdbc_connect
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ variable conflicts_stmt
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if {![info exists conflicts_stmt]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set query {SELECT files.id, files.path, files.actual_path FROM
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ (SELECT path FROM files where id = :thisport_id)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ AS thisport_files
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ INNER JOIN files ON thisport_files.path = files.actual_path
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ WHERE files.active = 1}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set conflicts_stmt [$tdbc_connection prepare $query]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set thisport_id [$port id]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $tdbc_connection transaction {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set results [$conflicts_stmt execute]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set id_to_port [dict create]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set path_to_port [dict create]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set port_to_paths [dict create]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set is_replaced [dict create]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set todeactivate [dict create]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set thisport_name [$port name]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ foreach result [$results allrows] {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set id [dict get $result id]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if {![dict exists $id_to_port $id]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ dict set id_to_port $id [lindex [registry::entry search id $id] 0]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set conflicting_port [dict get $id_to_port $id]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if {![dict exists $is_replaced $conflicting_port]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ lassign [mportlookup [$conflicting_port name]] _ portinfo
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if {[dict exists $portinfo replaced_by] && [lsearch -exact -nocase [dict get $portinfo replaced_by] $thisport_name] != -1} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ dict set is_replaced $conflicting_port 1
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ dict set todeactivate $conflicting_port 1
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ dict set is_replaced $conflicting_port 0
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set actual_path [dict get $result actual_path]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ dict set path_to_port $actual_path $conflicting_port
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if {![dict get $is_replaced $conflicting_port]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set imagepath [dict get $result path]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ dict lappend port_to_paths $conflicting_port [list $imagepath $actual_path]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $results close
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return [list $path_to_port $port_to_paths $todeactivate]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> ## Activates the contents of a port
proc _activate_contents {port {rename_list {}}} {
variable force
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -679,7 +730,7 @@ proc _activate_contents {port {rename_list {}}} {
</span> # Last, if the file exists, and belongs to another port, and force is set
# we remove the file from the file_map, take ownership of it, and
# clobber it
<span style='display:block; white-space:pre;background:#ffe0e0;'>- set todeactivate [list]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set todeactivate [dict create]
</span> try {
registry::write {
foreach file $imagefiles {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -694,51 +745,73 @@ proc _activate_contents {port {rename_list {}}} {
</span> throw registry::image-error "Image error: Source file $srcfile does not appear to exist. Unable to activate port ${portname}."
}
<span style='display:block; white-space:pre;background:#ffe0e0;'>- set owner [registry::entry owner $file]
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if {$owner ne {} && $owner ne $port} {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- # deactivate conflicting port if it is replaced_by this one
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- set result [mportlookup [$owner name]]
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- set portinfo [lindex $result 1]
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if {[dict exists $portinfo replaced_by] && [lsearch -exact -nocase [dict get $portinfo replaced_by] $portname] != -1} {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- # we'll deactivate the owner later, but before activating our files
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- lappend todeactivate $owner
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- set owner "replaced"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if {$owner ne "replaced"} {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if {$force} {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- # if we're forcing the activation, then we move any existing
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- # files to a backup file, both in the filesystem and in the
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- # registry
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if { ![catch {::file type $file}] } {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- set bakfile "${file}${baksuffix}"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- _progress intermission
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- ui_warn "File $file already exists. Moving to: $bakfile."
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- ::file rename -force -- $file $bakfile
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- lappend backups $file
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if { $owner ne {} } {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- $owner deactivate [list $file]
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- $owner activate [list $file] [list "${file}${baksuffix}"]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if {![catch {::file type $file}]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if {![info exists conflicts_path_to_port]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # Check for conflicting ports. 'todeactivate' contains ports replaced by this one,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # which we'll deactivate later, but before activating our files.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ lassign [_get_port_conflicts $port] conflicts_path_to_port conflicts_port_to_paths todeactivate
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if {!$force && [dict size $conflicts_port_to_paths] > 0} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set msg "The following ports have active files that conflict with ${portname}'s:\n"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ foreach conflicting_port [dict keys $conflicts_port_to_paths] {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ append msg "[$conflicting_port name] @[$conflicting_port version]_[$conflicting_port revision][$conflicting_port variants]\n"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set conflicting_paths [dict get $conflicts_port_to_paths $conflicting_port]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set pathcounter 0
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set pathtotal [llength $conflicting_paths]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ foreach {_ actual_path} $conflicting_paths {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if {$pathcounter >= 3 && $pathtotal > 4} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ append msg " (... [expr {$pathtotal - $pathcounter}] more not shown)\n"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ break
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ append msg " ${actual_path}\n"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ incr pathcounter
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ append msg "Image error: Conflicting file(s) present. Please deactivate the conflicting port(s) first, or use 'port -f activate $portname' to force the activation."
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ throw registry::image-error $msg
</span> }
<span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if {[dict exists $conflicts_path_to_port $file]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set owner [dict get $conflicts_path_to_port $file]
</span> } else {
<span style='display:block; white-space:pre;background:#ffe0e0;'>- # if we're not forcing the activation, then we bail out if
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- # we find any files that already exist, or have entries in
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- # the registry
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if { $owner ne {} && $owner ne $port } {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- set msg "Image error: $file is being used by the active [$owner name] port. Please deactivate this port first, or use 'port -f activate $portname' to force the activation."
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- #registry::entry close $owner
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- throw registry::image-error $msg
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- } elseif { $owner eq {} && ![catch {::file type $file}] } {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set owner {}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if {$owner eq {} || ![dict exists $todeactivate $owner]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if {$force} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # if we're forcing the activation, then we move any existing
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # files to a backup file, both in the filesystem and in the
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # registry
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if {$owner ne {}} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # Rename all conflicting files for this owner.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set owner_paths [list]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set owner_actual_paths [list]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ foreach {path actual_path} [dict get $conflicts_port_to_paths $owner] {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ lappend owner_deactivate_paths $path
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if {![catch {::file type $actual_path}]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ lappend owner_activate_paths $path
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set bakfile ${actual_path}${baksuffix}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ lappend owner_backup_paths $bakfile
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ui_warn "File $actual_path already exists. Moving to: $bakfile."
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ::file rename -force -- $actual_path $bakfile
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ lappend backups $actual_path
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $owner deactivate $owner_deactivate_paths
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $owner activate $owner_activate_paths $owner_backup_paths
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # Just rename this file.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set bakfile ${file}${baksuffix}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ _progress intermission
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ui_warn "File $file already exists. Moving to: $bakfile."
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ::file rename -force -- $file $bakfile
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ lappend backups $file
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # if we're not forcing the activation, then we bail out if
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # we find any files that already exist
</span> set msg "Image error: $file already exists and does not belong to a registered port. Unable to activate port ${portname}. Use 'port -f activate $portname' to force the activation."
throw registry::image-error $msg
}
}
<span style='display:block; white-space:pre;background:#ffe0e0;'>- #if {$owner ne {}} {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- # registry::entry close $owner
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- #}
</span> }
# Split out the filename's subpaths and add them to the
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -775,7 +848,7 @@ proc _activate_contents {port {rename_list {}}} {
</span>
# deactivate ports replaced_by this one
set deactivate_options [dict create ports_nodepcheck 1]
<span style='display:block; white-space:pre;background:#ffe0e0;'>- foreach owner $todeactivate {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ foreach owner [dict keys $todeactivate] {
</span> _progress intermission
if {$noexec || ![registry::run_target $owner deactivate $deactivate_options]} {
deactivate [$owner name] "" "" 0 $deactivate_options
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -860,7 +933,7 @@ proc _activate_contents {port {rename_list {}}} {
</span> ::file rename -force -- "${file}${baksuffix}" $file
}
# reactivate deactivated ports
<span style='display:block; white-space:pre;background:#ffe0e0;'>- foreach entry $todeactivate {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ foreach entry [dict keys $todeactivate] {
</span> if {[$entry state] eq "imaged" && ($noexec || ![registry::run_target $entry activate ""])} {
activate [$entry name] [$entry version] [$entry revision] [$entry variants] [dict create ports_activate_no-exec $noexec]
}
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -873,7 +946,7 @@ proc _activate_contents {port {rename_list {}}} {
</span>
throw [dict get $eOptions -errorcode] [dict get $eOptions -errorinfo]
} finally {
<span style='display:block; white-space:pre;background:#ffe0e0;'>- #foreach entry $todeactivate {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #foreach entry [dict keys $todeactivate] {
</span> # registry::entry close $entry
#}
# Only delete extracted dir if there is an archive to re-extract from
</pre><pre style='margin:0'>
</pre>