import (
        "fmt"
+       "go/build"
        "os"
        "path/filepath"
        "runtime"
 
 func runGet(cmd *Command, args []string) {
        // Phase 1.  Download/update.
-       args = importPaths(args)
        var stk importStack
-       for _, arg := range args {
+       for _, arg := range downloadPaths(args) {
                download(arg, &stk)
        }
        exitIfErrors()
 
-       if *getD {
-               // download only
-               return
-       }
-
-       // Phase 2. Install.
+       // Phase 2. Rescan packages and reevaluate args list.
 
        // Code we downloaded and all code that depends on it
        // needs to be evicted from the package cache so that
                delete(packageCache, name)
        }
 
+       args = importPaths(args)
+
+       // Phase 3.  Install.
+       if *getD {
+               // Download only.
+               // Check delayed until now so that importPaths
+               // has a chance to print errors.
+               return
+       }
+
        runInstall(cmd, args)
 }
 
+// downloadPath prepares the list of paths to pass to download.
+// It expands ... patterns that can be expanded.  If there is no match
+// for a particular pattern, downloadPaths leaves it in the result list,
+// in the hope that we can figure out the repository from the
+// initial ...-free prefix.
+func downloadPaths(args []string) []string {
+       args = importPathsNoDotExpansion(args)
+       var out []string
+       for _, a := range args {
+               if strings.Contains(a, "...") {
+                       var expand []string
+                       // Use matchPackagesInFS to avoid printing
+                       // warnings.  They will be printed by the 
+                       // eventual call to importPaths instead.
+                       if build.IsLocalImport(a) {
+                               expand = matchPackagesInFS(a)
+                       } else {
+                               expand = matchPackages(a)
+                       }
+                       if len(expand) > 0 {
+                               out = append(out, expand...)
+                               continue
+                       }
+               }
+               out = append(out, a)
+       }
+       return out
+}
+
 // downloadCache records the import paths we have already
 // considered during the download, to avoid duplicate work when
 // there is more than one dependency sequence leading to
        }
        downloadCache[arg] = true
 
+       pkgs := []*Package{p}
+       wildcardOkay := len(*stk) == 0
+
        // Download if the package is missing, or update if we're using -u.
        if p.Dir == "" || *getU {
                // The actual download.
                stk.push(p.ImportPath)
-               defer stk.pop()
-               if err := downloadPackage(p); err != nil {
+               err := downloadPackage(p)
+               if err != nil {
                        errorf("%s", &PackageError{ImportStack: stk.copy(), Err: err.Error()})
+                       stk.pop()
                        return
                }
 
-               // Reread the package information from the updated files.
-               p = reloadPackage(arg, stk)
-               if p.Error != nil {
-                       errorf("%s", p.Error)
-                       return
+               args := []string{arg}
+               // If the argument has a wildcard in it, re-evaluate the wildcard.
+               // We delay this until after reloadPackage so that the old entry
+               // for p has been replaced in the package cache.
+               if wildcardOkay && strings.Contains(arg, "...") {
+                       if build.IsLocalImport(arg) {
+                               args = matchPackagesInFS(arg)
+                       } else {
+                               args = matchPackages(arg)
+                       }
                }
-       }
 
-       if *getFix {
-               run(stringList(tool("fix"), relPaths(p.gofiles)))
+               // Clear all relevant package cache entries before
+               // doing any new loads.
+               for _, arg := range args {
+                       p := packageCache[arg]
+                       if p != nil {
+                               delete(packageCache, p.Dir)
+                               delete(packageCache, p.ImportPath)
+                       }
+               }
 
-               // The imports might have changed, so reload again.
-               p = reloadPackage(arg, stk)
-               if p.Error != nil {
-                       errorf("%s", p.Error)
-                       return
+               pkgs = pkgs[:0]
+               for _, arg := range args {
+                       stk.push(arg)
+                       p := loadPackage(arg, stk)
+                       stk.pop()
+                       if p.Error != nil {
+                               errorf("%s", p.Error)
+                               continue
+                       }
+                       pkgs = append(pkgs, p)
                }
        }
 
-       // Process dependencies, now that we know what they are.
-       for _, dep := range p.deps {
-               download(dep.ImportPath, stk)
+       // Process package, which might now be multiple packages
+       // due to wildcard expansion.
+       for _, p := range pkgs {
+               if *getFix {
+                       run(stringList(tool("fix"), relPaths(p.gofiles)))
+
+                       // The imports might have changed, so reload again.
+                       p = reloadPackage(arg, stk)
+                       if p.Error != nil {
+                               errorf("%s", p.Error)
+                               return
+                       }
+               }
+
+               // Process dependencies, now that we know what they are.
+               for _, dep := range p.deps {
+                       download(dep.ImportPath, stk)
+               }
        }
 }