Wed Feb 5 04:09:01 2020 UTC ()
pkgtools/pkglint: update to 19.4.7

Changes since 19.4.6:

HOMEPAGE definitions that use http no longer get a warning that they
should migrate to https. Those that could be migrated have been migrated,
and the remaining homepages are not yet ready, so there's no benefit in
having this warning by default. Only in --network mode and when the https
site is indeed reachable, the warning is shown.

In long continued lines, the continuation backslash should be preceded by
a single space. Pkglint had wrongly removed that space in a few cases
before.


(rillig)
diff -r1.629 -r1.630 pkgsrc/pkgtools/pkglint/Makefile
diff -r1.2 -r1.3 pkgsrc/pkgtools/pkglint/files/homepage.go
diff -r1.1 -r1.2 pkgsrc/pkgtools/pkglint/files/homepage_test.go
diff -r1.44 -r1.45 pkgsrc/pkgtools/pkglint/files/line.go
diff -r1.39 -r1.40 pkgsrc/pkgtools/pkglint/files/logging.go
diff -r1.12 -r1.13 pkgsrc/pkgtools/pkglint/files/redundantscope_test.go
diff -r1.15 -r1.16 pkgsrc/pkgtools/pkglint/files/varalignblock.go
diff -r1.11 -r1.12 pkgsrc/pkgtools/pkglint/files/varalignblock_test.go
diff -r1.75 -r1.76 pkgsrc/pkgtools/pkglint/files/vartypecheck_test.go
diff -r1.8 -r1.9 pkgsrc/pkgtools/pkglint/files/pkgver/vercmp_test.go

cvs diff -r1.629 -r1.630 pkgsrc/pkgtools/pkglint/Makefile (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/Makefile 2020/02/02 14:19:09 1.629
+++ pkgsrc/pkgtools/pkglint/Makefile 2020/02/05 04:09:00 1.630
@@ -1,17 +1,16 @@ @@ -1,17 +1,16 @@
1# $NetBSD: Makefile,v 1.629 2020/02/02 14:19:09 bsiegert Exp $ 1# $NetBSD: Makefile,v 1.630 2020/02/05 04:09:00 rillig Exp $
2 2
3PKGNAME= pkglint-19.4.6 3PKGNAME= pkglint-19.4.7
4PKGREVISION= 1 
5CATEGORIES= pkgtools 4CATEGORIES= pkgtools
6DISTNAME= tools 5DISTNAME= tools
7MASTER_SITES= ${MASTER_SITE_GITHUB:=golang/} 6MASTER_SITES= ${MASTER_SITE_GITHUB:=golang/}
8GITHUB_PROJECT= tools 7GITHUB_PROJECT= tools
9GITHUB_TAG= 92d8274bd7b8a4c65f24bafe401a029e58392704 8GITHUB_TAG= 92d8274bd7b8a4c65f24bafe401a029e58392704
10 9
11MAINTAINER= rillig@NetBSD.org 10MAINTAINER= rillig@NetBSD.org
12HOMEPAGE= https://github.com/rillig/pkglint 11HOMEPAGE= https://github.com/rillig/pkglint
13COMMENT= Verifier for NetBSD packages 12COMMENT= Verifier for NetBSD packages
14LICENSE= 2-clause-bsd 13LICENSE= 2-clause-bsd
15CONFLICTS+= pkglint4-[0-9]* 14CONFLICTS+= pkglint4-[0-9]*
16 15
17USE_TOOLS+= pax 16USE_TOOLS+= pax

cvs diff -r1.2 -r1.3 pkgsrc/pkgtools/pkglint/files/Attic/homepage.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/homepage.go 2020/01/26 19:35:22 1.2
+++ pkgsrc/pkgtools/pkglint/files/Attic/homepage.go 2020/02/05 04:09:00 1.3
@@ -30,30 +30,35 @@ import ( @@ -30,30 +30,35 @@ import (
30// - https://sf.net/projects/$project/ 30// - https://sf.net/projects/$project/
31// - http://sf.net/projects/$project/ 31// - http://sf.net/projects/$project/
32// - https://sf.net/p/$project/ 32// - https://sf.net/p/$project/
33// - http://sf.net/p/$project/ 33// - http://sf.net/p/$project/
34// 34//
35// TODO: implement complete homepage migration for SourceForge. 35// TODO: implement complete homepage migration for SourceForge.
36// TODO: allow to suppress the automatic migration for SourceForge, 36// TODO: allow to suppress the automatic migration for SourceForge,
37// even if it is not about https vs. http. 37// even if it is not about https vs. http.
38type HomepageChecker struct { 38type HomepageChecker struct {
39 Value string 39 Value string
40 ValueNoVar string 40 ValueNoVar string
41 MkLine *MkLine 41 MkLine *MkLine
42 MkLines *MkLines 42 MkLines *MkLines
 43
 44 // Can be mocked for the tests.
 45 isReachable func(url string) YesNoUnknown
43} 46}
44 47
45func NewHomepageChecker(value string, valueNoVar string, mkline *MkLine, mklines *MkLines) *HomepageChecker { 48func NewHomepageChecker(value string, valueNoVar string, mkline *MkLine, mklines *MkLines) *HomepageChecker {
46 return &HomepageChecker{value, valueNoVar, mkline, mklines} 49 ck := HomepageChecker{value, valueNoVar, mkline, mklines, nil}
 50 ck.isReachable = ck.isReachableOnline
 51 return &ck
47} 52}
48 53
49func (ck *HomepageChecker) Check() { 54func (ck *HomepageChecker) Check() {
50 ck.checkBasedOnMasterSites() 55 ck.checkBasedOnMasterSites()
51 ck.checkFtp() 56 ck.checkFtp()
52 ck.checkHttp() 57 ck.checkHttp()
53 ck.checkBadUrls() 58 ck.checkBadUrls()
54 ck.checkReachable() 59 ck.checkReachable()
55} 60}
56 61
57func (ck *HomepageChecker) checkBasedOnMasterSites() { 62func (ck *HomepageChecker) checkBasedOnMasterSites() {
58 m, wrong, sitename, subdir := match3(ck.Value, `^(\$\{(MASTER_SITE\w+)(?::=([\w\-/]+))?\})`) 63 m, wrong, sitename, subdir := match3(ck.Value, `^(\$\{(MASTER_SITE\w+)(?::=([\w\-/]+))?\})`)
59 if !m { 64 if !m {
@@ -109,133 +114,127 @@ func (ck *HomepageChecker) checkFtp() { @@ -109,133 +114,127 @@ func (ck *HomepageChecker) checkFtp() {
109 mkline.Explain( 114 mkline.Explain(
110 "This homepage URL has probably been generated by url2pkg", 115 "This homepage URL has probably been generated by url2pkg",
111 "and not been reviewed by the package author.", 116 "and not been reviewed by the package author.",
112 "", 117 "",
113 "In most cases there exists a more welcoming URL,", 118 "In most cases there exists a more welcoming URL,",
114 "which is usually served via HTTP.") 119 "which is usually served via HTTP.")
115} 120}
116 121
117func (ck *HomepageChecker) checkHttp() { 122func (ck *HomepageChecker) checkHttp() {
118 if ck.MkLine.HasRationale("http", "https") { 123 if ck.MkLine.HasRationale("http", "https") {
119 return 124 return
120 } 125 }
121 126
122 shouldAutofix, from, to := ck.toHttps(ck.Value) 127 migrate, from, to := ck.migrate(ck.Value)
123 if from == "" { 128 if !migrate {
124 return 129 return
125 } 130 }
126 131
127 fix := ck.MkLine.Autofix() 132 fix := ck.MkLine.Autofix()
128 fix.Warnf("HOMEPAGE should migrate from %s to %s.", from, to) 133 fix.Warnf("HOMEPAGE should migrate from %s to %s.", from, to)
129 if shouldAutofix { 134 fix.Replace(from, to)
130 fix.Replace(from, to) 135 if from == "http" && to == "https" {
 136 fix.Explain(
 137 "To provide secure communication by default,",
 138 "the HOMEPAGE URL should use the https protocol if available.",
 139 "",
 140 "If the HOMEPAGE really does not support https,",
 141 "add a comment near the HOMEPAGE variable stating this clearly.")
131 } 142 }
132 fix.Explain( 
133 "To provide secure communication by default,", 
134 "the HOMEPAGE URL should use the https protocol if available.", 
135 "", 
136 "If the HOMEPAGE really does not support https,", 
137 "add a comment near the HOMEPAGE variable stating this clearly.") 
138 fix.Apply() 143 fix.Apply()
139} 144}
140 145
141// toHttps checks whether the homepage should be migrated from http to https 146// migrate checks whether the homepage should be migrated from http to https
142// and which part of the homepage URL needs to be modified for that. 147// and which part of the homepage URL needs to be modified for that.
143// 148//
144// If for some reason the https URL should not be reachable but the 149// If for some reason the https URL should not be reachable but the
145// corresponding http URL is, the homepage is changed back to http. 150// corresponding http URL is, the homepage is changed back to http.
146func (ck *HomepageChecker) toHttps(url string) (bool, string, string) { 151func (ck *HomepageChecker) migrate(url string) (bool, string, string) {
147 m, scheme, host, port := match3(url, `(https?)://([A-Za-z0-9-.]+)(:[0-9]+)?`) 152 m, scheme, host := match2(url, `(https?)://([A-Za-z0-9-.]+)(?:/|$)?`)
148 if !m { 153 if !m || containsVarRefLong(url) {
149 return false, "", "" 154 return false, "", ""
150 } 155 }
151 156
152 if ck.hasAnySuffix(host, 157 if scheme == "http" && ck.hasAnySuffix(host,
153 "www.gnustep.org", // 2020-01-18 158 "www.gnustep.org", // no https as of 2020-01-18
154 "aspell.net", // 2020-01-18 159 "aspell.net", // no https as of 2020-01-18
155 "downloads.sourceforge.net", // gets another warning already 160 "downloads.sourceforge.net", // gets another warning already
156 ".dl.sourceforge.net", // gets another warning already 161 "dl.sourceforge.net", // gets another warning already
157 ) { 162 ) {
158 return false, "", "" 163 return false, "", ""
159 } 164 }
160 165
161 if scheme == "http" && ck.hasAnySuffix(host, 166 if scheme == "http" && ck.hasAnySuffix(host,
162 "apache.org", 167 "apache.org",
163 "archive.org", 168 "archive.org",
164 "ctan.org", 169 "ctan.org",
165 "freedesktop.org", 170 "freedesktop.org",
166 "github.com", 171 "github.com",
167 "github.io", 172 "github.io",
168 "gnome.org", 173 "gnome.org",
169 "gnu.org", 174 "gnu.org",
170 "kde.org", 175 "kde.org",
171 "kldp.net", 176 "kldp.net",
172 "linuxfoundation.org", 177 "linuxfoundation.org",
173 "NetBSD.org", 178 "NetBSD.org",
174 "nongnu.org", 179 "nongnu.org",
175 "tryton.org", 180 "tryton.org",
176 "tug.org") { 181 "tug.org") {
177 return port == "", "http", "https" 182 return true, "http", "https"
178 } 183 }
179 184
180 if scheme == "http" && host == "sf.net" { 185 if host == "sf.net" {
181 return port == "", "http://sf.net", "https://sourceforge.net" 186 // sf.net redirects to sourceforge.net
 187 return true, scheme + "://sf.net", "https://sourceforge.net"
182 } 188 }
183 189
184 from := scheme 190 from := scheme
185 to := "https" 191 to := "https"
186 toReachable := unknown 
187 192
188 // SourceForge projects use either http://project.sourceforge.net or 193 // SourceForge projects use either http://project.sourceforge.net or
189 // https://project.sourceforge.io (not net). 194 // https://project.sourceforge.io (not net).
190 if m, project := match1(host, `^([\w-]+)\.(?:sf|sourceforge)\.net$`); m { 195 if m, project, domain := match2(host, `^([\w-]+)\.((?:sf|sourceforge)\.net)$`); m {
 196
191 if scheme == "http" { 197 if scheme == "http" {
192 from = scheme + "://" + host 
193 // See https://sourceforge.net/p/forge/documentation/Custom%20VHOSTs 198 // See https://sourceforge.net/p/forge/documentation/Custom%20VHOSTs
 199 from = "http://" + host
194 to = "https://" + project + ".sourceforge.io" 200 to = "https://" + project + ".sourceforge.io"
195 } else { 201 } else {
196 from = "sourceforge.net" 202 from = domain
197 to = "sourceforge.io" 203 to = "sourceforge.io"
198 204
199 // Roll back wrong https SourceForge homepages generated by: 205 // Roll back wrong https SourceForge homepages generated by:
200 // https://mail-index.netbsd.org/pkgsrc-changes/2020/01/18/msg205146.html 206 // https://mail-index.netbsd.org/pkgsrc-changes/2020/01/18/msg205146.html
201 if port == "" && G.Opts.Network { 207 _, migrated := replaceOnce(url, from, to)
202 _, migrated := replaceOnce(url, from, to) 208 if ck.isReachable(migrated) == no {
203 if ck.isReachable(migrated) == no { 209 _, httpOnly := replaceOnce(url, "https://", "http://")
204 ok, httpOnly := replaceOnce(url, "https://", "http://") 210 if ck.isReachable(httpOnly) == yes && ck.isReachable(url) == no {
205 if ok && ck.isReachable(httpOnly) == yes && ck.isReachable(url) == no { 211 return true, "https", "http"
206 from = "https" 
207 to = "http" 
208 toReachable = yes 
209 } 
210 } 212 }
211 } 213 }
212 } 214 }
213 } 215 }
214 216
215 if from == to { 217 if from == to {
216 return false, "", "" 218 return false, "", ""
217 } 219 }
218 220
219 shouldAutofix := toReachable == yes 221 _, migrated := replaceOnce(url, from, to)
220 if port == "" && G.Opts.Network && toReachable == unknown { 222 migrate := ck.isReachable(migrated)
221 _, migrated := replaceOnce(url, from, to) 223 if migrate == yes {
222 if ck.isReachable(migrated) == yes { 224 return true, from, to
223 shouldAutofix = true 
224 } else { 
225 return false, "", "" 
226 } 
227 } 225 }
228 return shouldAutofix, from, to 226
 227 return false, "", ""
229} 228}
230 229
231func (ck *HomepageChecker) checkBadUrls() { 230func (ck *HomepageChecker) checkBadUrls() {
232 m, host := match1(ck.Value, `https?://([A-Za-z0-9-.]+)`) 231 m, host := match1(ck.Value, `https?://([A-Za-z0-9-.]+)`)
233 if !m { 232 if !m {
234 return 233 return
235 } 234 }
236 235
237 if !ck.hasAnySuffix(host, 236 if !ck.hasAnySuffix(host,
238 ".dl.sourceforge.net", 237 ".dl.sourceforge.net",
239 "downloads.sourceforge.net") { 238 "downloads.sourceforge.net") {
240 return 239 return
241 } 240 }
@@ -282,27 +281,27 @@ func (ck *HomepageChecker) checkReachabl @@ -282,27 +281,27 @@ func (ck *HomepageChecker) checkReachabl
282 281
283 location, err := response.Location() 282 location, err := response.Location()
284 if err == nil { 283 if err == nil {
285 mkline.Warnf("Homepage %q redirects to %q.", url, location.String()) 284 mkline.Warnf("Homepage %q redirects to %q.", url, location.String())
286 return 285 return
287 } 286 }
288 287
289 if response.StatusCode != 200 { 288 if response.StatusCode != 200 {
290 mkline.Warnf("Homepage %q returns HTTP status %q.", url, response.Status) 289 mkline.Warnf("Homepage %q returns HTTP status %q.", url, response.Status)
291 return 290 return
292 } 291 }
293} 292}
294 293
295func (*HomepageChecker) isReachable(url string) YesNoUnknown { 294func (*HomepageChecker) isReachableOnline(url string) YesNoUnknown {
296 switch { 295 switch {
297 case !G.Opts.Network, 296 case !G.Opts.Network,
298 containsVarRefLong(url), 297 containsVarRefLong(url),
299 !matches(url, `^https?://[A-Za-z0-9-.]+(?::[0-9]+)?/[!-~]*$`): 298 !matches(url, `^https?://[A-Za-z0-9-.]+(?::[0-9]+)?/[!-~]*$`):
300 return unknown 299 return unknown
301 } 300 }
302 301
303 var client http.Client 302 var client http.Client
304 client.Timeout = 3 * time.Second 303 client.Timeout = 3 * time.Second
305 client.CheckRedirect = func(req *http.Request, via []*http.Request) error { 304 client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
306 return http.ErrUseLastResponse 305 return http.ErrUseLastResponse
307 } 306 }
308 307

cvs diff -r1.1 -r1.2 pkgsrc/pkgtools/pkglint/files/Attic/homepage_test.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/homepage_test.go 2020/01/26 17:12:36 1.1
+++ pkgsrc/pkgtools/pkglint/files/Attic/homepage_test.go 2020/02/05 04:09:00 1.2
@@ -122,88 +122,163 @@ func (s *Suite) Test_HomepageChecker_che @@ -122,88 +122,163 @@ func (s *Suite) Test_HomepageChecker_che
122 122
123 vt.Varname("HOMEPAGE") 123 vt.Varname("HOMEPAGE")
124 vt.Values( 124 vt.Values(
125 "http://www.gnustep.org/", 125 "http://www.gnustep.org/",
126 "http://www.pkgsrc.org/", 126 "http://www.pkgsrc.org/",
127 "http://project.sourceforge.net/", 127 "http://project.sourceforge.net/",
128 "http://sf.net/p/project/", 128 "http://sf.net/p/project/",
129 "http://sourceforge.net/p/project/", 129 "http://sourceforge.net/p/project/",
130 "http://example.org/ # doesn't support https", 130 "http://example.org/ # doesn't support https",
131 "http://example.org/ # only supports http", 131 "http://example.org/ # only supports http",
132 "http://asf.net/") 132 "http://asf.net/")
133 133
134 vt.Output( 134 vt.Output(
135 "WARN: filename.mk:2: HOMEPAGE should migrate from http to https.", 135 "WARN: filename.mk:4: HOMEPAGE should migrate " +
136 "WARN: filename.mk:3: HOMEPAGE should migrate "+ 136 "from http://sf.net to https://sourceforge.net.")
137 "from http://project.sourceforge.net "+ 
138 "to https://project.sourceforge.io.", 
139 "WARN: filename.mk:4: HOMEPAGE should migrate "+ 
140 "from http://sf.net to https://sourceforge.net.", 
141 "WARN: filename.mk:5: HOMEPAGE should migrate from http to https.", 
142 "WARN: filename.mk:8: HOMEPAGE should migrate from http to https.") 
143 137
144 t.SetUpCommandLine("--autofix") 138 t.SetUpCommandLine("--autofix")
145 vt.Values( 139 vt.Values(
146 "http://www.gnustep.org/", 140 "http://www.gnustep.org/",
147 "http://www.pkgsrc.org/", 141 "http://www.pkgsrc.org/",
148 "http://project.sourceforge.net/", 142 "http://project.sourceforge.net/",
149 "http://sf.net/p/project/", 143 "http://sf.net/p/project/",
150 "http://sourceforge.net/p/project/", 144 "http://sourceforge.net/p/project/",
151 "http://example.org/ # doesn't support https", 145 "http://example.org/ # doesn't support https",
152 "http://example.org/ # only supports http", 146 "http://example.org/ # only supports http",
153 "http://kde.org/", 147 "http://kde.org/",
154 "http://asf.net/") 148 "http://asf.net/")
155 149
156 // www.gnustep.org does not support https at all. 150 // www.gnustep.org does not support https at all.
157 // www.pkgsrc.org is not in the (short) list of known https domains, 151 // www.pkgsrc.org is not in the (short) list of known https domains,
158 // therefore pkglint does not dare to change it automatically. 152 // therefore pkglint does not dare to change it automatically.
159 vt.Output( 153 vt.Output(
160 "AUTOFIX: filename.mk:14: Replacing \"http://sf.net\" "+ 154 "AUTOFIX: filename.mk:14: Replacing \"http://sf.net\" "+
161 "with \"https://sourceforge.net\".", 155 "with \"https://sourceforge.net\".",
162 "AUTOFIX: filename.mk:18: Replacing \"http\" with \"https\".") 156 "AUTOFIX: filename.mk:18: Replacing \"http\" with \"https\".")
163} 157}
164 158
165func (s *Suite) Test_HomepageChecker_toHttps(c *check.C) { 159func (s *Suite) Test_HomepageChecker_migrate(c *check.C) {
166 t := s.Init(c) 160 t := s.Init(c)
167 161
168 test := func(url string, shouldAutofix bool, from, to string) { 162 reachable := map[string]YesNoUnknown{}
169 toHttps := (*HomepageChecker).toHttps 163 used := map[string]bool{}
170 actualShouldAutofix, actualFrom, actualTo := toHttps(nil, url) 164
 165 isReachable := func(url string) YesNoUnknown {
 166 if r, ok := reachable[url]; ok {
 167 used[url] = true
 168 return r
 169 }
 170 panic(url)
 171 }
 172
 173 test := func(url string, migrate bool, from, to string) {
 174 ck := NewHomepageChecker(url, url, nil, nil)
 175 ck.isReachable = isReachable
 176
 177 actualMigrate, actualFrom, actualTo := ck.migrate(url)
 178
171 t.CheckDeepEquals( 179 t.CheckDeepEquals(
172 []interface{}{actualShouldAutofix, actualFrom, actualTo}, 180 []interface{}{actualMigrate, actualFrom, actualTo},
173 []interface{}{shouldAutofix, from, to}) 181 []interface{}{migrate, from, to})
 182
 183 for key, _ := range reachable {
 184 assertf(used[key], "Reachability of %q was not used.", key)
 185 delete(reachable, key)
 186 }
174 } 187 }
175 188
176 test("http://localhost/", false, "http", "https") 189 reachable["https://localhost/"] = unknown
 190 test(
 191 "http://localhost/",
 192 false,
 193 "",
 194 "")
 195
 196 reachable["https://localhost/"] = yes
 197 test(
 198 "http://localhost/",
 199 true,
 200 "http",
 201 "https")
177 202
 203 reachable["https://project.sourceforge.io/"] = unknown
178 test( 204 test(
179 "http://project.sourceforge.net/", 205 "http://project.sourceforge.net/",
180 false, 206 false,
 207 "",
 208 "")
 209
 210 reachable["https://project.sourceforge.io/"] = yes
 211 test(
 212 "http://project.sourceforge.net/",
 213 true,
181 "http://project.sourceforge.net", 214 "http://project.sourceforge.net",
182 "https://project.sourceforge.io") 215 "https://project.sourceforge.io")
183 216
184 // To clean up the wrong autofix from 2020-01-18: 217 // To clean up the wrong autofix from 2020-01-18:
185 // https://mail-index.netbsd.org/pkgsrc-changes/2020/01/18/msg205146.html 218 // https://mail-index.netbsd.org/pkgsrc-changes/2020/01/18/msg205146.html
 219 reachable["https://project.sourceforge.io/"] = yes
186 test( 220 test(
187 "https://project.sourceforge.net/", 221 "https://project.sourceforge.net/",
188 false, 222 true,
189 "sourceforge.net", 223 "sourceforge.net",
190 "sourceforge.io") 224 "sourceforge.io")
191 225
 226 // To clean up the wrong autofix from 2020-01-18:
 227 // https://mail-index.netbsd.org/pkgsrc-changes/2020/01/18/msg205146.html
 228 //
 229 // If neither of the https URLs is reachable, the homepage
 230 // is rolled back to the http URL.
 231 reachable["https://project.sourceforge.io/"] = no
 232 reachable["http://project.sourceforge.net/"] = yes
 233 reachable["https://project.sourceforge.net/"] = no
 234 test(
 235 "https://project.sourceforge.net/",
 236 true,
 237 "https",
 238 "http")
 239
 240 // To clean up the wrong autofix from 2020-01-18:
 241 // https://mail-index.netbsd.org/pkgsrc-changes/2020/01/18/msg205146.html
 242 //
 243 // If the https URL of sourceforge.net is reachable,
 244 // it is preferred over the http URL,
 245 // even though it is not mentioned in the SourceForge documentation.
 246 reachable["https://project.sourceforge.io/"] = no
 247 reachable["http://project.sourceforge.net/"] = yes
 248 reachable["https://project.sourceforge.net/"] = yes
 249 test(
 250 "https://project.sourceforge.net/",
 251 false,
 252 "",
 253 "")
 254
 255 // To clean up the wrong autofix from 2020-01-18:
 256 // https://mail-index.netbsd.org/pkgsrc-changes/2020/01/18/msg205146.html
 257 reachable["https://project.sourceforge.io/"] = no
 258 reachable["http://project.sourceforge.net/"] = no
 259 test(
 260 "https://project.sourceforge.net/",
 261 false,
 262 "",
 263 "")
 264
 265 // Since the URL contains a variable, it cannot be resolved.
 266 // Therefore it is skipped without any HTTP request being sent.
192 test( 267 test(
193 "http://godoc.org/${GO_SRCPATH}", 268 "http://godoc.org/${GO_SRCPATH}",
194 false, 269 false,
195 "http", 270 "",
196 "https") 271 "")
197} 272}
198 273
199func (s *Suite) Test_HomepageChecker_checkBadUrls(c *check.C) { 274func (s *Suite) Test_HomepageChecker_checkBadUrls(c *check.C) {
200 t := s.Init(c) 275 t := s.Init(c)
201 vt := NewVartypeCheckTester(t, BtHomepage) 276 vt := NewVartypeCheckTester(t, BtHomepage)
202 277
203 vt.Varname("HOMEPAGE") 278 vt.Varname("HOMEPAGE")
204 vt.Values( 279 vt.Values(
205 "http://garr.dl.sourceforge.net/project/name/dir/subdir/", 280 "http://garr.dl.sourceforge.net/project/name/dir/subdir/",
206 "https://downloads.sourceforge.net/project/name/dir/subdir/") 281 "https://downloads.sourceforge.net/project/name/dir/subdir/")
207 282
208 vt.Output( 283 vt.Output(
209 "WARN: filename.mk:1: A direct download URL is not a user-friendly homepage.", 284 "WARN: filename.mk:1: A direct download URL is not a user-friendly homepage.",
@@ -249,80 +324,77 @@ func (s *Suite) Test_HomepageChecker_che @@ -249,80 +324,77 @@ func (s *Suite) Test_HomepageChecker_che
249 <-shutdown 324 <-shutdown
250 }() 325 }()
251 326
252 vt.Varname("HOMEPAGE") 327 vt.Varname("HOMEPAGE")
253 vt.Values( 328 vt.Values(
254 "http://localhost:28780/status/200", 329 "http://localhost:28780/status/200",
255 "http://localhost:28780/status/301?location=/redirect301", 330 "http://localhost:28780/status/301?location=/redirect301",
256 "http://localhost:28780/status/302?location=/redirect302", 331 "http://localhost:28780/status/302?location=/redirect302",
257 "http://localhost:28780/status/307?location=/redirect307", 332 "http://localhost:28780/status/307?location=/redirect307",
258 "http://localhost:28780/status/404", 333 "http://localhost:28780/status/404",
259 "http://localhost:28780/status/500") 334 "http://localhost:28780/status/500")
260 335
261 vt.Output( 336 vt.Output(
262 "WARN: filename.mk:1: HOMEPAGE should migrate from http to https.", 
263 "WARN: filename.mk:2: HOMEPAGE should migrate from http to https.", 
264 "WARN: filename.mk:2: Homepage "+ 337 "WARN: filename.mk:2: Homepage "+
265 "\"http://localhost:28780/status/301?location=/redirect301\" "+ 338 "\"http://localhost:28780/status/301?location=/redirect301\" "+
266 "redirects to \"http://localhost:28780/redirect301\".", 339 "redirects to \"http://localhost:28780/redirect301\".",
267 "WARN: filename.mk:3: HOMEPAGE should migrate from http to https.", 
268 "WARN: filename.mk:3: Homepage "+ 340 "WARN: filename.mk:3: Homepage "+
269 "\"http://localhost:28780/status/302?location=/redirect302\" "+ 341 "\"http://localhost:28780/status/302?location=/redirect302\" "+
270 "redirects to \"http://localhost:28780/redirect302\".", 342 "redirects to \"http://localhost:28780/redirect302\".",
271 "WARN: filename.mk:4: HOMEPAGE should migrate from http to https.", 
272 "WARN: filename.mk:4: Homepage "+ 343 "WARN: filename.mk:4: Homepage "+
273 "\"http://localhost:28780/status/307?location=/redirect307\" "+ 344 "\"http://localhost:28780/status/307?location=/redirect307\" "+
274 "redirects to \"http://localhost:28780/redirect307\".", 345 "redirects to \"http://localhost:28780/redirect307\".",
275 "WARN: filename.mk:5: HOMEPAGE should migrate from http to https.", 
276 "WARN: filename.mk:5: Homepage \"http://localhost:28780/status/404\" "+ 346 "WARN: filename.mk:5: Homepage \"http://localhost:28780/status/404\" "+
277 "returns HTTP status \"404 Not Found\".", 347 "returns HTTP status \"404 Not Found\".",
278 "WARN: filename.mk:6: HOMEPAGE should migrate from http to https.", 
279 "WARN: filename.mk:6: Homepage \"http://localhost:28780/status/500\" "+ 348 "WARN: filename.mk:6: Homepage \"http://localhost:28780/status/500\" "+
280 "returns HTTP status \"500 Internal Server Error\".") 349 "returns HTTP status \"500 Internal Server Error\".")
281 350
282 vt.Values( 351 vt.Values(
283 "http://localhost:28780/timeout") 352 "http://localhost:28780/timeout")
284 353
285 vt.Output( 354 vt.Output(
286 "WARN: filename.mk:11: HOMEPAGE should migrate from http to https.", 355 "WARN: filename.mk:11: Homepage \"http://localhost:28780/timeout\" " +
287 "WARN: filename.mk:11: Homepage \"http://localhost:28780/timeout\" "+ 
288 "cannot be checked: timeout") 356 "cannot be checked: timeout")
289 357
290 vt.Values( 358 vt.Values(
291 "http://localhost:28780/%invalid") 359 "http://localhost:28780/%invalid")
292 360
293 vt.Output( 361 vt.Output(
294 "WARN: filename.mk:21: HOMEPAGE should migrate from http to https.", 
295 "ERROR: filename.mk:21: Invalid URL \"http://localhost:28780/%invalid\".") 362 "ERROR: filename.mk:21: Invalid URL \"http://localhost:28780/%invalid\".")
296 363
297 vt.Values( 364 vt.Values(
298 "http://localhost:28781/") 365 "http://localhost:28781/")
299 366
300 // The "unknown network error" is for compatibility with Go < 1.13. 367 // The "unknown network error" is for compatibility with Go < 1.13.
301 t.CheckOutputMatches( 368 t.CheckOutputMatches(
302 "WARN: filename.mk:31: HOMEPAGE should migrate from http to https.", 369 `^WARN: filename\.mk:31: Homepage "http://localhost:28781/" ` +
303 `^WARN: filename\.mk:31: Homepage "http://localhost:28781/" `+ 
304 `cannot be checked: (connection refused|unknown network error:.*)$`) 370 `cannot be checked: (connection refused|unknown network error:.*)$`)
305 371
306 vt.Values( 372 vt.Values(
307 "https://no-such-name.example.org/") 373 "https://no-such-name.example.org/")
308 374
309 // The "unknown network error" is for compatibility with Go < 1.13. 375 // The "unknown network error" is for compatibility with Go < 1.13.
310 t.CheckOutputMatches( 376 t.CheckOutputMatches(
311 `^WARN: filename\.mk:41: Homepage "https://no-such-name.example.org/" ` + 377 `^WARN: filename\.mk:41: Homepage "https://no-such-name.example.org/" ` +
312 `cannot be checked: (name not found|unknown network error:.*)$`) 378 `cannot be checked: (name not found|unknown network error:.*)$`)
 379
 380 vt.Values(
 381 "https://!!!invalid/")
 382
 383 t.CheckOutputLines(
 384 "WARN: filename.mk:51: \"https://!!!invalid/\" is not a valid URL.")
313} 385}
314 386
315func (s *Suite) Test_HomepageChecker_isReachable(c *check.C) { 387func (s *Suite) Test_HomepageChecker_isReachableOnline(c *check.C) {
316 t := s.Init(c) 388 t := s.Init(c)
317 389
318 t.SetUpCommandLine("--network") 390 t.SetUpCommandLine("--network")
319 391
320 mux := http.NewServeMux() 392 mux := http.NewServeMux()
321 mux.HandleFunc("/status/", func(writer http.ResponseWriter, request *http.Request) { 393 mux.HandleFunc("/status/", func(writer http.ResponseWriter, request *http.Request) {
322 location := request.URL.Query().Get("location") 394 location := request.URL.Query().Get("location")
323 if location != "" { 395 if location != "" {
324 writer.Header().Set("Location", location) 396 writer.Header().Set("Location", location)
325 } 397 }
326 398
327 status, err := strconv.Atoi(request.URL.Path[len("/status/"):]) 399 status, err := strconv.Atoi(request.URL.Path[len("/status/"):])
328 assertNil(err, "") 400 assertNil(err, "")
@@ -342,27 +414,28 @@ func (s *Suite) Test_HomepageChecker_isR @@ -342,27 +414,28 @@ func (s *Suite) Test_HomepageChecker_isR
342 go func() { 414 go func() {
343 err := srv.Serve(listener) 415 err := srv.Serve(listener)
344 assertf(err == http.ErrServerClosed, "%s", err) 416 assertf(err == http.ErrServerClosed, "%s", err)
345 shutdown <- true 417 shutdown <- true
346 }() 418 }()
347 419
348 defer func() { 420 defer func() {
349 err := srv.Shutdown(context.Background()) 421 err := srv.Shutdown(context.Background())
350 assertNil(err, "") 422 assertNil(err, "")
351 <-shutdown 423 <-shutdown
352 }() 424 }()
353 425
354 test := func(url string, reachable YesNoUnknown) { 426 test := func(url string, reachable YesNoUnknown) {
355 actual := (*HomepageChecker).isReachable(nil, url) 427 ck := NewHomepageChecker(url, url, nil, nil)
 428 actual := ck.isReachableOnline(url)
356 429
357 t.CheckEquals(actual, reachable) 430 t.CheckEquals(actual, reachable)
358 } 431 }
359 432
360 test("http://localhost:28780/status/200", yes) 433 test("http://localhost:28780/status/200", yes)
361 test("http://localhost:28780/status/301?location=/", no) 434 test("http://localhost:28780/status/301?location=/", no)
362 test("http://localhost:28780/status/404", no) 435 test("http://localhost:28780/status/404", no)
363 test("http://localhost:28780/status/500", no) 436 test("http://localhost:28780/status/500", no)
364 test("http://localhost:28780/timeout", no) 437 test("http://localhost:28780/timeout", no)
365 test("http://localhost:28780/ok/${VAR}", unknown) 438 test("http://localhost:28780/ok/${VAR}", unknown)
366 test("http://localhost:28780/ invalid", unknown) 439 test("http://localhost:28780/ invalid", unknown)
367 test("http://localhost:28780/%invalid", no) 440 test("http://localhost:28780/%invalid", no)
368 test("http://localhost:28781/", no) 441 test("http://localhost:28781/", no)

cvs diff -r1.44 -r1.45 pkgsrc/pkgtools/pkglint/files/Attic/line.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/line.go 2020/01/04 19:53:14 1.44
+++ pkgsrc/pkgtools/pkglint/files/Attic/line.go 2020/02/05 04:09:00 1.45
@@ -134,26 +134,29 @@ func (line *Line) RelLocation(other Loca @@ -134,26 +134,29 @@ func (line *Line) RelLocation(other Loca
134func (line *Line) Rel(other CurrPath) RelPath { 134func (line *Line) Rel(other CurrPath) RelPath {
135 return G.Pkgsrc.Relpath(line.Filename.DirNoClean(), other) 135 return G.Pkgsrc.Relpath(line.Filename.DirNoClean(), other)
136} 136}
137 137
138func (line *Line) IsMultiline() bool { 138func (line *Line) IsMultiline() bool {
139 return line.firstLine > 0 && line.firstLine != line.lastLine 139 return line.firstLine > 0 && line.firstLine != line.lastLine
140} 140}
141 141
142func (line *Line) IsCvsID(prefixRe regex.Pattern) (found bool, expanded bool) { 142func (line *Line) IsCvsID(prefixRe regex.Pattern) (found bool, expanded bool) {
143 m, exp := match1(line.Text, `^`+prefixRe+`\$`+`NetBSD(:[^\$]+)?\$$`) 143 m, exp := match1(line.Text, `^`+prefixRe+`\$`+`NetBSD(:[^\$]+)?\$$`)
144 return m, exp != "" 144 return m, exp != ""
145} 145}
146 146
 147// FIXME: By definition there cannot be fatal diagnostics.
 148// Having these was a misconception from the beginning,
 149// and they must be re-classified as fatal technical errors.
147func (line *Line) Fatalf(format string, args ...interface{}) { 150func (line *Line) Fatalf(format string, args ...interface{}) {
148 if trace.Tracing { 151 if trace.Tracing {
149 trace.Stepf("Fatalf: %q, %v", format, args) 152 trace.Stepf("Fatalf: %q, %v", format, args)
150 } 153 }
151 G.Logger.Diag(line, Fatal, format, args...) 154 G.Logger.Diag(line, Fatal, format, args...)
152} 155}
153 156
154func (line *Line) Errorf(format string, args ...interface{}) { 157func (line *Line) Errorf(format string, args ...interface{}) {
155 G.Logger.Diag(line, Error, format, args...) 158 G.Logger.Diag(line, Error, format, args...)
156} 159}
157 160
158func (line *Line) Warnf(format string, args ...interface{}) { 161func (line *Line) Warnf(format string, args ...interface{}) {
159 G.Logger.Diag(line, Warn, format, args...) 162 G.Logger.Diag(line, Warn, format, args...)

cvs diff -r1.39 -r1.40 pkgsrc/pkgtools/pkglint/files/Attic/logging.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/logging.go 2020/01/26 17:12:36 1.39
+++ pkgsrc/pkgtools/pkglint/files/Attic/logging.go 2020/02/05 04:09:00 1.40
@@ -48,26 +48,29 @@ type LoggerOpts struct { @@ -48,26 +48,29 @@ type LoggerOpts struct {
48 ShowSource, 48 ShowSource,
49 GccOutput, 49 GccOutput,
50 Quiet bool 50 Quiet bool
51 51
52 Only []string 52 Only []string
53} 53}
54 54
55type LogLevel struct { 55type LogLevel struct {
56 TraditionalName string 56 TraditionalName string
57 GccName string 57 GccName string
58} 58}
59 59
60var ( 60var (
 61 // FIXME: By definition there cannot be fatal diagnostics.
 62 // Having these was a misconception from the beginning,
 63 // and they must be re-classified as fatal technical errors.
61 Fatal = &LogLevel{"FATAL", "fatal"} 64 Fatal = &LogLevel{"FATAL", "fatal"}
62 Error = &LogLevel{"ERROR", "error"} 65 Error = &LogLevel{"ERROR", "error"}
63 Warn = &LogLevel{"WARN", "warning"} 66 Warn = &LogLevel{"WARN", "warning"}
64 Note = &LogLevel{"NOTE", "note"} 67 Note = &LogLevel{"NOTE", "note"}
65 AutofixLogLevel = &LogLevel{"AUTOFIX", "autofix"} 68 AutofixLogLevel = &LogLevel{"AUTOFIX", "autofix"}
66) 69)
67 70
68// Explain outputs an explanation for the preceding diagnostic 71// Explain outputs an explanation for the preceding diagnostic
69// if the --explain option is given. Otherwise it just records 72// if the --explain option is given. Otherwise it just records
70// that an explanation is available. 73// that an explanation is available.
71func (l *Logger) Explain(explanation ...string) { 74func (l *Logger) Explain(explanation ...string) {
72 if l.suppressExpl { 75 if l.suppressExpl {
73 return 76 return

cvs diff -r1.12 -r1.13 pkgsrc/pkgtools/pkglint/files/Attic/redundantscope_test.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/redundantscope_test.go 2019/12/30 16:27:13 1.12
+++ pkgsrc/pkgtools/pkglint/files/Attic/redundantscope_test.go 2020/02/05 04:09:00 1.13
@@ -1435,30 +1435,27 @@ func (s *Suite) Test_RedundantScope__is_ @@ -1435,30 +1435,27 @@ func (s *Suite) Test_RedundantScope__is_
1435 "PKG_OPTIONS=\t# empty", 1435 "PKG_OPTIONS=\t# empty",
1436 "PKG_OPTIONS=\toverwritten") 1436 "PKG_OPTIONS=\toverwritten")
1437 t.CreateFileLines("options.mk", 1437 t.CreateFileLines("options.mk",
1438 "OUTSIDE:=\t# empty", 1438 "OUTSIDE:=\t# empty",
1439 "OUTSIDE=\t# empty", 1439 "OUTSIDE=\t# empty",
1440 "OUTSIDE=\toverwritten", 1440 "OUTSIDE=\toverwritten",
1441 ".include \"mk/bsd.options.mk\"") 1441 ".include \"mk/bsd.options.mk\"")
1442 1442
1443 test := func(diagnostics ...string) { 1443 test := func(diagnostics ...string) {
1444 mklines := t.LoadMkInclude("options.mk") 1444 mklines := t.LoadMkInclude("options.mk")
1445 scope := NewRedundantScope() 1445 scope := NewRedundantScope()
1446 scope.IsRelevant = func(mkline *MkLine) bool { 1446 scope.IsRelevant = func(mkline *MkLine) bool {
1447 // See checkfilePackageMakefile. 1447 // See checkfilePackageMakefile.
1448 if !G.Infrastructure && !G.Opts.CheckGlobal { 1448 return G.Opts.CheckGlobal || !G.Pkgsrc.IsInfra(mkline.Filename)
1449 return !G.Pkgsrc.IsInfra(mkline.Filename) 
1450 } 
1451 return true 
1452 } 1449 }
1453 1450
1454 scope.Check(mklines) 1451 scope.Check(mklines)
1455 1452
1456 // No note about the redundant variable assignment in bsd.options.mk 1453 // No note about the redundant variable assignment in bsd.options.mk
1457 // because it is part of the infrastructure, which is filtered out. 1454 // because it is part of the infrastructure, which is filtered out.
1458 t.CheckOutput(diagnostics) 1455 t.CheckOutput(diagnostics)
1459 } 1456 }
1460 1457
1461 test( 1458 test(
1462 "NOTE: ~/options.mk:2: "+ 1459 "NOTE: ~/options.mk:2: "+
1463 "Definition of OUTSIDE is redundant because of line 1.", 1460 "Definition of OUTSIDE is redundant because of line 1.",
1464 "WARN: ~/options.mk:2: "+ 1461 "WARN: ~/options.mk:2: "+

cvs diff -r1.15 -r1.16 pkgsrc/pkgtools/pkglint/files/Attic/varalignblock.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/varalignblock.go 2020/01/04 19:53:14 1.15
+++ pkgsrc/pkgtools/pkglint/files/Attic/varalignblock.go 2020/02/05 04:09:00 1.16
@@ -645,26 +645,29 @@ func (info *varalignLine) alignContinuat @@ -645,26 +645,29 @@ func (info *varalignLine) alignContinuat
645 } 645 }
646 if column == 72 || column == rightMarginColumn || column <= valueColumn { 646 if column == 72 || column == rightMarginColumn || column <= valueColumn {
647 return 647 return
648 } 648 }
649 649
650 newSpace := " " 650 newSpace := " "
651 fix := info.fixer.Autofix() 651 fix := info.fixer.Autofix()
652 if oldSpace == "" || rightMarginColumn == 0 { 652 if oldSpace == "" || rightMarginColumn == 0 {
653 fix.Notef("The continuation backslash should be preceded by a single space or tab.") 653 fix.Notef("The continuation backslash should be preceded by a single space or tab.")
654 } else if info.isTooLongFor(valueColumn) { 654 } else if info.isTooLongFor(valueColumn) {
655 fix.Notef("The continuation backslash should be preceded by a single space.") 655 fix.Notef("The continuation backslash should be preceded by a single space.")
656 } else { 656 } else {
657 newSpace = alignmentToWidths(info.uptoValueWidth(), rightMarginColumn) 657 newSpace = alignmentToWidths(info.uptoValueWidth(), rightMarginColumn)
 658 if newSpace == "" {
 659 newSpace = " "
 660 }
658 fix.Notef( 661 fix.Notef(
659 "The continuation backslash should be in column %d, not %d.", 662 "The continuation backslash should be in column %d, not %d.",
660 rightMarginColumn+1, column+1) 663 rightMarginColumn+1, column+1)
661 } 664 }
662 index := info.continuationIndex() - len(oldSpace) 665 index := info.continuationIndex() - len(oldSpace)
663 fix.ReplaceAt(info.rawIndex, index, oldSpace, newSpace) 666 fix.ReplaceAt(info.rawIndex, index, oldSpace, newSpace)
664 info.setSpaceBeforeContinuation(newSpace) 667 info.setSpaceBeforeContinuation(newSpace)
665 fix.Apply() 668 fix.Apply()
666} 669}
667 670
668func (info *varalignLine) replaceSpaceBeforeValue(fix *Autofix, newSpace string) { 671func (info *varalignLine) replaceSpaceBeforeValue(fix *Autofix, newSpace string) {
669 index := info.spaceBeforeValueIndex() 672 index := info.spaceBeforeValueIndex()
670 fix.ReplaceAt(info.rawIndex, index, info.spaceBeforeValue, newSpace) 673 fix.ReplaceAt(info.rawIndex, index, info.spaceBeforeValue, newSpace)
@@ -842,19 +845,22 @@ func (p *varalignParts) isCanonicalIniti @@ -842,19 +845,22 @@ func (p *varalignParts) isCanonicalIniti
842 } 845 }
843 846
844 return strings.TrimLeft(space, "\t") == "" 847 return strings.TrimLeft(space, "\t") == ""
845} 848}
846 849
847// isCanonicalFollow returns whether the space before the value has its 850// isCanonicalFollow returns whether the space before the value has its
848// canonical form, which is at least one tab, followed by up to 7 spaces. 851// canonical form, which is at least one tab, followed by up to 7 spaces.
849func (p *varalignParts) isCanonicalFollow() bool { 852func (p *varalignParts) isCanonicalFollow() bool {
850 column := p.valueColumn() 853 column := p.valueColumn()
851 return column >= 8 && p.spaceBeforeValue == indent(column) 854 return column >= 8 && p.spaceBeforeValue == indent(column)
852} 855}
853 856
854func (p *varalignParts) isTooLongFor(valueColumn int) bool { 857func (p *varalignParts) isTooLongFor(valueColumn int) bool {
 858 // FIXME: As of 2020-01-27, this method is called from
 859 // Test_VaralignBlock__right_margin with valueColumn == 0,
 860 // which doesn't make sense. It should at least be 8.
855 column := tabWidthAppend(valueColumn, p.value) 861 column := tabWidthAppend(valueColumn, p.value)
856 if p.isContinuation() { 862 if p.isContinuation() {
857 column += 2 863 column += 2
858 } 864 }
859 return column > 73 865 return column > 73
860} 866}

cvs diff -r1.11 -r1.12 pkgsrc/pkgtools/pkglint/files/Attic/varalignblock_test.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/varalignblock_test.go 2020/01/04 19:53:14 1.11
+++ pkgsrc/pkgtools/pkglint/files/Attic/varalignblock_test.go 2020/02/05 04:09:00 1.12
@@ -208,27 +208,27 @@ func (vt *VaralignTester) checkTestName( @@ -208,27 +208,27 @@ func (vt *VaralignTester) checkTestName(
208 m, name, widthStr := match2(part, `^([a-z]+)(\d*)$`) 208 m, name, widthStr := match2(part, `^([a-z]+)(\d*)$`)
209 assert(m) 209 assert(m)
210 width, err := strconv.Atoi(widthStr) 210 width, err := strconv.Atoi(widthStr)
211 if err != nil || width == 0 { 211 if err != nil || width == 0 {
212 width = 0 212 width = 0
213 if i < len(actual) && name == actual[i].name { 213 if i < len(actual) && name == actual[i].name {
214 width = actual[i].width 214 width = actual[i].width
215 } 215 }
216 } 216 }
217 expected = append(expected, descriptor{name, width}) 217 expected = append(expected, descriptor{name, width})
218 } 218 }
219 219
220 vt.tester.CheckDeepEquals(descriptorsString(actual), descriptorsString(expected)) 220 vt.tester.CheckDeepEquals(descriptorsString(actual), descriptorsString(expected))
221 vt.tester.CheckDeepEquals(actual, expected) 221 vt.tester.CheckDeepEquals(expected, actual)
222} 222}
223 223
224func (s *Suite) Test_VaralignBlock__var_none_value(c *check.C) { 224func (s *Suite) Test_VaralignBlock__var_none_value(c *check.C) {
225 vt := NewVaralignTester(s, c) 225 vt := NewVaralignTester(s, c)
226 vt.Input( 226 vt.Input(
227 "VVVVVVVVVVVVVVVVVVV=value") 227 "VVVVVVVVVVVVVVVVVVV=value")
228 vt.Internals( 228 vt.Internals(
229 "20 20") 229 "20 20")
230 vt.Diagnostics( 230 vt.Diagnostics(
231 "NOTE: Makefile:1: This variable value should be aligned to column 25 instead of 21.") 231 "NOTE: Makefile:1: This variable value should be aligned to column 25 instead of 21.")
232 vt.Autofixes( 232 vt.Autofixes(
233 "AUTOFIX: Makefile:1: Replacing \"\" with \"\\t\".") 233 "AUTOFIX: Makefile:1: Replacing \"\" with \"\\t\".")
234 vt.Fixed( 234 vt.Fixed(
@@ -2053,26 +2053,49 @@ func (s *Suite) Test_VaralignBlock__var_ @@ -2053,26 +2053,49 @@ func (s *Suite) Test_VaralignBlock__var_
2053 "indented with \"\\t\\t\".", 2053 "indented with \"\\t\\t\".",
2054 "NOTE: Makefile:3: This continuation line should be "+ 2054 "NOTE: Makefile:3: This continuation line should be "+
2055 "indented with \"\\t\\t\".") 2055 "indented with \"\\t\\t\".")
2056 vt.Autofixes( 2056 vt.Autofixes(
2057 "AUTOFIX: Makefile:2: Replacing \"\\t\" with \"\\t\\t\".", 2057 "AUTOFIX: Makefile:2: Replacing \"\\t\" with \"\\t\\t\".",
2058 "AUTOFIX: Makefile:3: Replacing \"\\t\" with \"\\t\\t\".") 2058 "AUTOFIX: Makefile:3: Replacing \"\\t\" with \"\\t\\t\".")
2059 vt.Fixed( 2059 vt.Fixed(
2060 "PROGFILES= 67890 234567890 234567890 234567890 234567890 2 \\", 2060 "PROGFILES= 67890 234567890 234567890 234567890 234567890 2 \\",
2061 " 890 234567890 234567890 234567890 234567890 234567890 234567890 \\", 2061 " 890 234567890 234567890 234567890 234567890 234567890 234567890 \\",
2062 " value") 2062 " value")
2063 vt.Run() 2063 vt.Run()
2064} 2064}
2065 2065
 2066// Up to 2020-01-27, pkglint removed all spaces before the backslash,
 2067// which was against the rule of having at least one space.
 2068func (s *Suite) Test_VaralignBlock__right_margin(c *check.C) {
 2069 vt := NewVaralignTester(s, c)
 2070 vt.Input(
 2071 "CONFIGURE_ARGS+=\t\\",
 2072 "\t.....................................................................79\t\\",
 2073 "\t............................................................70 \t\t\\",
 2074 "\t........................................................66")
 2075 vt.Diagnostics(
 2076 "NOTE: Makefile:2: The continuation backslash should be in column 73, not 81.",
 2077 "NOTE: Makefile:3: The continuation backslash should be in column 73, not 81.")
 2078 vt.Autofixes(
 2079 "AUTOFIX: Makefile:2: Replacing \"\\t\" with \" \".",
 2080 "AUTOFIX: Makefile:3: Replacing \" \\t\\t\" with \"\\t\".")
 2081 vt.Fixed(
 2082 "CONFIGURE_ARGS+= \\",
 2083 " .....................................................................79 \\",
 2084 " ............................................................70 \\",
 2085 " ........................................................66")
 2086 vt.Run()
 2087}
 2088
2066// Up to 2018-01-27, it could happen that some source code was logged 2089// Up to 2018-01-27, it could happen that some source code was logged
2067// without a corresponding diagnostic. This was unintended and confusing. 2090// without a corresponding diagnostic. This was unintended and confusing.
2068func (s *Suite) Test_VaralignBlock__fix_without_diagnostic(c *check.C) { 2091func (s *Suite) Test_VaralignBlock__fix_without_diagnostic(c *check.C) {
2069 vt := NewVaralignTester(s, c) 2092 vt := NewVaralignTester(s, c)
2070 vt.Input( 2093 vt.Input(
2071 "MESSAGE_SUBST+=\t\tRUBY_DISTNAME=${RUBY_DISTNAME}", 2094 "MESSAGE_SUBST+=\t\tRUBY_DISTNAME=${RUBY_DISTNAME}",
2072 "PLIST_SUBST+=\t\tRUBY_SHLIBVER=${RUBY_SHLIBVER:Q} \\", 2095 "PLIST_SUBST+=\t\tRUBY_SHLIBVER=${RUBY_SHLIBVER:Q} \\",
2073 "\t\t\tRUBY_SHLIBMAJOR=${RUBY_SHLIBMAJOR:Q} \\", 2096 "\t\t\tRUBY_SHLIBMAJOR=${RUBY_SHLIBMAJOR:Q} \\",
2074 "\t\t\tRUBY_NOSHLIBMAJOR=${RUBY_NOSHLIBMAJOR} \\", 2097 "\t\t\tRUBY_NOSHLIBMAJOR=${RUBY_NOSHLIBMAJOR} \\",
2075 "\t\t\tRUBY_NAME=${RUBY_NAME:Q}") 2098 "\t\t\tRUBY_NAME=${RUBY_NAME:Q}")
2076 vt.Internals( 2099 vt.Internals(
2077 "15 24", 2100 "15 24",
2078 "13 24 57", 2101 "13 24 57",

cvs diff -r1.75 -r1.76 pkgsrc/pkgtools/pkglint/files/Attic/vartypecheck_test.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/vartypecheck_test.go 2020/01/26 17:12:36 1.75
+++ pkgsrc/pkgtools/pkglint/files/Attic/vartypecheck_test.go 2020/02/05 04:09:00 1.76
@@ -907,27 +907,26 @@ func (s *Suite) Test_VartypeCheck_GccReq @@ -907,27 +907,26 @@ func (s *Suite) Test_VartypeCheck_GccReq
907} 907}
908 908
909func (s *Suite) Test_VartypeCheck_Homepage(c *check.C) { 909func (s *Suite) Test_VartypeCheck_Homepage(c *check.C) {
910 t := s.Init(c) 910 t := s.Init(c)
911 vt := NewVartypeCheckTester(t, BtHomepage) 911 vt := NewVartypeCheckTester(t, BtHomepage)
912 912
913 vt.Varname("HOMEPAGE") 913 vt.Varname("HOMEPAGE")
914 vt.Values( 914 vt.Values(
915 "http://www.pkgsrc.org/", 915 "http://www.pkgsrc.org/",
916 "https://www.pkgsrc.org/", 916 "https://www.pkgsrc.org/",
917 "${MASTER_SITES}") 917 "${MASTER_SITES}")
918 918
919 vt.Output( 919 vt.Output(
920 "WARN: filename.mk:1: HOMEPAGE should migrate from http to https.", 
921 "WARN: filename.mk:3: HOMEPAGE should not be defined in terms of MASTER_SITEs.") 920 "WARN: filename.mk:3: HOMEPAGE should not be defined in terms of MASTER_SITEs.")
922 921
923 // For more tests, see HomepageChecker. 922 // For more tests, see HomepageChecker.
924} 923}
925 924
926func (s *Suite) Test_VartypeCheck_IdentifierDirect(c *check.C) { 925func (s *Suite) Test_VartypeCheck_IdentifierDirect(c *check.C) {
927 t := s.Init(c) 926 t := s.Init(c)
928 vt := NewVartypeCheckTester(t, BtIdentifierDirect) 927 vt := NewVartypeCheckTester(t, BtIdentifierDirect)
929 928
930 vt.Varname("PKGBASE") 929 vt.Varname("PKGBASE")
931 vt.Values( 930 vt.Values(
932 "${OTHER_VAR}", 931 "${OTHER_VAR}",
933 "identifiers cannot contain spaces", 932 "identifiers cannot contain spaces",

cvs diff -r1.8 -r1.9 pkgsrc/pkgtools/pkglint/files/pkgver/Attic/vercmp_test.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/pkgver/Attic/vercmp_test.go 2019/11/27 22:10:07 1.8
+++ pkgsrc/pkgtools/pkglint/files/pkgver/Attic/vercmp_test.go 2020/02/05 04:09:01 1.9
@@ -75,26 +75,42 @@ func (s *Suite) Test_newVersion(c *check @@ -75,26 +75,42 @@ func (s *Suite) Test_newVersion(c *check
75 &version{[]int{1, 0, 0, -3, 3}, 0}) 75 &version{[]int{1, 0, 0, -3, 3}, 0})
76 c.Check(newVersion("1_0alpha3"), check.DeepEquals, 76 c.Check(newVersion("1_0alpha3"), check.DeepEquals,
77 &version{[]int{1, 0, 0, -3, 3}, 0}) 77 &version{[]int{1, 0, 0, -3, 3}, 0})
78 c.Check(newVersion("2.5beta"), check.DeepEquals, 78 c.Check(newVersion("2.5beta"), check.DeepEquals,
79 &version{[]int{2, 0, 5, -2}, 0}) 79 &version{[]int{2, 0, 5, -2}, 0})
80 c.Check(newVersion("20151110"), check.DeepEquals, 80 c.Check(newVersion("20151110"), check.DeepEquals,
81 &version{[]int{20151110}, 0}) 81 &version{[]int{20151110}, 0})
82 c.Check(newVersion("0"), check.DeepEquals, 82 c.Check(newVersion("0"), check.DeepEquals,
83 &version{[]int{0}, 0}) 83 &version{[]int{0}, 0})
84 c.Check(newVersion("nb1"), check.DeepEquals, 84 c.Check(newVersion("nb1"), check.DeepEquals,
85 &version{nil, 1}) 85 &version{nil, 1})
86 c.Check(newVersion("1.0.1a"), check.DeepEquals, 86 c.Check(newVersion("1.0.1a"), check.DeepEquals,
87 &version{[]int{1, 0, 0, 0, 1, 1}, 0}) 87 &version{[]int{1, 0, 0, 0, 1, 1}, 0})
 88 c.Check(newVersion("1.1.1dnb2"), check.DeepEquals,
 89 &version{[]int{1, 0, 1, 0, 1, 4}, 2})
88 c.Check(newVersion("1.0.1z"), check.DeepEquals, 90 c.Check(newVersion("1.0.1z"), check.DeepEquals,
89 &version{[]int{1, 0, 0, 0, 1, 26}, 0}) 91 &version{[]int{1, 0, 0, 0, 1, 26}, 0})
90 c.Check(newVersion("0pre20160620"), check.DeepEquals, 92 c.Check(newVersion("0pre20160620"), check.DeepEquals,
91 &version{[]int{0, -1, 20160620}, 0}) 93 &version{[]int{0, -1, 20160620}, 0})
92 c.Check(newVersion("3.5.DEV1710"), check.DeepEquals, 94 c.Check(newVersion("3.5.DEV1710"), check.DeepEquals,
93 &version{[]int{3, 0, 5, 0, 4, 5, 22, 1710}, 0}) 95 &version{[]int{3, 0, 5, 0, 4, 5, 22, 1710}, 0})
 96
 97 // In the following edge case, the "nb" and "beta" overlap.
 98 // All the digits after the "nb" (which in this case are none at all)
 99 // end up in the nb version part, and parsing continues with the next
 100 // letter.
 101 //
 102 // Luckily this will not happen in practice since most version numbers
 103 // are completely numeric, and those that aren't might have suffixes
 104 // like "alpha", "beta", "public beta", "GA" (general availability),
 105 // "final", "snapshot". The word "nonbeta" is purely hypothetical, and
 106 // I didn't find any other word that would contain "nbeta". Commit
 107 // hashes are also safe since their hex encoding cannot contain "n".
 108 c.Check(newVersion("1.0nonbeta"), check.DeepEquals,
 109 &version{[]int{1, 0, 0, 14, 15, 5, 20, 1}, 0})
94} 110}
95 111
96func (s *Suite) Test__qa(c *check.C) { 112func (s *Suite) Test__qa(c *check.C) {
97 ck := intqa.NewQAChecker(c.Errorf) 113 ck := intqa.NewQAChecker(c.Errorf)
98 ck.Configure("*", "*", "*", -intqa.EMissingTest) 114 ck.Configure("*", "*", "*", -intqa.EMissingTest)
99 ck.Check() 115 ck.Check()
100} 116}