<pre style='margin:0'>
Clemens Lang (neverpanic) pushed a commit to branch gsoc17-migrate
in repository macports-base.

</pre>
<p><a href="https://github.com/macports/macports-base/commit/eff80e5b206fcde49d63bcad4dd7c2b3065c5b17">https://github.com/macports/macports-base/commit/eff80e5b206fcde49d63bcad4dd7c2b3065c5b17</a></p>
<pre style="white-space: pre; background: #F8F8F8"><span style='display:block; white-space:pre;color:#808000;'>commit eff80e5b206fcde49d63bcad4dd7c2b3065c5b17
</span>Author: Umesh Singla <umeshksingla@macports.org>
AuthorDate: Fri Oct 6 21:41:52 2017 +0530

<span style='display:block; white-space:pre;color:#404040;'>    Add --last option to restore action
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    Since migrate upgrades the port command, it can't be used to
</span><span style='display:block; white-space:pre;color:#404040;'>    continue restoring the state which needs the newly installed
</span><span style='display:block; white-space:pre;color:#404040;'>    port command. Thus, broken into two stages asking the user to
</span><span style='display:block; white-space:pre;color:#404040;'>    run `port restore --last` immediately after migrate.
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    Also, add option to select a snapshot interactively on running
</span><span style='display:block; white-space:pre;color:#404040;'>    `port restore` which deactivates the currently active ports and
</span><span style='display:block; white-space:pre;color:#404040;'>    installs/activates the ports from selected snapshot.
</span>---
 src/cregistry/snapshot.c    |  6 +++---
 src/cregistry/snapshot.h    |  2 +-
 src/macports1.0/migrate.tcl | 16 +++++++-------
 src/macports1.0/restore.tcl | 51 ++++++++++++++++++++++++++++++++-------------
 src/port/port.tcl           |  8 +++++--
 src/registry2.0/snapshot.c  | 37 +++++++++++++++++++++++++++++++-
 6 files changed, 90 insertions(+), 30 deletions(-)

<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/cregistry/snapshot.c b/src/cregistry/snapshot.c
</span><span style='display:block; white-space:pre;color:#808080;'>index 79877a8..3f2ec03 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/cregistry/snapshot.c
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/cregistry/snapshot.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -157,7 +157,7 @@ reg_snapshot* reg_snapshot_open(reg_registry* reg, sqlite_int64 id, reg_error* e
</span> }
 
 /**
<span style='display:block; white-space:pre;background:#ffe0e0;'>- * Lists all the existing snapshots in the registry for the user to choose
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Lists the existing snapshots in the registry for the user to choose
</span>  * from, for restore action
  *
  * @param [in] reg         registry to search in
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -165,9 +165,9 @@ reg_snapshot* reg_snapshot_open(reg_registry* reg, sqlite_int64 id, reg_error* e
</span>  * @param [out] errPtr     on error, a description of the error that occurred
  * @return                 the number of snapshots if success; false if failure
  */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-int reg_snapshot_list(reg_registry* reg, reg_snapshot*** snapshots, reg_error* errPtr) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+int reg_snapshot_list(reg_registry* reg, reg_snapshot*** snapshots, int limit, reg_error* errPtr) {
</span>     // Currently limiting to last 10 snapshots in the registry
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    int lower_bound = 10;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    int lower_bound = limit;
</span>     char* query;
     int result;
     query = sqlite3_mprintf("SELECT id FROM registry.snapshots ORDER BY id DESC LIMIT %d",
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/cregistry/snapshot.h b/src/cregistry/snapshot.h
</span><span style='display:block; white-space:pre;color:#808080;'>index 498e5f4..e2c6d88 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/cregistry/snapshot.h
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/cregistry/snapshot.h
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -69,7 +69,7 @@ reg_snapshot* reg_snapshot_open(reg_registry* reg, sqlite_int64 id,
</span>         reg_error* errPtr);
 // list all snapshots
 int reg_snapshot_list(reg_registry* reg, reg_snapshot*** snapshots,
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        reg_error* errPtr);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        int limit, reg_error* errPtr);
</span> // create snapshot method
 reg_snapshot* reg_snapshot_create(reg_registry* reg, char* note,
         reg_error* errPtr);
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/macports1.0/migrate.tcl b/src/macports1.0/migrate.tcl
</span><span style='display:block; white-space:pre;color:#808080;'>index 9eeab84..d878704 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/macports1.0/migrate.tcl
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/macports1.0/migrate.tcl
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -53,7 +53,7 @@ namespace eval migrate {
</span>         set id [$snapshot id]
         set note [$snapshot note]
         set datetime [$snapshot created_at]
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        ui_msg "Done: Snapshot '$id':'$note' created at $datetime"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        ui_msg "Done: Snapshot '$id' : '$note' created at $datetime"
</span> 
         if {[info exists macports::ui_options(questions_yesno)]} {
             set msg "Migration will first uninstall all the installed ports, upgrade MacPorts and then reinstall them again."
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -69,15 +69,13 @@ namespace eval migrate {
</span>         uninstall_installed
 
         ui_msg "Upgrading MacPorts..."
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        upgrade_port_command
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        ui_msg "Fetching ports to install..."
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        set snapshot_portlist [$snapshot ports]
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        ui_msg "Restoring the original state..."
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        restore::restore_state $snapshot_portlist
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {[catch {upgrade_port_command} result]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            ui_debug $::errorInfo
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            ui_msg "Upgrading port command failed. Try running 'sudo port -v selfupdate' and then, 'sudo port restore --last'"
</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:#ffe0e0;'>-        # TODO: CLEAN PARTIAL BUILDS STEP HERE
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        ui_msg "You need to run 'port restore --last' to complete the migration."
</span>         return 0
     }
 
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/macports1.0/restore.tcl b/src/macports1.0/restore.tcl
</span><span style='display:block; white-space:pre;color:#808080;'>index ad63b49..89a2bd9 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/macports1.0/restore.tcl
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/macports1.0/restore.tcl
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -36,33 +36,52 @@ package require snapshot 1.0
</span> 
 namespace eval restore {
     proc main {opts} {
<span style='display:block; white-space:pre;background:#e0ffe0;'>+        # The main function. If the action is provided a snapshot id, then it deactivates
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        # all the current ports and restores the specified snapshot.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        #
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        # If '--last', then it assumes that this is a continution step of migration and
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        # no need of deactivating, since no ports exist. It simply sorts and installs the
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        # last snapshot ports
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        #
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        # If none, then it lists the last k (or all) snapshots with id for the user to
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        # choose from. Deactivates and installs the selected snapshot.
</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;'>+        #           opts - options array.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        # Returns:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        #           0 if success
</span> 
         array set options $opts
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        if ([info exists options(ports_restore_snapshot-id)]) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            # use that snapshot
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {[info exists options(ports_restore_snapshot-id)]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            # use the specified snapshot
</span>             set snapshot [fetch_snapshot $options(ports_restore_snapshot-id)]
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            puts $snapshot
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            puts [$snapshot id]
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            puts [$snapshot note]
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            puts [$snapshot created_at]
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            puts [$snapshot ports]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            ui_msg "Deactivating all ports installed.."
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            deactivate_all
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        } elseif {[info exists options(ports_restore_last)]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            set snapshot [fetch_snapshot_last]
</span>         } else {
             set list [list_snapshots]
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            foreach l $list {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                puts "[$l id] : [$l note] [$l created_at]"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            set retstring [$macports::ui_options(questions_singlechoice) "Select any one snapshot to restore:" "" $list]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            set snapshot [lindex $list $retstring]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            ui_msg "Deactivating all ports installed.."
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            deactivate_all
</span>         }
 
         if {![check_port_command]} {
             return -code error "OS platform mismatch"
         }
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        ui_msg ":: Deactivating all ports installed.."
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        deactivate_all
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        ui_msg "Restoring snapshot '[$snapshot note]' 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;'>+        ui_msg "Fetching ports to install..."
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        set snapshot_portlist [$snapshot ports]
</span> 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        ui_msg ":: Restoring the selected snapshot.."
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        ui_msg "Restoring the selected snapshot.."
</span>         restore_state [$snapshot ports]
<span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return 0
</span>     }
 
     proc check_port_command {} {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -72,7 +91,7 @@ namespace eval restore {
</span>         set os_major [lindex [split $os_version .] 0]
         set os_platform [string tolower $tcl_platform(os)]
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        # Check that the current pla tform is the one we were configured for, otherwise need to do migration
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        # Check that the current platform is the one we were configured for, otherwise need to do migration
</span>         if {($os_platform ne $macports::autoconf::os_platform) || ($os_major != $macports::autoconf::os_major)} {
             ui_error "Current platform \"$os_platform $os_major\" does not match expected platform \"$macports::autoconf::os_platform $macports::autoconf::os_major\""
             ui_error "If you upgraded your OS or changed the hardware architecture, you need to run 'port migrate' instead."
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -85,6 +104,10 @@ namespace eval restore {
</span>         return [registry::snapshot get_by_id $snapshot_id]
     }
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+    proc fetch_snapshot_last {} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return [registry::snapshot get_last]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span>     proc list_snapshots {} {
         return [registry::snapshot get_all]
     }
<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 046d693..32f23a8 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;'>@@ -2807,7 +2807,11 @@ proc action_reclaim { action portlist opts } {
</span> }
 
 proc action_snapshot { action portlist opts } {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        return [macports::snapshot_main $opts]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if {[catch {macports::snapshot_main $opts} result]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        ui_debug $::errorInfo
</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;'>+   return 0
</span> }
 
 proc action_restore { action portlist opts } {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4462,7 +4466,7 @@ array set cmd_opts_array {
</span>     reclaim     {enable-reminders disable-reminders}
     fetch       {no-mirrors}
     snapshot    {{note 1}}
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    restore     {{snapshot-id 1}}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    restore     {{snapshot-id 1} last}
</span> }
 
 ##
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/registry2.0/snapshot.c b/src/registry2.0/snapshot.c
</span><span style='display:block; white-space:pre;color:#808080;'>index 7817a1c..74f7dcb 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/registry2.0/snapshot.c
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/registry2.0/snapshot.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -121,6 +121,38 @@ static int snapshot_get(Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[]) {
</span> }
 
 /*
<span style='display:block; white-space:pre;background:#e0ffe0;'>+ * registry::snaphot get_last
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static int snapshot_get_last(Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[]) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    reg_registry* reg = registry_for(interp, reg_attached);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (objc > 2) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        Tcl_WrongNumArgs(interp, 1, objv, "get_last");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return TCL_ERROR;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    } else if (reg == NULL) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return TCL_ERROR;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        reg_error error;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        reg_snapshot** snapshots;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        int limit = 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        // 1 passed in reg_snapshot_list is to get the last '1' snapshot.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        int snapshot_count = reg_snapshot_list(reg, &snapshots, limit, &error);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if (snapshot_count >= 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            int retval;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            Tcl_Obj* result;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if (snapshot_to_obj(interp, &result, snapshots[0], NULL, &error)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                Tcl_SetObjResult(interp, result);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                retval = TCL_OK;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                retval = registry_failed(interp, &error);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            free(snapshots);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            return retval;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return registry_failed(interp, &error);
</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;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/*
</span>  * registry::snaphot get_all
  */
 static int snapshot_get_list(Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[]) {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -133,7 +165,9 @@ static int snapshot_get_list(Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[]
</span>     } else {
         reg_error error;
         reg_snapshot** snapshots;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        int snapshot_count = reg_snapshot_list(reg, &snapshots, &error);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        int limit = 10;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        // limit = k passed in reg_snapshot_list is to get the last 'k' snapshots
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        int snapshot_count = reg_snapshot_list(reg, &snapshots, limit, &error);
</span>         if (snapshot_count >= 0) {
             int retval;
             Tcl_Obj* result;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -162,6 +196,7 @@ static snapshot_cmd_type snapshot_cmds[] = {
</span>     /* Global commands */
     { "create", snapshot_create},
     { "get_by_id", snapshot_get},
<span style='display:block; white-space:pre;background:#e0ffe0;'>+    { "get_last", snapshot_get_last},
</span>     { "get_all", snapshot_get_list},
     { NULL, NULL }
 };
</pre><pre style='margin:0'>

</pre>