<pre style='margin:0'>
Clemens Lang (neverpanic) pushed a commit to branch master
in repository macports-base.
</pre>
<p><a href="https://github.com/macports/macports-base/commit/4d9e8a125d328aa3ac6b558570891123eaabbb1c">https://github.com/macports/macports-base/commit/4d9e8a125d328aa3ac6b558570891123eaabbb1c</a></p>
<pre style="white-space: pre; background: #F8F8F8"><span style='display:block; white-space:pre;color:#808000;'>commit 4d9e8a125d328aa3ac6b558570891123eaabbb1c
</span>Author: Clemens Lang <neverpanic@gmail.com>
AuthorDate: Wed Jul 24 17:22:26 2024 +0200
<span style='display:block; white-space:pre;color:#404040;'> snapshot: Add JSON export functionality
</span><span style='display:block; white-space:pre;color:#404040;'>
</span><span style='display:block; white-space:pre;color:#404040;'> This will eventually allow users to move to a new machine by running
</span><span style='display:block; white-space:pre;color:#404040;'>
</span><span style='display:block; white-space:pre;color:#404040;'> old> sudo port snapshot
</span><span style='display:block; white-space:pre;color:#404040;'> old> sudo port snapshot --export $ID >snapshot.json
</span><span style='display:block; white-space:pre;color:#404040;'> new> sudo port snapshot --import <snapshot.json
</span><span style='display:block; white-space:pre;color:#404040;'> new> sudo port restore --latest
</span>---
src/macports1.0/snapshot.tcl | 115 ++++++++++++++++++++++++++++++++++++++++++-
src/port/port.tcl | 2 +-
2 files changed, 114 insertions(+), 3 deletions(-)
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/macports1.0/snapshot.tcl b/src/macports1.0/snapshot.tcl
</span><span style='display:block; white-space:pre;color:#808080;'>index f9a1a06fe..4cf1028f9 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/macports1.0/snapshot.tcl
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/macports1.0/snapshot.tcl
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -32,6 +32,7 @@ package provide snapshot 1.0
</span>
package require macports 1.0
package require registry 1.0
<span style='display:block; white-space:pre;background:#e0ffe0;'>+package require json::write
</span>
namespace eval snapshot {
proc print_usage {} {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -40,6 +41,8 @@ namespace eval snapshot {
</span> ui_msg " port snapshot --list"
ui_msg " port snapshot --diff <snapshot-id> \[--all\]"
ui_msg " port snapshot --delete <snapshot-id>"
<span style='display:block; white-space:pre;background:#e0ffe0;'>+ ui_msg " port snapshot --export <snapshot-id> >snapshot.json"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ui_msg " port snapshot --import <snapshot.json"
</span> }
proc main {opts} {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -54,11 +57,11 @@ namespace eval snapshot {
</span> set operation "create"
} else {
set operation ""
<span style='display:block; white-space:pre;background:#ffe0e0;'>- foreach op {list create diff delete} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ foreach op {list create diff delete export import} {
</span> set opname "ports_snapshot_$op"
if {[dict exists $opts $opname]} {
if {$operation ne ""} {
<span style='display:block; white-space:pre;background:#ffe0e0;'>- ui_error "Only one of the --list, --create, --diff, and --delete options can be specified."
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ui_error "Only one of the --list, --create, --diff, --delete, --export, or --import options can be specified."
</span> error "Incorrect usage, see port snapshot --help."
}
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -183,6 +186,16 @@ namespace eval snapshot {
</span> "delete" {
return [delete_snapshot $opts]
}
<span style='display:block; white-space:pre;background:#e0ffe0;'>+ "export" {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if {[catch {set snapshot [registry::snapshot get_by_id [dict get $opts ports_snapshot_export]]} result]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ui_error "Failed to obtain snapshot with ID [dict get $opts ports_snapshot_export]: $result"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return 1
</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;'>+ puts [snapshot2json $snapshot]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ "import" {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span> default {
print_usage
return 1
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -190,6 +203,81 @@ namespace eval snapshot {
</span> }
}
<span style='display:block; white-space:pre;background:#e0ffe0;'>+ proc snapshot2json {snapshot} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # Convert the given snapshot to JSON format and return it
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # The data format is
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # metadata:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # type: string "org.macports/snapshot/v1", denoting the version of this format
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # note: string, the note associated with this snapshot
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # created_at: string, the local date at which the snapshot was created
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # ports:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # list of objects:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # port_name: string, the name of the port
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # requested: int, 1 for ports that are requested, 0 otherwise
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # state: string, "installed" for ports that are active
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # variants: string, list of active variants
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # requested_variants: string, list of variants requested by the user
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # port_files: list of strings, the files installed by this port
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # Args:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # snapshot - The snapshot object to convert to JSON
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # Returns:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # string representation of the snapshot object
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # The conversion can take quite a while because we're querying all
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # files installed by the various ports, so display a progress bar
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set fancy_output [expr {![macports::ui_isset ports_debug] && [info exists macports::ui_options(progress_generic)]}]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if {$fancy_output} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set progress $macports::ui_options(progress_generic)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ proc noop {args} {}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set progress noop
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set counter 0
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set total [llength [$snapshot ports]]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # Add some metadata and a version header that allows us to make
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # backwards-incompatible changes to the output format.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set metadata [json::write object-strings \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ type "org.macports/snapshot/v1" \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ note [$snapshot note] \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ created_at [$snapshot created_at]]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $progress start
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $progress update $counter $total
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # Convert each port into its JSON representation
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set ports [list]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ foreach port [$snapshot ports] {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ incr counter
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ lassign $port port_name requested state variants requested_variants
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set files [snapshot::port_files [$snapshot id] $port_name]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ui_debug "Processing port $counter/$total: $port_name"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ lappend ports [json::write object \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ port_name [json::write string $port_name] \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ requested $requested \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ state [json::write string $state] \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ variants [json::write string $variants] \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ requested_variants [json::write string $requested_variants] \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ port_files [json::write array-strings {*}$files]]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $progress update $counter $total
</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;'>+ # Assemble the metadata and port list into the final JSON object and
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # return it.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set res [json::write object \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ metadata $metadata \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ports [json::write array {*}$ports]]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $progress finish
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return $res
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> proc create {opts} {
registry::write {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -276,6 +364,29 @@ namespace eval snapshot {
</span> return $ret
}
<span style='display:block; white-space:pre;background:#e0ffe0;'>+ proc port_files {snapshot_id port_name} {
</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 port_files_stmt
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if {![info exists port_files_stmt]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set port_files_stmt [$tdbc_connection prepare {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ SELECT snapshot_files.path FROM snapshot_files
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ INNER JOIN snapshot_ports ON snapshot_files.id = snapshot_ports.id
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ WHERE snapshot_ports.port_name = :port_name
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ AND snapshot_ports.snapshots_id = :snapshot_id
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ORDER BY snapshot_files.path ASC
</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;'>+ $tdbc_connection transaction {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set results [$port_files_stmt execute]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set ret [lmap l [$results allrows] {lindex $l 1}]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $results close
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return $ret
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> proc _os_mismatch {iplatform iosmajor} {
global macports::os_platform macports::os_major
if {$iplatform ne "any" && ($iplatform ne $os_platform
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/port/port.tcl b/src/port/port.tcl
</span><span style='display:block; white-space:pre;color:#808080;'>index c66e62ac6..743ec7c56 100755
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/port/port.tcl
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/port/port.tcl
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4237,7 +4237,7 @@ set cmd_opts_array [dict create {*}{
</span> reclaim {enable-reminders disable-reminders}
fetch {no-mirrors}
bump {patch}
<span style='display:block; white-space:pre;background:#ffe0e0;'>- snapshot {create list {diff 1} all {delete 1} help {note 1}}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ snapshot {create list {diff 1} all {delete 1} help {note 1} {export 1} import}
</span> restore {{snapshot-id 1} all last}
migrate {continue all}
}]
</pre><pre style='margin:0'>
</pre>