[124488] trunk/base/src/macports1.0

larryv at macports.org larryv at macports.org
Sun Aug 24 18:59:51 PDT 2014


Revision: 124488
          https://trac.macports.org/changeset/124488
Author:   larryv at macports.org
Date:     2014-08-24 18:59:51 -0700 (Sun, 24 Aug 2014)
Log Message:
-----------
macports.tcl: Factor VCS syncing out of mportsync.

The previous code was basically the same thing repeated twice - once for
Subversion, once for Git. Refactoring the VCS syncing logic should
reduce repetition, make it easier to add support for new VCSes later,
and make mportsync a little less sprawling.

Modified Paths:
--------------
    trunk/base/src/macports1.0/macports.tcl
    trunk/base/src/macports1.0/tests/macports.test

Modified: trunk/base/src/macports1.0/macports.tcl
===================================================================
--- trunk/base/src/macports1.0/macports.tcl	2014-08-24 22:15:05 UTC (rev 124487)
+++ trunk/base/src/macports1.0/macports.tcl	2014-08-25 01:59:51 UTC (rev 124488)
@@ -2312,6 +2312,84 @@
     return [file join [macports::getsourcepath $source] PortIndex]
 }
 
+# macports::GetVCSUpdateCmd --
+#
+# Determine whether the given directory is associated with a repository
+# for a supported version control system. If so, return a list
+# containing two strings:
+#
+#   1) The human-readable name of the version control system.
+#   2) A command that will update the repository's working tree to the
+#      latest commit/changeset/revision/whatever. This command should
+#      work properly from any working directory, although it doesn't
+#      have to worry about cleaning up after itself (restoring the
+#      environment, changing back to the initial directory, etc.).
+#
+# If the directory is not associated with any supported system, return
+# an empty list.
+#
+proc macports::GetVCSUpdateCmd portDir {
+
+    set oldPWD [pwd]
+    cd $portDir
+
+    # Subversion
+    if {![catch {macports::findBinary svn} svn] &&
+        ([file exists .svn] ||
+         ![catch {exec $svn info >/dev/null 2>@1}])
+    } then {
+        return [list Subversion "$svn update --non-interactive $portDir"]
+    }
+
+    # Git
+    if {![catch {macports::findBinary git} git] &&
+        ![catch {exec $git rev-parse --is-inside-work-tree}]
+    } then {
+        if {![catch {exec $git config --local --get svn-remote.svn.url}]} {
+            # git-svn repository
+            return [list git-svn "cd $portDir && $git svn rebase || true"]
+        }
+        # regular git repository
+        return [list Git "cd $portDir && $git pull --rebase || true"]
+    }
+
+    # Add new VCSes here!
+
+    cd $oldPWD
+    return [list]
+}
+
+# macports::UpdateVCS --
+#
+# Execute the given command in a shell. If called with superuser
+# privileges, execute the command as the user/group that owns the given
+# directory, restoring privileges before returning.
+#
+# This proc could probably be generalized and used elsewhere.
+#
+proc macports::UpdateVCS {cmd portDir} {
+    if {[getuid] == 0} {
+        # Must change egid before dropping root euid.
+        set oldEGID [getegid]
+        set newEGID [name_to_gid [file attributes $portDir -group]]
+        setegid $newEGID
+        ui_debug "Changed effective group ID from $oldEGID to $newEGID"
+        set oldEUID [geteuid]
+        set newEUID [name_to_uid [file attributes $portDir -owner]]
+        seteuid $newEUID
+        ui_debug "Changed effective user ID from $oldEUID to $newEUID"
+    }
+    ui_debug $cmd
+    catch {system $cmd} result options
+    if {[getuid] == 0} {
+        seteuid $oldEUID
+        ui_debug "Changed effective user ID from $newEUID to $oldEUID"
+        setegid $oldEGID
+        ui_debug "Changed effective group ID from $newEGID to $oldEGID"
+    }
+    return -options $options $result
+}
+
 proc mportsync {{optionslist {}}} {
     global macports::sources macports::portdbpath macports::rsync_options \
            tcl_platform macports::portverbose macports::autoconf::rsync_path \
@@ -2337,88 +2415,20 @@
         switch -regexp -- [macports::getprotocol $source] {
             {^file$} {
                 set portdir [macports::getportdir $source]
-                set svn_cmd {}
-                catch {set svn_cmd [macports::findBinary svn]}
-                set git_cmd {}
-                catch {set git_cmd [macports::findBinary git]}
-                if {$svn_cmd ne {} && ([file exists ${portdir}/.svn] || ![catch {exec $svn_cmd info $portdir > /dev/null 2>@1}])} {
-                    set svn_commandline "$svn_cmd update --non-interactive $portdir"
-                    ui_debug $svn_commandline
-                    if {
-                        [catch {
-                            if {[getuid] == 0} {
-                                # Must change egid before dropping root euid.
-                                set old_egid [getegid]
-                                set new_egid [name_to_gid [file attributes $portdir -group]]
-                                setegid $new_egid
-                                ui_debug "Changed effective group ID from $old_egid to $new_egid"
-                                set old_euid [geteuid]
-                                set new_euid [name_to_uid [file attributes $portdir -owner]]
-                                seteuid $new_euid
-                                ui_debug "Changed effective user ID from $old_euid to $new_euid"
-                            }
-                            system $svn_commandline
-                            if {[getuid] == 0} {
-                                seteuid $old_euid
-                                ui_debug "Changed effective user ID from $new_euid to $old_euid"
-                                setegid $old_egid
-                                ui_debug "Changed effective group ID from $new_egid to $old_egid"
-                            }
-                        }]
-                    } {
+                if {[catch {macports::GetVCSUpdateCmd $portdir} repoInfo]} {
+                    ui_debug $::errorInfo
+                    ui_info "Could not access contents of $portdir"
+                    incr numfailed
+                    continue
+                }
+                if {[llength $repoInfo]} {
+                    lassign $repoInfo vcs cmd
+                    if {[catch {macports::UpdateVCS $cmd $portdir}]} {
                         ui_debug $::errorInfo
-                        ui_error "Synchronization of the local ports tree failed doing an svn update"
-                        if {[getuid] == 0} {
-                            seteuid $old_euid
-                            ui_debug "Changed effective user ID from $new_euid to $old_euid"
-                            setegid $old_egid
-                            ui_debug "Changed effective group ID from $new_egid to $old_egid"
-                        }
+                        ui_info "Syncing local $vcs ports tree failed"
                         incr numfailed
                         continue
                     }
-                } elseif {$git_cmd ne {} && ![catch {exec sh -c "cd ${portdir} && $git_cmd rev-parse --is-inside-work-tree"} result]} {
-                    # determine what type of git repository this is
-                    if {![catch {exec sh -c "cd ${portdir} && $git_cmd config --local --get svn-remote.svn.url"} result]} {
-                        set git_action "svn rebase"
-                    } else {
-                        set git_action "pull --rebase"
-                    }
-                    set git_commandline "cd $portdir && $git_cmd $git_action || true"
-                    ui_debug $git_commandline
-                    if {
-                        [catch {
-                            if {[getuid] == 0} {
-                                # Must change egid before dropping root euid.
-                                set old_egid [getegid]
-                                set new_egid [name_to_gid [file attributes $portdir -group]]
-                                setegid $new_egid
-                                ui_debug "Changed effective group ID from $old_egid to $new_egid"
-                                set old_euid [geteuid]
-                                set new_euid [name_to_uid [file attributes $portdir -owner]]
-                                seteuid $new_euid
-                                ui_debug "Changed effective user ID from $old_euid to $new_euid"
-                            }
-                            system $git_commandline
-                            if {[getuid] == 0} {
-                                seteuid $old_euid
-                                ui_debug "Changed effective user ID from $new_euid to $old_euid"
-                                setegid $old_egid
-                                ui_debug "Changed effective group ID from $new_egid to $old_egid"
-                            }
-                        }]
-                    } {
-                        ui_debug $::errorInfo
-                        ui_error "Synchronization of the local ports tree failed doing a git update"
-                        if {[getuid] == 0} {
-                            seteuid $old_euid
-                            ui_debug "Changed effective user ID from $new_euid to $old_euid"
-                            setegid $old_egid
-                            ui_debug "Changed effective group ID from $new_egid to $old_egid"
-                        }
-                        incr numfailed
-                        continue
-                    }
                 }
                 set needs_portindex true
             }

Modified: trunk/base/src/macports1.0/tests/macports.test
===================================================================
--- trunk/base/src/macports1.0/tests/macports.test	2014-08-24 22:15:05 UTC (rev 124487)
+++ trunk/base/src/macports1.0/tests/macports.test	2014-08-25 01:59:51 UTC (rev 124488)
@@ -704,6 +704,85 @@
 # test getportworkpath_from_buildpath
 # test getportworkpath_from_portdir
 # test getindex
+
+
+# The test files might themselves be under version control, so the test
+# repositories need to live somewhere else.
+# TODO: Replace with "file tempfile" when we move to Tcl 8.6.
+package require fileutil 1.5.1-
+set tempdir [::fileutil::tempdir]
+
+
+testConstraint hasSvn [expr {
+    ![catch {macports::findBinary svn} svn] &&
+    ![catch {macports::findBinary svnadmin} svnadmin]
+}]
+
+test GetVCSUpdateCmd-svn {
+    Tests GetVCSUpdateCmd on a valid Subversion repository
+} -constraints {
+    hasSvn
+} -setup {
+    set repo [makeDirectory macports-test-svn-repo $tempdir]
+    exec $svnadmin create $repo
+    set wc [makeDirectory macports-test-svn-wc $tempdir]
+    # This URL should probably be encoded.
+    exec $svn checkout file://$repo $wc
+} -body {
+    string map [list $svn SVN $wc WC] [macports::GetVCSUpdateCmd $wc]
+} -cleanup {
+    removeDirectory macports-test-svn-wc $tempdir
+    removeDirectory macports-test-svn-repo $tempdir
+} -result {Subversion {SVN update --non-interactive WC}}
+
+
+testConstraint hasGit [expr {![catch {macports::findBinary git} git]}]
+
+test GetVCSUpdateCmd-git {
+    Tests GetVCSUpdateCmd on a valid Git repository
+} -constraints {
+    hasGit
+} -setup {
+    set repo [makeDirectory macports-test-git-repo $tempdir]
+    exec $git init $repo
+} -body {
+    string map [list $git GIT $repo REPO] [macports::GetVCSUpdateCmd $repo]
+} -cleanup {
+    removeDirectory macports-test-git-repo $tempdir
+} -result {Git {cd REPO && GIT pull --rebase || true}}
+
+
+testConstraint hasGitSvn [expr {
+    ![catch {macports::findBinary git} git] &&
+    [file readable [file join [exec $git --exec-path] git-svn]]
+}]
+
+test GetVCSUpdateCmd-gitsvn {
+    Tests GetVCSUpdateCmd on a valid git-svn repository
+} -constraints {
+    hasGitSvn
+} -setup {
+    set repo [makeDirectory macports-test-git-svn-repo $tempdir]
+    exec $git svn init http://localhost $repo
+} -body {
+    string map [list $git GIT $repo REPO] [macports::GetVCSUpdateCmd $repo]
+} -cleanup {
+    removeDirectory macports-test-git-svn-repo $tempdir
+} -result {git-svn {cd REPO && GIT svn rebase || true}}
+
+
+test GetVCSUpdateCmd-none {
+    Tests GetVCSUpdateCmd on directories that aren't recognized repositories
+} -setup {
+    set repo [makeDirectory macports-test-non-repo $tempdir]
+} -body {
+    macports::GetVCSUpdateCmd $repo
+} -cleanup {
+    removeDirectory macports-test-non-repo $tempdir
+} -result {}
+
+
+# test updatevcs
 # test mportsync
 # test mportsearch
 # test mportlookup
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/macports-changes/attachments/20140824/107513bb/attachment.html>


More information about the macports-changes mailing list