diff options
Diffstat (limited to 'pkgtools/pkglint/files')
-rw-r--r-- | pkgtools/pkglint/files/buildlink3.go | 29 | ||||
-rw-r--r-- | pkgtools/pkglint/files/buildlink3_test.go | 65 | ||||
-rw-r--r-- | pkgtools/pkglint/files/mkshparser_test.go | 112 | ||||
-rw-r--r-- | pkgtools/pkglint/files/package.go | 2 | ||||
-rw-r--r-- | pkgtools/pkglint/files/pkgsrc.go | 4 | ||||
-rw-r--r-- | pkgtools/pkglint/files/pkgsrc_test.go | 10 | ||||
-rw-r--r-- | pkgtools/pkglint/files/shell.y | 2 | ||||
-rw-r--r-- | pkgtools/pkglint/files/vartypecheck.go | 28 | ||||
-rw-r--r-- | pkgtools/pkglint/files/vartypecheck_test.go | 24 |
9 files changed, 242 insertions, 34 deletions
diff --git a/pkgtools/pkglint/files/buildlink3.go b/pkgtools/pkglint/files/buildlink3.go index 7125f2683c4..c8ee205dd27 100644 --- a/pkgtools/pkglint/files/buildlink3.go +++ b/pkgtools/pkglint/files/buildlink3.go @@ -119,8 +119,6 @@ func (ck *Buildlink3Checker) checkUniquePkgbase(pkgbase string, mkline *MkLine) // introduces the uppercase package identifier. func (ck *Buildlink3Checker) checkSecondParagraph(mlex *MkLinesLexer) bool { pkgbase := ck.pkgbase - pkgbaseLine := ck.pkgbaseLine - m := mlex.NextRegexp(`^\.if !defined\(([^\t ]+)_BUILDLINK3_MK\)$`) if m == nil { return false @@ -136,18 +134,31 @@ func (ck *Buildlink3Checker) checkSecondParagraph(mlex *MkLinesLexer) bool { ucPkgbase := strings.ToUpper(strings.Replace(pkgbase, "-", "_", -1)) if ucPkgbase != pkgupper && !containsVarRef(pkgbase) { pkgupperLine.Errorf("Package name mismatch between multiple-inclusion guard %q (expected %q) and package name %q (from %s).", - pkgupper, ucPkgbase, pkgbase, pkgupperLine.RefTo(pkgbaseLine)) - } - if G.Pkg != nil { - if mkbase := G.Pkg.EffectivePkgbase; mkbase != "" && mkbase != pkgbase { - pkgbaseLine.Errorf("Package name mismatch between %q in this file and %q from %s.", - pkgbase, mkbase, pkgbaseLine.RefTo(G.Pkg.EffectivePkgnameLine)) - } + pkgupper, ucPkgbase, pkgbase, pkgupperLine.RefTo(ck.pkgbaseLine)) } + ck.checkPkgbaseMismatch(pkgbase) return true } +func (ck *Buildlink3Checker) checkPkgbaseMismatch(bl3base string) { + if G.Pkg == nil { + return + } + + mkbase := G.Pkg.EffectivePkgbase + if mkbase == "" || mkbase == bl3base || strings.TrimPrefix(mkbase, "lib") == bl3base { + return + } + + if hasPrefix(mkbase, bl3base) && matches(mkbase[len(bl3base):], `^\d+$`) { + return + } + + ck.pkgbaseLine.Errorf("Package name mismatch between %q in this file and %q from %s.", + bl3base, mkbase, ck.pkgbaseLine.RefTo(G.Pkg.EffectivePkgnameLine)) +} + // Third paragraph: Package information. func (ck *Buildlink3Checker) checkMainPart(mlex *MkLinesLexer) bool { pkgbase := ck.pkgbase diff --git a/pkgtools/pkglint/files/buildlink3_test.go b/pkgtools/pkglint/files/buildlink3_test.go index 17d7d86cce8..c2e50d5e122 100644 --- a/pkgtools/pkglint/files/buildlink3_test.go +++ b/pkgtools/pkglint/files/buildlink3_test.go @@ -164,6 +164,71 @@ func (s *Suite) Test_CheckLinesBuildlink3Mk__name_mismatch__Perl(c *check.C) { t.CheckOutputEmpty() } +func (s *Suite) Test_CheckLinesBuildlink3Mk__name_mismatch__lib(c *check.C) { + t := s.Init(c) + + t.SetUpPackage("converters/libiconv") + t.CreateFileLines("converters/libiconv/buildlink3.mk", + MkCvsID, + "", + "BUILDLINK_TREE+=\ticonv", + "", + ".if !defined(ICONV_BUILDLINK3_MK)", + "ICONV_BUILDLINK3_MK:=", + "", + "BUILDLINK_API_DEPENDS.iconv+=\tlibiconv>=1.0", + "BUILDLINK_ABI_DEPENDS.iconv+=\tlibiconv>=1.0", + "", + ".endif\t# ICONV_BUILDLINK3_MK", + "", + "BUILDLINK_TREE+=\t-iconv") + t.FinishSetUp() + + G.Check(t.File("converters/libiconv")) + + // Up to 2019-10-12, pkglint complained about a mismatch + // between the package name from buildlink3.mk (iconv) and the + // one from the package Makefile (libiconv). + // + // This mismatch is not important enough to warrant a global + // renaming of the buildlink3 identifier, therefore the warning + // is suppressed in cases like this. + t.CheckOutputEmpty() +} + +func (s *Suite) Test_CheckLinesBuildlink3Mk__name_mismatch__version(c *check.C) { + t := s.Init(c) + + t.SetUpPackage("editors/emacs22", + "PKGNAME=\temacs22-22.0") + t.CreateFileLines("editors/emacs22/buildlink3.mk", + MkCvsID, + "", + "BUILDLINK_TREE+=\temacs", + "", + ".if !defined(EMACS_BUILDLINK3_MK)", + "EMACS_BUILDLINK3_MK:=", + "", + "BUILDLINK_API_DEPENDS.emacs+=\temacs22>=1.0", + "BUILDLINK_ABI_DEPENDS.emacs+=\temacs22>=1.0", + "", + ".endif\t# EMACS_BUILDLINK3_MK", + "", + "BUILDLINK_TREE+=\t-emacs") + t.FinishSetUp() + + G.Check(t.File("editors/emacs22")) + + // Up to 2019-10-12, pkglint complained about a mismatch + // between the package name from buildlink3.mk (emacs) and the + // one from the package Makefile (emacs22). + // + // This mismatch is not important enough to warrant a global + // renaming of the buildlink3 identifier, therefore the warning + // is suppressed in cases like this. + t.CheckOutputEmpty() +} + func (s *Suite) Test_CheckLinesBuildlink3Mk__name_mismatch_multiple_inclusion(c *check.C) { t := s.Init(c) diff --git a/pkgtools/pkglint/files/mkshparser_test.go b/pkgtools/pkglint/files/mkshparser_test.go index be937ab42b7..3c36762250a 100644 --- a/pkgtools/pkglint/files/mkshparser_test.go +++ b/pkgtools/pkglint/files/mkshparser_test.go @@ -331,12 +331,24 @@ func (s *ShSuite) Test_ShellParser__for_clause(c *check.C) { b.Words("a", "b", "c"), b.List().AddCommand(b.SimpleCommand("echo", "$var")).AddSemicolon()))) + s.test("for var \n in ; do echo $var ; done", + b.List().AddCommand(b.For( + "var", + nil, + b.List().AddCommand(b.SimpleCommand("echo", "$var")).AddSemicolon()))) + s.test("for var in in esac ; do echo $var ; done", b.List().AddCommand(b.For( "var", b.Words("in", "esac"), b.List().AddCommand(b.SimpleCommand("echo", "$var")).AddSemicolon()))) + s.test("for var in \n do : ; done", + b.List().AddCommand(b.For( + "var", + nil, + b.List().AddCommand(b.SimpleCommand(":")).AddSemicolon()))) + // No semicolon necessary between the two "done". s.test("for i in 1; do for j in 1; do echo $$i$$j; done done", b.List().AddCommand(b.For( @@ -385,6 +397,20 @@ func (s *ShSuite) Test_ShellParser__case_clause(c *check.C) { b.Words("pattern"), b.List().AddCommand(b.SimpleCommand("case-item-action")), sepNone)))) + s.test("case selector in pattern) \n case-item-action ; esac", + b.List().AddCommand(b.Case( + b.Token("selector"), + b.CaseItem( + b.Words("pattern"), + b.List().AddCommand(b.SimpleCommand("case-item-action")), sepSemicolon)))) + + s.test("case selector in pattern) action \n esac", + b.List().AddCommand(b.Case( + b.Token("selector"), + b.CaseItem( + b.Words("pattern"), + b.List().AddCommand(b.SimpleCommand("action")), sepNone)))) + s.test("case $$expr in (if|then|else) ;; esac", b.List().AddCommand(b.Case( b.Token("$$expr"), @@ -433,6 +459,14 @@ func (s *ShSuite) Test_ShellParser__if_clause(c *check.C) { b.List().AddCommand(b.If( b.List().AddCommand(b.SimpleCommand("cond2")).AddSemicolon(), b.List().AddCommand(b.SimpleCommand("action")).AddSemicolon()))))) + + s.test("if cond1; then action1; elif cond2; then action2; else action3; fi", + b.List().AddCommand(b.If( + b.List().AddCommand(b.SimpleCommand("cond1")).AddSemicolon(), + b.List().AddCommand(b.SimpleCommand("action1")).AddSemicolon(), + b.List().AddCommand(b.SimpleCommand("cond2")).AddSemicolon(), + b.List().AddCommand(b.SimpleCommand("action2")).AddSemicolon(), + b.List().AddCommand(b.SimpleCommand("action3")).AddSemicolon()))) } func (s *ShSuite) Test_ShellParser__while_clause(c *check.C) { @@ -526,7 +560,7 @@ func (s *ShSuite) Test_ShellParser__io_redirect(c *check.C) { s.test("echo >> ${PLIST_SRC}", b.List().AddCommand(b.SimpleCommand("echo", ">>${PLIST_SRC}"))) - s.test("echo 1>output 2>>append 3>|clobber 4>&5 6<input >>append", + s.test("echo 1>output 2>>append 3>|clobber 4>&5 6<input >>append <&input <>diamond <<-here", b.List().AddCommand(&MkShCommand{Simple: &MkShSimpleCommand{ Assignments: nil, Name: b.Token("echo"), @@ -537,9 +571,12 @@ func (s *ShSuite) Test_ShellParser__io_redirect(c *check.C) { {3, ">|", b.Token("clobber")}, {4, ">&", b.Token("5")}, {6, "<", b.Token("input")}, - {-1, ">>", b.Token("append")}}}})) + {-1, ">>", b.Token("append")}, + {-1, "<&", b.Token("input")}, + {-1, "<>", b.Token("diamond")}, + {-1, "<<-", b.Token("here")}}}})) - s.test("echo 1> output 2>> append 3>| clobber 4>& 5 6< input >> append", + s.test("echo 1> output 2>> append 3>| clobber 4>& 5 6< input >> append <& input <> diamond <<- here", b.List().AddCommand(&MkShCommand{Simple: &MkShSimpleCommand{ Assignments: nil, Name: b.Token("echo"), @@ -550,7 +587,10 @@ func (s *ShSuite) Test_ShellParser__io_redirect(c *check.C) { {3, ">|", b.Token("clobber")}, {4, ">&", b.Token("5")}, {6, "<", b.Token("input")}, - {-1, ">>", b.Token("append")}}}})) + {-1, ">>", b.Token("append")}, + {-1, "<&", b.Token("input")}, + {-1, "<>", b.Token("diamond")}, + {-1, "<<-", b.Token("here")}}}})) s.test("${MAKE} print-summary-data 2>&1 > /dev/stderr", b.List().AddCommand(&MkShCommand{Simple: &MkShSimpleCommand{ @@ -560,11 +600,60 @@ func (s *ShSuite) Test_ShellParser__io_redirect(c *check.C) { Redirections: []*MkShRedirection{ {2, ">&", b.Token("1")}, {-1, ">", b.Token("/dev/stderr")}}}})) + + s.test("1> output command", + b.List().AddCommand(&MkShCommand{Simple: &MkShSimpleCommand{ + Name: b.Token("command"), + Redirections: []*MkShRedirection{ + {1, ">", b.Token("output")}}}})) + + s.test("ENV=value 1> output command", + b.List().AddCommand(&MkShCommand{Simple: &MkShSimpleCommand{ + Assignments: []*ShToken{b.Token("ENV=value")}, + Name: b.Token("command"), + Redirections: []*MkShRedirection{ + {1, ">", b.Token("output")}}}})) +} + +func (s *ShSuite) Test_ShellParser__redirect_list(c *check.C) { + b := s.init(c) + + s.test("(:) 1>out", + b.List().AddCommand( + b.Redirected( + b.Subshell(b.List().AddCommand(b.SimpleCommand(":"))), + b.Redirection(1, ">", "out")))) + + s.test("(:) 1>out 2>out", + b.List().AddCommand( + b.Redirected( + b.Subshell(b.List().AddCommand(b.SimpleCommand(":"))), + b.Redirection(1, ">", "out"), + b.Redirection(2, ">", "out")))) } func (s *ShSuite) Test_ShellParser__io_here(c *check.C) { - // In pkgsrc Makefiles, the IO here-documents cannot be used since all the text - // is joined into a single line. Therefore there are no tests here. + // In pkgsrc Makefiles, the IO here-documents cannot be used since + // all the text is joined into a single line. Therefore these test + // cases only show that pkglint can indeed not parse <<EOF + // redirections. + b := s.init(c) + + s.test("<<EOF\ntext\nEOF", + b.List(). + AddCommand(b.SimpleCommand("<<EOF")). + AddNewline(). + AddCommand(b.SimpleCommand("text")). // This is wrong. + AddNewline(). + AddCommand(b.SimpleCommand("EOF"))) // This is wrong. + + s.test("1<<EOF\ntext\nEOF", + b.List(). + AddCommand(b.SimpleCommand("1<<EOF")). + AddNewline(). + AddCommand(b.SimpleCommand("text")). // This is wrong. + AddNewline(). + AddCommand(b.SimpleCommand("EOF"))) // This is wrong. } func (s *ShSuite) init(c *check.C) *MkShBuilder { @@ -766,6 +855,9 @@ func (b *MkShBuilder) Pipeline(negated bool, cmds ...*MkShCommand) *MkShPipeline return NewMkShPipeline(negated, cmds) } +// SimpleCommand classifies the given arguments into variable assignments +// (only at the beginning of the command), the command name, arguments and +// redirections. It is not intended to cover any edge cases. func (b *MkShBuilder) SimpleCommand(words ...string) *MkShCommand { cmd := MkShSimpleCommand{} assignments := true @@ -787,6 +879,9 @@ func (b *MkShBuilder) SimpleCommand(words ...string) *MkShCommand { return &MkShCommand{Simple: &cmd} } +// If creates an if-then-elif-then-else sequence. +// The first arguments are pairs of conditions and actions. +// The remaining argument, if any, is the else action. func (b *MkShBuilder) If(condActionElse ...*MkShList) *MkShCommand { ifClause := MkShIf{} for i, part := range condActionElse { @@ -846,6 +941,11 @@ func (b *MkShBuilder) Subshell(list *MkShList) *MkShCommand { return &MkShCommand{Compound: &MkShCompoundCommand{Subshell: list}} } +func (b *MkShBuilder) Redirected(cmd *MkShCommand, redirects ...*MkShRedirection) *MkShCommand { + cmd.Redirects = redirects + return cmd +} + func (b *MkShBuilder) Token(mktext string) *ShToken { tokenizer := NewShTokenizer(dummyLine, mktext, false) token := tokenizer.ShToken() diff --git a/pkgtools/pkglint/files/package.go b/pkgtools/pkglint/files/package.go index 70591500be4..452ef1e26b7 100644 --- a/pkgtools/pkglint/files/package.go +++ b/pkgtools/pkglint/files/package.go @@ -980,6 +980,7 @@ func (pkg *Package) CheckVarorder(mklines *MkLines) { var variables = []Variable{ {"GITHUB_PROJECT", optional}, // either here or below MASTER_SITES {"GITHUB_TAG", optional}, + {"GITHUB_RELEASE", optional}, {"DISTNAME", optional}, {"PKGNAME", optional}, {"R_PKGNAME", optional}, @@ -989,6 +990,7 @@ func (pkg *Package) CheckVarorder(mklines *MkLines) { {"MASTER_SITES", many}, {"GITHUB_PROJECT", optional}, // either here or at the very top {"GITHUB_TAG", optional}, + {"GITHUB_RELEASE", optional}, {"DIST_SUBDIR", optional}, {"EXTRACT_SUFX", optional}, {"DISTFILES", many}, diff --git a/pkgtools/pkglint/files/pkgsrc.go b/pkgtools/pkglint/files/pkgsrc.go index fc3e9781f5a..afad3c26b7a 100644 --- a/pkgtools/pkglint/files/pkgsrc.go +++ b/pkgtools/pkglint/files/pkgsrc.go @@ -28,7 +28,7 @@ type Pkgsrc struct { Tools *Tools - MasterSiteURLToVar map[string]string // "https://github.com/" => "MASTER_SITE_GITHUB" + MasterSiteURLToVar map[string]string // "github.com/" => "MASTER_SITE_GITHUB" MasterSiteVarToURL map[string]string // "MASTER_SITE_GITHUB" => "https://github.com/" PkgOptions map[string]string // "x11" => "Provides X11 support" @@ -921,7 +921,7 @@ func (src *Pkgsrc) registerMasterSite(varname, url string) { if nameToURL[varname] == "" { nameToURL[varname] = url } - urlToName[url] = varname + urlToName[replaceAll(url, `^\w+://`, "")] = varname } func (src *Pkgsrc) loadPkgOptions() { diff --git a/pkgtools/pkglint/files/pkgsrc_test.go b/pkgtools/pkglint/files/pkgsrc_test.go index 34858f0f6e5..3de9622a31e 100644 --- a/pkgtools/pkglint/files/pkgsrc_test.go +++ b/pkgtools/pkglint/files/pkgsrc_test.go @@ -24,16 +24,16 @@ func (s *Suite) Test_Pkgsrc_loadMasterSites(c *check.C) { G.Pkgsrc.loadMasterSites() - t.CheckEquals(G.Pkgsrc.MasterSiteURLToVar["https://example.org/distfiles/"], "MASTER_SITE_A") - t.CheckEquals(G.Pkgsrc.MasterSiteURLToVar["https://b.example.org/distfiles/"], "MASTER_SITE_B") - t.CheckEquals(G.Pkgsrc.MasterSiteURLToVar["https://b2.example.org/distfiles/"], "MASTER_SITE_B") - t.CheckEquals(G.Pkgsrc.MasterSiteURLToVar["https://a.example.org/distfiles/"], "MASTER_SITE_A") + t.CheckEquals(G.Pkgsrc.MasterSiteURLToVar["example.org/distfiles/"], "MASTER_SITE_A") + t.CheckEquals(G.Pkgsrc.MasterSiteURLToVar["b.example.org/distfiles/"], "MASTER_SITE_B") + t.CheckEquals(G.Pkgsrc.MasterSiteURLToVar["b2.example.org/distfiles/"], "MASTER_SITE_B") + t.CheckEquals(G.Pkgsrc.MasterSiteURLToVar["a.example.org/distfiles/"], "MASTER_SITE_A") t.CheckEquals(G.Pkgsrc.MasterSiteVarToURL["MASTER_SITE_A"], "https://example.org/distfiles/") t.CheckEquals(G.Pkgsrc.MasterSiteVarToURL["MASTER_SITE_B"], "https://b.example.org/distfiles/") // Ignored entries: t.CheckEquals(G.Pkgsrc.MasterSiteURLToVar["${other}"], "") - t.CheckEquals(G.Pkgsrc.MasterSiteURLToVar["https://backup.example.org/"], "") + t.CheckEquals(G.Pkgsrc.MasterSiteURLToVar["backup.example.org/"], "") t.CheckEquals(G.Pkgsrc.MasterSiteVarToURL["MASTER_SITE_BACKUP"], "") } diff --git a/pkgtools/pkglint/files/shell.y b/pkgtools/pkglint/files/shell.y index b10fa5e7a33..c762f8160a7 100644 --- a/pkgtools/pkglint/files/shell.y +++ b/pkgtools/pkglint/files/shell.y @@ -61,7 +61,7 @@ start : program { } program : compound_list { - $$ = $1 + /* empty */ } program : /* empty */ { $$ = &MkShList{} diff --git a/pkgtools/pkglint/files/vartypecheck.go b/pkgtools/pkglint/files/vartypecheck.go index de022e35fa7..2277473afc8 100644 --- a/pkgtools/pkglint/files/vartypecheck.go +++ b/pkgtools/pkglint/files/vartypecheck.go @@ -560,18 +560,24 @@ func (cv *VartypeCheck) FetchURL() { cv.WithValue(url).URL() - for siteURL, siteName := range G.Pkgsrc.MasterSiteURLToVar { - if hasPrefix(url, siteURL) { - subdir := url[len(siteURL):] - if hasPrefix(url, "https://github.com/") { - subdir = strings.SplitAfter(subdir, "/")[0] - cv.Warnf("Please use ${%s%s:=%s} instead of %q and run %q for further instructions.", - siteName, hyphenSubst, subdir, hyphen+url[:len(siteURL)+len(subdir)], bmakeHelp("github")) - } else { - cv.Warnf("Please use ${%s%s:=%s} instead of %q.", siteName, hyphenSubst, subdir, hyphen+url) - } - return + trimURL := url[len(url)-len(replaceAll(url, `^\w+://`, "")):] + protoLen := len(url) - len(trimURL) + + for trimSiteURL, siteName := range G.Pkgsrc.MasterSiteURLToVar { + if !hasPrefix(trimURL, trimSiteURL) { + continue + } + + subdir := trimURL[len(trimSiteURL):] + if hasPrefix(trimURL, "github.com/") { + subdir = strings.SplitAfter(subdir, "/")[0] + commonPrefix := hyphen + url[:protoLen+len(trimSiteURL)+len(subdir)] + cv.Warnf("Please use ${%s%s:=%s} instead of %q and run %q for further instructions.", + siteName, hyphenSubst, subdir, commonPrefix, bmakeHelp("github")) + } else { + cv.Warnf("Please use ${%s%s:=%s} instead of %q.", siteName, hyphenSubst, subdir, hyphen+url) } + return } tokens := cv.MkLine.Tokenize(url, false) diff --git a/pkgtools/pkglint/files/vartypecheck_test.go b/pkgtools/pkglint/files/vartypecheck_test.go index 6d382ed8a69..a10f2b538fa 100644 --- a/pkgtools/pkglint/files/vartypecheck_test.go +++ b/pkgtools/pkglint/files/vartypecheck_test.go @@ -605,6 +605,30 @@ func (s *Suite) Test_VartypeCheck_FetchURL(c *check.C) { "WARN: filename.mk:71: The fetch URL \"https://example.org/pub\" should end with a slash.", "WARN: filename.mk:72: \"https://example.org/$@\" is not a valid URL.", "WARN: filename.mk:75: The fetch URL \"https://example.org/download?\" should end with a slash.") + + // The transport protocol doesn't matter for matching the MASTER_SITEs. + // See url2pkg.py, function adjust_site_from_sites_mk. + vt.Values( + "http://ftp.gnu.org/pub/gnu/bash/", + "ftp://ftp.gnu.org/pub/gnu/bash/", + "https://ftp.gnu.org/pub/gnu/bash/", + "-http://ftp.gnu.org/pub/gnu/bash/bash-5.0.tar.gz", + "-ftp://ftp.gnu.org/pub/gnu/bash/bash-5.0.tar.gz", + "-https://ftp.gnu.org/pub/gnu/bash/bash-5.0.tar.gz") + + vt.Output( + "WARN: filename.mk:81: Please use ${MASTER_SITE_GNU:=bash/} "+ + "instead of \"http://ftp.gnu.org/pub/gnu/bash/\".", + "WARN: filename.mk:82: Please use ${MASTER_SITE_GNU:=bash/} "+ + "instead of \"ftp://ftp.gnu.org/pub/gnu/bash/\".", + "WARN: filename.mk:83: Please use ${MASTER_SITE_GNU:=bash/} "+ + "instead of \"https://ftp.gnu.org/pub/gnu/bash/\".", + "WARN: filename.mk:84: Please use ${MASTER_SITE_GNU:S,^,-,:=bash/bash-5.0.tar.gz} "+ + "instead of \"-http://ftp.gnu.org/pub/gnu/bash/bash-5.0.tar.gz\".", + "WARN: filename.mk:85: Please use ${MASTER_SITE_GNU:S,^,-,:=bash/bash-5.0.tar.gz} "+ + "instead of \"-ftp://ftp.gnu.org/pub/gnu/bash/bash-5.0.tar.gz\".", + "WARN: filename.mk:86: Please use ${MASTER_SITE_GNU:S,^,-,:=bash/bash-5.0.tar.gz} "+ + "instead of \"-https://ftp.gnu.org/pub/gnu/bash/bash-5.0.tar.gz\".") } func (s *Suite) Test_VartypeCheck_FetchURL__without_package(c *check.C) { |