Index: src/port/port.1
===================================================================
--- src/port/port.1	(revision 25313)
+++ src/port/port.1	(working copy)
@@ -358,6 +358,14 @@
 For example:
 .Pp
 .Dl "port -n upgrade ethereal"
+.Pp 
+Note that in selecting the variants to use in the upgraded build of the
+port, any variants specified on the command line take highest precedence,
+then the variants active in the latest installed version of the port, and
+finally the global variants specified in variants.conf, if any.  Note that
+upgrade will not normally rebuild a port only to change the selected
+variants; you can either specify -f, or deactivate the port and reinstall it
+with different variants.
 .Ss clean
 Clean the files used for building
 .Ar portname .
Index: src/port/port.tcl
===================================================================
--- src/port/port.tcl	(revision 25313)
+++ src/port/port.tcl	(working copy)
@@ -1410,14 +1410,10 @@
     global global_variations
 	require_portlist portlist
 	foreachport $portlist {
-		# Merge global variations into the variations specified for this port
-		foreach { variation value } [array get global_variations] {
-			if { ![info exists variations($variation)] } {
-				set variations($variation) $value
-			}
-		}
-		
-		darwinports::upgrade $portname "port:$portname" [array get variations] [array get options]
+		# Global variations will have to be merged into the specified
+	        # variations, but perhaps after the installed variations are
+	        # merged. So we pass them into upgrade:
+		darwinports::upgrade $portname "port:$portname" [array get global_variations] [array get variations] [array get options]
 	}
 	
 	return 0
Index: src/darwinports1.0/darwinports.tcl
===================================================================
--- src/darwinports1.0/darwinports.tcl	(revision 25313)
+++ src/darwinports1.0/darwinports.tcl	(working copy)
@@ -1607,10 +1607,14 @@
 }
 
 # upgrade procedure
-proc darwinports::upgrade {portname dspec variationslist optionslist {depscachename ""}} {
+proc darwinports::upgrade {portname dspec globalvarlist variationslist optionslist {depscachename ""}} {
 	global darwinports::registry.installtype
 	global darwinports::portarchivemode
 	array set options $optionslist
+	# Note $variationslist is left alone and so retains the original
+        # requested variations, which should be passed to recursive calls to
+	# upgrade; while variations gets existing variants and global variations
+        # merged in later on, so it applies only to this port's upgrafe
 	array set variations $variationslist
 	if {![string match "" $depscachename]} {
 		upvar $depscachename depscache
@@ -1646,6 +1650,10 @@
 	# if this is set (not 0) we dont follow the deps
 	set depflag 0
 
+        # Sooner or later we may have to open this port to update the portinfo
+	# by evaluating the variants. Keep track of whether this has happened
+	set portwasopened 0
+
 	# set version_installed
 	set ilist {}
 	if { [catch {set ilist [registry::installed $portname ""]} result] } {
@@ -1653,15 +1661,26 @@
 			ui_debug "$portname is *not* installed by DarwinPorts"
 			# open porthandle    
 			set porturl $portinfo(porturl)
-		    if {![info exists porturl]} {
-		        set porturl file://./    
+			if {![info exists porturl]} {
+				set porturl file://./    
 			}    
-			if {[catch {set workername [dportopen $porturl [array get options] ]} result]} {
-					global errorInfo
-					ui_debug "$errorInfo"
+			# Merge the global variations into the specified
+			foreach { variation value } $globalvarlist {
+				if { ![info exists variations($variation)] } {
+					set variations($variation) $value
+				}
+			}
+		
+			if {[catch {set workername [dportopen $porturl [array get options] [array get variations]]} result]} {
+				global errorInfo
+				ui_debug "$errorInfo"
 			        ui_error "Unable to open port: $result"        
-					return 1
-		    }
+				return 1
+			}
+			# While we're at it, update the portinfo
+			array unset portinfo
+			array set portinfo [dportinfo $workername]
+			set portwasopened 1
 
 			if {![_dportispresent $workername $dspec ] } {
 				# port in not installed - install it!
@@ -1671,12 +1690,18 @@
 					ui_error "Unable to exec port: $result"
 					return 1
 				}
+				if {$result > 0} {
+					ui_error "Problem while installing $portname"
+					return $result
+				}
 			} else {
 				# port installed outside DP
 				ui_debug "$portname installed outside the MacPorts system"
 				set depflag 1
 			}
 
+			# update ilist since we just did an installation
+			set ilist [registry::installed $portname ""]
 		} else {
 			ui_error "Checking installed version failed: $result"
 			exit 1
@@ -1685,6 +1710,7 @@
 	set anyactive 0
 	set version_installed 0
 	set epoch_installed 0
+
 	if {$ilist == ""} {
 		# XXX  this sets $version_installed to $version_in_tree even if not installed!!
 		set version_installed $version_in_tree
@@ -1717,12 +1743,14 @@
     			}
 			}
 		}
-        if { [lindex $num 4] == 0 && 0 == [string compare "image" ${darwinports::registry.installtype}] } {
+		# record the variant of the latest version
+		set variant [lindex $num 3]
+		if { [lindex $num 4] == 0 && 0 == [string compare "image" ${darwinports::registry.installtype}] } {
 			# activate the latest installed version
 			if {[catch {portimage::activate $portname $version_installed$variant $optionslist} result]} {
 				global errorInfo
 				ui_debug "$errorInfo"
-    			ui_error "Activating $portname $version_installed failed: $result"
+				ui_error "Activating $portname $version_installed failed: $result"
 				return 1
 			}
 		}
@@ -1731,7 +1759,7 @@
 	# output version numbers
 	ui_debug "epoch: in tree: $epoch_in_tree installed: $epoch_installed"
 	ui_debug "$portname $version_in_tree exists in the ports tree"
-	ui_debug "$portname $version_installed is installed"
+	ui_debug "$portname $version_installed $variant is installed"
 
 	# set the nodeps option  
 	if {![info exists options(ports_nodeps)]} {
@@ -1740,6 +1768,63 @@
 		set nodeps yes
 	}
 
+	# save existing variant for later use
+	set oldvariant $variant
+	if {$portwasopened == 0} {
+		# If the port has not been opened, then before we do 
+		# dependencies, we need to figure out the final variants, 
+		# open the port, and update the portinfo. (If it was opened,
+		# then the variants must still be the ones we opened it with,
+		# and the portinfo is correct.)
+
+		set porturl $portinfo(porturl)
+		if {![info exists porturl]} {
+			set porturl file://./
+		}
+
+		# check if the variants is present in $version_in_tree
+		set variant [split $variant +]
+		ui_debug "Merging existing variants $variant into variants"
+		if {[info exists portinfo(variants)]} {
+			set avariants $portinfo(variants)
+		} else {
+			set avariants {}
+		}
+		ui_debug "available variants are : $avariants"
+		foreach v $variant {
+			if {[lsearch $avariants $v] == -1} {
+			} else {
+				ui_debug "variant $v is present in $portname $version_in_tree"
+				if { ![info exists variations($v)]} {
+					set variations($v) "+"
+				}
+			}
+		}
+		
+		# Now merge in the global (i.e. variants.conf) variations.
+		# We wait until now so that existing variants for this port
+		# override global variations
+		foreach { variation value } $globalvarlist {
+			if { ![info exists variations($variation)] } {
+				set variations($variation) $value
+			}
+		}
+		
+		ui_debug "new fully merged portvariants: [array get variations]"
+	
+		if {[catch {set workername [dportopen $porturl [array get options] [array get variations]]} result]} {
+			global errorInfo
+			ui_debug "$errorInfo"
+			ui_error "Unable to open port: $result"
+			return 1
+		}
+
+		array unset portinfo
+		array set portinfo [dportinfo $workername]
+		set portwasopened 1
+	}
+		
+
 	if {$nodeps == "yes" || $depflag == 1} {
 		ui_debug "Not following dependencies"
 		set depflag 0
@@ -1750,7 +1835,7 @@
 				if {![llength [array get depscache $i]]} {
 				set d [lindex [split $i :] end]
 					set depscache($i) 1
-					upgrade $d $i $variationslist $optionslist depscache
+					upgrade $d $i $globalvarlist $variationslist $optionslist depscache
 				} 
 			}
 		}
@@ -1760,7 +1845,7 @@
 				if {![llength [array get depscache $i]]} {
 				set d [lindex [split $i :] end]
 					set depscache($i) 1
-					upgrade $d $i $variationslist $optionslist depscache
+					upgrade $d $i $globalvarlist $variationslist $optionslist depscache
 				} 
 			}
 		}
@@ -1770,7 +1855,7 @@
 				if {![llength [array get depscache $i]]} {
 				set d [lindex [split $i :] end]
 					set depscache($i) 1
-					upgrade $d $i $variationslist $optionslist depscache
+					upgrade $d $i $globalvarlist $variationslist $optionslist depscache
 				} 
 			}
 		}
@@ -1779,6 +1864,10 @@
 	# check installed version against version in ports
 	if { [rpm-vercomp $version_installed $version_in_tree] >= 0 && ![info exists options(ports_force)] } {
 		ui_debug "No need to upgrade! $portname $version_installed >= $portname $version_in_tree"
+		if {[info exists portinfo(portvariants)]
+		    && $portinfo(portvariants) != $oldvariant} {
+			ui_warn "Skipping upgrdae since $portname $version_installed >= $portname $version_in_tree, even though installed variant $oldvariant differs from $portinfo(portvariants). Specify -f to force upgrade."
+		}
 		if { $epoch_installed >= $epoch_in_tree } {
 			# Check if we have to do dependents
 			if {[info exists options(ports_do_dependents)]} {
@@ -1791,7 +1880,7 @@
 				if { [llength deplist] > 0 } {
 					foreach dep $deplist {
 						set dpname [lindex $dep 2] 
-						darwinports::upgrade $dpname "port:$dpname" [array get variations] [array get options]
+						darwinports::upgrade $dpname "port:$dpname" $globalvarlist $variationslist [array get options]
 					}
 				}
 			}
@@ -1803,38 +1892,7 @@
 		}
 	}
 
-	# open porthandle
-	set porturl $portinfo(porturl)
-	if {![info exists porturl]} {
-		set porturl file://./
-	}
 
-	# check if the variants is present in $version_in_tree
-	set oldvariant $variant
-	set variant [split $variant +]
-	ui_debug "variants to install $variant"
-	if {[info exists portinfo(variants)]} {
-		set avariants $portinfo(variants)
-	} else {
-		set avariants {}
-	}
-	ui_debug "available variants are : $avariants"
-	foreach v $variant {
-		if {[lsearch $avariants $v] == -1} {
-		} else {
-			ui_debug "variant $v is present in $portname $version_in_tree"
-			set variations($v) "+"
-		}
-	}
-	ui_debug "new portvariants: [array get variations]"
-	
-	if {[catch {set workername [dportopen $porturl [array get options] [array get variations]]} result]} {
-		global errorInfo
-		ui_debug "$errorInfo"
-		ui_error "Unable to open port: $result"
-		return 1
-	}
-
 	# install version_in_tree
 	if {0 == [string compare "yes" ${darwinports::portarchivemode}]} {
 		set upgrade_action "archive"
@@ -1887,7 +1945,7 @@
 		if { [llength deplist] > 0 } {
 			foreach dep $deplist {
 				set dpname [lindex $dep 2] 
-				darwinports::upgrade $dpname "port:$dpname" [array get variations] [array get options]
+				darwinports::upgrade $dpname "port:$dpname" $globalvarlist $variationslist [array get options]
 			}
 		}
 	}

