]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgo/go/cmd/go/internal/modconv/dep.go
libgo: update to Go1.14beta1
[thirdparty/gcc.git] / libgo / go / cmd / go / internal / modconv / dep.go
CommitLineData
dd931d9b
ILT
1// Copyright 2018 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
5package modconv
6
7import (
8 "fmt"
aa8901e9
ILT
9 "internal/lazyregexp"
10 "net/url"
11 "path"
dd931d9b
ILT
12 "strconv"
13 "strings"
14
5a8ea165
ILT
15 "golang.org/x/mod/modfile"
16 "golang.org/x/mod/module"
17 "golang.org/x/mod/semver"
dd931d9b
ILT
18)
19
20func ParseGopkgLock(file string, data []byte) (*modfile.File, error) {
aa8901e9
ILT
21 type pkg struct {
22 Path string
23 Version string
24 Source string
25 }
dd931d9b 26 mf := new(modfile.File)
aa8901e9
ILT
27 var list []pkg
28 var r *pkg
dd931d9b
ILT
29 for lineno, line := range strings.Split(string(data), "\n") {
30 lineno++
31 if i := strings.Index(line, "#"); i >= 0 {
32 line = line[:i]
33 }
34 line = strings.TrimSpace(line)
35 if line == "[[projects]]" {
aa8901e9 36 list = append(list, pkg{})
dd931d9b
ILT
37 r = &list[len(list)-1]
38 continue
39 }
40 if strings.HasPrefix(line, "[") {
41 r = nil
42 continue
43 }
44 if r == nil {
45 continue
46 }
47 i := strings.Index(line, "=")
48 if i < 0 {
49 continue
50 }
51 key := strings.TrimSpace(line[:i])
52 val := strings.TrimSpace(line[i+1:])
53 if len(val) >= 2 && val[0] == '"' && val[len(val)-1] == '"' {
54 q, err := strconv.Unquote(val) // Go unquoting, but close enough for now
55 if err != nil {
56 return nil, fmt.Errorf("%s:%d: invalid quoted string: %v", file, lineno, err)
57 }
58 val = q
59 }
60 switch key {
61 case "name":
62 r.Path = val
aa8901e9
ILT
63 case "source":
64 r.Source = val
dd931d9b
ILT
65 case "revision", "version":
66 // Note: key "version" should take priority over "revision",
67 // and it does, because dep writes toml keys in alphabetical order,
68 // so we see version (if present) second.
69 if key == "version" {
70 if !semver.IsValid(val) || semver.Canonical(val) != val {
71 break
72 }
73 }
74 r.Version = val
75 }
76 }
77 for _, r := range list {
78 if r.Path == "" || r.Version == "" {
79 return nil, fmt.Errorf("%s: empty [[projects]] stanza (%s)", file, r.Path)
80 }
aa8901e9
ILT
81 mf.Require = append(mf.Require, &modfile.Require{Mod: module.Version{Path: r.Path, Version: r.Version}})
82
83 if r.Source != "" {
84 // Convert "source" to import path, such as
85 // git@test.com:x/y.git and https://test.com/x/y.git.
86 // We get "test.com/x/y" at last.
87 source, err := decodeSource(r.Source)
88 if err != nil {
89 return nil, err
90 }
91 old := module.Version{Path: r.Path, Version: r.Version}
92 new := module.Version{Path: source, Version: r.Version}
93 mf.Replace = append(mf.Replace, &modfile.Replace{Old: old, New: new})
94 }
dd931d9b
ILT
95 }
96 return mf, nil
97}
aa8901e9
ILT
98
99var scpSyntaxReg = lazyregexp.New(`^([a-zA-Z0-9_]+)@([a-zA-Z0-9._-]+):(.*)$`)
100
101func decodeSource(source string) (string, error) {
102 var u *url.URL
103 var p string
104 if m := scpSyntaxReg.FindStringSubmatch(source); m != nil {
105 // Match SCP-like syntax and convert it to a URL.
106 // Eg, "git@github.com:user/repo" becomes
107 // "ssh://git@github.com/user/repo".
108 u = &url.URL{
109 Scheme: "ssh",
110 User: url.User(m[1]),
111 Host: m[2],
112 Path: "/" + m[3],
113 }
114 } else {
115 var err error
116 u, err = url.Parse(source)
117 if err != nil {
118 return "", fmt.Errorf("%q is not a valid URI", source)
119 }
120 }
121
122 // If no scheme was passed, then the entire path will have been put into
123 // u.Path. Either way, construct the normalized path correctly.
124 if u.Host == "" {
125 p = source
126 } else {
127 p = path.Join(u.Host, u.Path)
128 }
129 p = strings.TrimSuffix(p, ".git")
130 p = strings.TrimSuffix(p, ".hg")
131 return p, nil
132}