github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/mergeCode/vndr/godl/get.go (about) 1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package godl 6 7 import ( 8 "fmt" 9 "os" 10 "path/filepath" 11 "regexp" 12 "strconv" 13 "strings" 14 ) 15 16 // VCS represents package vcs root. 17 type VCS struct { 18 Root string 19 ImportPath string 20 Type string 21 } 22 23 // Download downloads package by its import path. It can be a subpackage, 24 // whole repo will be downloaded anyway. 25 // if repoPath is not empty string, it will be uses for vcs. 26 // target is top directory for download. i.e. if target is vendor/ and 27 // importPath is github.com/LK4D4/vndr, package will be downloaded to 28 // vendor/github.com/LK4D4/vndr. 29 // rev is desired revision of package. 30 func Download(importPath, repoPath, target, rev string) (*VCS, error) { 31 security := secure 32 // Analyze the import path to determine the version control system, 33 // repository, and the import path for the root of the repository. 34 rr, err := repoRootForImportPath(importPath, security) 35 if err != nil { 36 return nil, err 37 } 38 root := filepath.Join(target, rr.root) 39 if repoPath != "" { 40 rr.repo = repoPath 41 } 42 43 if err := os.RemoveAll(root); err != nil { 44 return nil, fmt.Errorf("remove package root: %v", err) 45 } 46 // Some version control tools require the parent of the target to exist. 47 parent, _ := filepath.Split(root) 48 if err = os.MkdirAll(parent, 0777); err != nil { 49 return nil, err 50 } 51 if rev == "" { 52 if err = rr.vcs.create(root, rr.repo); err != nil { 53 return nil, err 54 } 55 } else { 56 if err = rr.vcs.createRev(root, rr.repo, rev); err != nil { 57 return nil, err 58 } 59 } 60 return &VCS{Root: root, ImportPath: importPath, Type: rr.vcs.cmd}, nil 61 } 62 63 // goTag matches go release tags such as go1 and go1.2.3. 64 // The numbers involved must be small (at most 4 digits), 65 // have no unnecessary leading zeros, and the version cannot 66 // end in .0 - it is go1, not go1.0 or go1.0.0. 67 var goTag = regexp.MustCompile( 68 `^go((0|[1-9][0-9]{0,3})\.)*([1-9][0-9]{0,3})$`, 69 ) 70 71 // selectTag returns the closest matching tag for a given version. 72 // Closest means the latest one that is not after the current release. 73 // Version "goX" (or "goX.Y" or "goX.Y.Z") matches tags of the same form. 74 // Version "release.rN" matches tags of the form "go.rN" (N being a floating-point number). 75 // Version "weekly.YYYY-MM-DD" matches tags like "go.weekly.YYYY-MM-DD". 76 // 77 // NOTE(rsc): Eventually we will need to decide on some logic here. 78 // For now, there is only "go1". This matches the docs in go help get. 79 func selectTag(goVersion string, tags []string) (match string) { 80 for _, t := range tags { 81 if t == "go1" { 82 return "go1" 83 } 84 } 85 return "" 86 87 /* 88 if goTag.MatchString(goVersion) { 89 v := goVersion 90 for _, t := range tags { 91 if !goTag.MatchString(t) { 92 continue 93 } 94 if cmpGoVersion(match, t) < 0 && cmpGoVersion(t, v) <= 0 { 95 match = t 96 } 97 } 98 } 99 100 return match 101 */ 102 } 103 104 // cmpGoVersion returns -1, 0, +1 reporting whether 105 // x < y, x == y, or x > y. 106 func cmpGoVersion(x, y string) int { 107 // Malformed strings compare less than well-formed strings. 108 if !goTag.MatchString(x) { 109 return -1 110 } 111 if !goTag.MatchString(y) { 112 return +1 113 } 114 115 // Compare numbers in sequence. 116 xx := strings.Split(x[len("go"):], ".") 117 yy := strings.Split(y[len("go"):], ".") 118 119 for i := 0; i < len(xx) && i < len(yy); i++ { 120 // The Atoi are guaranteed to succeed 121 // because the versions match goTag. 122 xi, _ := strconv.Atoi(xx[i]) 123 yi, _ := strconv.Atoi(yy[i]) 124 if xi < yi { 125 return -1 126 } else if xi > yi { 127 return +1 128 } 129 } 130 131 if len(xx) < len(yy) { 132 return -1 133 } 134 if len(xx) > len(yy) { 135 return +1 136 } 137 return 0 138 }