New upstream version 0.0~git20170925.0.fd02c4a
Dr. Tobias Quathamer
6 years ago
436 | 436 | return "TODO" |
437 | 437 | } |
438 | 438 | |
439 | func websiteForGopkg(gopkg string) string { | |
440 | if strings.HasPrefix(gopkg, "github.com/") { | |
441 | return "https://" + gopkg | |
442 | } | |
443 | return "TODO" | |
444 | } | |
445 | ||
446 | 439 | func writeTemplates(dir, gopkg, debsrc, debbin, debversion string, dependencies []string) error { |
447 | 440 | if err := os.Mkdir(filepath.Join(dir, "debian"), 0755); err != nil { |
448 | 441 | return err |
481 | 474 | fmt.Fprintf(f, "Source: %s\n", debsrc) |
482 | 475 | // TODO: change this once we have a “golang” section. |
483 | 476 | fmt.Fprintf(f, "Section: devel\n") |
484 | fmt.Fprintf(f, "Priority: extra\n") | |
477 | fmt.Fprintf(f, "Priority: optional\n") | |
485 | 478 | fmt.Fprintf(f, "Maintainer: Debian Go Packaging Team <pkg-go-maintainers@lists.alioth.debian.org>\n") |
486 | 479 | fmt.Fprintf(f, "Uploaders: %s <%s>\n", getDebianName(), getDebianEmail()) |
487 | 480 | sort.Strings(dependencies) |
488 | 481 | builddeps := append([]string{"debhelper (>= 10)", "dh-golang", "golang-any"}, dependencies...) |
489 | 482 | fmt.Fprintf(f, "Build-Depends: %s\n", strings.Join(builddeps, ",\n ")) |
490 | fmt.Fprintf(f, "Standards-Version: 4.0.0\n") | |
491 | fmt.Fprintf(f, "Homepage: %s\n", websiteForGopkg(gopkg)) | |
483 | fmt.Fprintf(f, "Standards-Version: 4.1.0\n") | |
484 | fmt.Fprintf(f, "Homepage: %s\n", getHomepageForGopkg(gopkg)) | |
492 | 485 | fmt.Fprintf(f, "Vcs-Browser: https://anonscm.debian.org/cgit/pkg-go/packages/%s.git\n", debsrc) |
493 | 486 | fmt.Fprintf(f, "Vcs-Git: https://anonscm.debian.org/git/pkg-go/packages/%s.git\n", debsrc) |
494 | 487 | fmt.Fprintf(f, "XS-Go-Import-Path: %s\n", gopkg) |
535 | 528 | } |
536 | 529 | fmt.Fprintf(f, "Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/\n") |
537 | 530 | fmt.Fprintf(f, "Upstream-Name: %s\n", filepath.Base(gopkg)) |
538 | fmt.Fprintf(f, "Source: %s\n", websiteForGopkg(gopkg)) | |
531 | fmt.Fprintf(f, "Source: %s\n", getHomepageForGopkg(gopkg)) | |
532 | fmt.Fprintf(f, "Files-Excluded: vendor Godeps/_workspace\n") | |
539 | 533 | fmt.Fprintf(f, "\n") |
540 | 534 | fmt.Fprintf(f, "Files: *\n") |
541 | 535 | fmt.Fprintf(f, "Copyright: %s\n", copyright) |
634 | 628 | fmt.Fprintf(f, "* Package name : %s\n", debsrc) |
635 | 629 | fmt.Fprintf(f, " Version : %s\n", debversion) |
636 | 630 | fmt.Fprintf(f, " Upstream Author : %s\n", author) |
637 | fmt.Fprintf(f, "* URL : %s\n", websiteForGopkg(gopkg)) | |
631 | fmt.Fprintf(f, "* URL : %s\n", getHomepageForGopkg(gopkg)) | |
638 | 632 | fmt.Fprintf(f, "* License : %s\n", license) |
639 | 633 | fmt.Fprintf(f, " Programming Lang: Go\n") |
640 | 634 | fmt.Fprintf(f, " Description : %s\n", description) |
3 | 3 | "encoding/json" |
4 | 4 | "fmt" |
5 | 5 | "net/http" |
6 | "regexp" | |
6 | 7 | "strings" |
7 | 8 | "time" |
9 | ||
10 | "golang.org/x/net/html" | |
8 | 11 | ) |
9 | 12 | |
10 | 13 | type licensesReply struct { |
50 | 53 | "lgpl-2.1": "LGPL-2.1", |
51 | 54 | "lgpl-3.0": "LGPL-3.0", |
52 | 55 | //"mit" - expat? |
53 | //"mpl-2.0" (only 1.1 is in debian) | |
56 | "mpl-2.0": "MPL-2.0", // include in base-files >= 9.9 | |
54 | 57 | //"unlicense" (not in debian) |
55 | 58 | } |
56 | 59 | |
70 | 73 | On Debian systems, the complete text of the Apache version 2.0 license |
71 | 74 | can be found in "/usr/share/common-licenses/Apache-2.0". |
72 | 75 | `, |
76 | "MPL-2.0": ` This Source Code Form is subject to the terms of the Mozilla Public | |
77 | License, v. 2.0. If a copy of the MPL was not distributed with this | |
78 | file, You can obtain one at http://mozilla.org/MPL/2.0/. | |
79 | . | |
80 | On Debian systems, the complete text of the MPL-2.0 license can be found | |
81 | in "/usr/share/common-licenses/MPL-2.0". | |
82 | `, | |
83 | } | |
84 | ||
85 | var githubRegexp = regexp.MustCompile(`github\.com/([^/]+/[^/]+)`) | |
86 | ||
87 | func findGitHubRepo(gopkg string) (string, error) { | |
88 | if strings.HasPrefix(gopkg, "github.com/") { | |
89 | return strings.TrimPrefix(gopkg, "github.com/"), nil | |
90 | } | |
91 | resp, err := http.Get("https://" + gopkg + "?go-get=1") | |
92 | if err != nil { | |
93 | return "", err | |
94 | } | |
95 | defer resp.Body.Close() | |
96 | z := html.NewTokenizer(resp.Body) | |
97 | for { | |
98 | tt := z.Next() | |
99 | if tt == html.ErrorToken { | |
100 | return "", fmt.Errorf("%q is not on GitHub", gopkg) | |
101 | } | |
102 | token := z.Token() | |
103 | if token.Data != "meta" { | |
104 | continue | |
105 | } | |
106 | var meta struct { | |
107 | name, content string | |
108 | } | |
109 | for _, attr := range token.Attr { | |
110 | if attr.Key == "name" { | |
111 | meta.name = attr.Val | |
112 | } | |
113 | if attr.Key == "content" { | |
114 | meta.content = attr.Val | |
115 | } | |
116 | } | |
117 | ||
118 | match := func(name string, length int) string { | |
119 | if f := strings.Fields(meta.content); meta.name == name && len(f) == length { | |
120 | if f[0] != gopkg { | |
121 | return "" | |
122 | } | |
123 | if repoMatch := githubRegexp.FindStringSubmatch(f[2]); repoMatch != nil { | |
124 | return repoMatch[1] | |
125 | } | |
126 | } | |
127 | return "" | |
128 | } | |
129 | if repo := match("go-import", 3); repo != "" { | |
130 | return repo, nil | |
131 | } | |
132 | if repo := match("go-source", 4); repo != "" { | |
133 | return repo, nil | |
134 | } | |
135 | } | |
73 | 136 | } |
74 | 137 | |
75 | 138 | func getLicenseForGopkg(gopkg string) (string, string, error) { |
76 | if !strings.HasPrefix(gopkg, "github.com/") { | |
77 | return "", "", fmt.Errorf("%q is not on GitHub", gopkg) | |
139 | repo, err := findGitHubRepo(gopkg) | |
140 | if err != nil { | |
141 | return "", "", err | |
78 | 142 | } |
79 | 143 | // TODO: cache this reply |
80 | req, err := http.NewRequest("GET", "https://api.github.com/repos/"+gopkg[len("github.com/"):], nil) | |
144 | req, err := http.NewRequest("GET", "https://api.github.com/repos/"+repo, nil) | |
81 | 145 | if err != nil { |
82 | 146 | return "", "", err |
83 | 147 | } |
103 | 167 | } |
104 | 168 | |
105 | 169 | func getAuthorAndCopyrightForGopkg(gopkg string) (string, string, error) { |
106 | if !strings.HasPrefix(gopkg, "github.com/") { | |
107 | return "", "", fmt.Errorf("%q is not on GitHub", gopkg) | |
108 | } | |
109 | resp, err := http.Get("https://api.github.com/repos/" + gopkg[len("github.com/"):]) | |
170 | repo, err := findGitHubRepo(gopkg) | |
171 | if err != nil { | |
172 | return "", "", err | |
173 | } | |
174 | resp, err := http.Get("https://api.github.com/repos/" + repo) | |
110 | 175 | if err != nil { |
111 | 176 | return "", "", err |
112 | 177 | } |
137 | 202 | return "", "", err |
138 | 203 | } |
139 | 204 | |
140 | return ur.Name, creation.Format("2006") + " " + ur.Name, nil | |
205 | copyright := creation.Format("2006") + " " + ur.Name | |
206 | if strings.HasPrefix(repo, "google/") { | |
207 | // As per https://opensource.google.com/docs/creating/, Google retains | |
208 | // the copyright for repositories underneath github.com/google/. | |
209 | copyright = creation.Format("2006") + " Google Inc." | |
210 | } | |
211 | ||
212 | return ur.Name, copyright, nil | |
141 | 213 | } |
142 | 214 | |
143 | 215 | func getDescriptionForGopkg(gopkg string) (string, error) { |
144 | if !strings.HasPrefix(gopkg, "github.com/") { | |
145 | return "", fmt.Errorf("%q is not on GitHub", gopkg) | |
146 | } | |
147 | resp, err := http.Get("https://api.github.com/repos/" + gopkg[len("github.com/"):]) | |
216 | repo, err := findGitHubRepo(gopkg) | |
217 | if err != nil { | |
218 | return "", err | |
219 | } | |
220 | resp, err := http.Get("https://api.github.com/repos/" + repo) | |
148 | 221 | if err != nil { |
149 | 222 | return "", err |
150 | 223 | } |
157 | 230 | |
158 | 231 | return strings.TrimSpace(rr.Description), nil |
159 | 232 | } |
233 | ||
234 | func getHomepageForGopkg(gopkg string) string { | |
235 | repo, err := findGitHubRepo(gopkg) | |
236 | if err != nil { | |
237 | return "TODO" | |
238 | } | |
239 | return "https://github.com/" + repo | |
240 | } |
1 | 1 | |
2 | 2 | import ( |
3 | 3 | "fmt" |
4 | "log" | |
5 | 4 | "os" |
6 | 5 | "os/exec" |
7 | 6 | "regexp" |
12 | 11 | |
13 | 12 | var ( |
14 | 13 | // describeRegexp parses the count and revision part of the “git describe --long” output. |
15 | describeRegexp = regexp.MustCompile(`-(\d+)-g([0-9a-f]+)\s*$`) | |
14 | describeRegexp = regexp.MustCompile(`-\d+-g([0-9a-f]+)\s*$`) | |
16 | 15 | ) |
17 | 16 | |
18 | 17 | // TODO: also support other VCS |
19 | 18 | func pkgVersionFromGit(gitdir string) (string, error) { |
20 | cmd := exec.Command("git", "describe", "--exact-match") | |
19 | cmd := exec.Command("git", "describe", "--exact-match", "--tags") | |
21 | 20 | cmd.Dir = gitdir |
22 | 21 | if tag, err := cmd.Output(); err == nil { |
23 | 22 | version := strings.TrimSpace(string(tag)) |
45 | 44 | // https://www.debian.org/doc/manuals/maint-guide/first.en.html#namever |
46 | 45 | lastTag := "0.0~" |
47 | 46 | if lastTagBytes, err := cmd.Output(); err == nil { |
48 | lastTag = strings.TrimSpace(string(lastTagBytes)) | |
49 | ||
50 | // Compare with the most recent annotated tag | |
51 | foundLightweightTag := false | |
52 | cmd = exec.Command("git", "describe", "--abbrev=0") | |
53 | cmd.Dir = gitdir | |
54 | if lastAnnotatedTagBytes, err := cmd.Output(); err == nil { | |
55 | lastAnnotatedTag := strings.TrimSpace(string(lastAnnotatedTagBytes)) | |
56 | if lastTag != lastAnnotatedTag { | |
57 | log.Printf("WARNING: Lightweight tag %q found, but the most recent annotated tag is %q\n", lastTag, lastAnnotatedTag) | |
58 | foundLightweightTag = true | |
59 | } | |
60 | } else { | |
61 | log.Printf("WARNING: Annotated tag not found, using lightweight tag %q\n", lastTag) | |
62 | foundLightweightTag = true | |
63 | } | |
64 | ||
65 | if foundLightweightTag { | |
66 | log.Printf(" Lightweight tags (created by e.g. \"git tag %s\"", lastTag) | |
67 | log.Printf(" with no flag) are problematic because, among other\n") | |
68 | log.Printf(" things, they are ignored by \"git describe\" by default.\n") | |
69 | log.Printf(" Please suggest that the upstream replaces the\n") | |
70 | log.Printf(" lightweight tags with annotated ones. See\n") | |
71 | log.Printf(" https://github.com/russross/blackfriday/issues/196\n") | |
72 | log.Printf(" for details.\n") | |
73 | log.Printf("\n") | |
74 | } | |
75 | ||
76 | lastTag += "+" | |
77 | if strings.HasPrefix(lastTag, "v") { | |
78 | lastTag = lastTag[1:] | |
79 | } | |
47 | lastTag = strings.TrimPrefix(strings.TrimSpace(string(lastTagBytes)), "v") + "+" | |
80 | 48 | } |
81 | 49 | |
82 | 50 | // This results in an output like 4.10.2-232-g9f107c8 |
99 | 67 | if submatches == nil { |
100 | 68 | return "", fmt.Errorf("git describe output %q does not match expected format", string(describeBytes)) |
101 | 69 | } |
102 | version := fmt.Sprintf("%sgit%s.%s.%s", | |
70 | version := fmt.Sprintf("%sgit%s.%s", | |
103 | 71 | lastTag, |
104 | 72 | time.Unix(lastCommitUnix, 0).UTC().Format("20060102"), |
105 | string(submatches[1]), | |
106 | string(submatches[2])) | |
73 | string(submatches[1])) | |
107 | 74 | return version, nil |
108 | 75 | } |
45 | 45 | if err != nil { |
46 | 46 | t.Fatalf("Determining package version from git failed: %v", err) |
47 | 47 | } |
48 | if want := "0.0~git20150420.0."; !strings.HasPrefix(got, want) { | |
49 | t.Logf("got %q, want %q", got, want) | |
48 | if want := "0.0~git20150420."; !strings.HasPrefix(got, want) { | |
49 | t.Errorf("got %q, want %q", got, want) | |
50 | 50 | } |
51 | 51 | |
52 | 52 | gitCmdOrFatal(t, tempdir, "tag", "-a", "v1", "-m", "release v1") |