[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