[BACK]Return to category.go CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / pkgsrc / pkgtools / pkglint / files

Annotation of pkgsrc/pkgtools/pkglint/files/category.go, Revision 1.22

1.16      rillig      1: package pkglint
1.1       rillig      2:
1.19      rillig      3: import (
                      4:        "fmt"
                      5:        "netbsd.org/pkglint/textproc"
                      6:        "strings"
                      7: )
1.1       rillig      8:
1.13      rillig      9: func CheckdirCategory(dir string) {
1.7       rillig     10:        if trace.Tracing {
1.13      rillig     11:                defer trace.Call1(dir)()
1.4       rillig     12:        }
1.1       rillig     13:
1.14      rillig     14:        mklines := LoadMk(dir+"/Makefile", NotEmpty|LogErrors)
                     15:        if mklines == nil {
1.1       rillig     16:                return
                     17:        }
1.4       rillig     18:
                     19:        mklines.Check()
1.1       rillig     20:
1.17      rillig     21:        mlex := NewMkLinesLexer(mklines)
                     22:        for mlex.SkipPrefix("#") {
1.1       rillig     23:        }
1.17      rillig     24:        mlex.SkipEmptyOrNote()
1.15      rillig     25:
1.20      rillig     26:        if mlex.SkipIf(func(mkline *MkLine) bool { return mkline.IsVarassign() && mkline.Varname() == "COMMENT" }) {
1.17      rillig     27:                mkline := mlex.PreviousMkLine()
1.15      rillig     28:
                     29:                lex := textproc.NewLexer(mkline.Value())
                     30:                valid := textproc.NewByteSet("--- '(),/0-9A-Za-z")
                     31:                invalid := valid.Inverse()
1.19      rillig     32:                var uni strings.Builder
1.15      rillig     33:
                     34:                for !lex.EOF() {
                     35:                        _ = lex.NextBytesSet(valid)
                     36:                        ch := lex.NextByteSet(invalid)
                     37:                        if ch != -1 {
1.19      rillig     38:                                _, _ = fmt.Fprintf(&uni, " %U", ch)
1.15      rillig     39:                        }
                     40:                }
                     41:
1.19      rillig     42:                if uni.Len() > 0 {
                     43:                        mkline.Warnf("%s contains invalid characters (%s).", mkline.Varname(), uni.String()[1:])
1.15      rillig     44:                }
1.1       rillig     45:
1.4       rillig     46:        } else {
1.17      rillig     47:                mlex.CurrentLine().Errorf("COMMENT= line expected.")
1.1       rillig     48:        }
1.17      rillig     49:        mlex.SkipEmptyOrNote()
1.1       rillig     50:
1.4       rillig     51:        type subdir struct {
1.15      rillig     52:                name string
1.20      rillig     53:                line *MkLine
1.1       rillig     54:        }
                     55:
                     56:        // And now to the most complicated part of the category Makefiles,
                     57:        // the (hopefully) sorted list of SUBDIRs. The first step is to
                     58:        // collect the SUBDIRs in the Makefile and in the file system.
                     59:
1.13      rillig     60:        fSubdirs := getSubdirs(dir)
1.2       rillig     61:        var mSubdirs []subdir
1.1       rillig     62:
1.20      rillig     63:        seen := make(map[string]*MkLine)
1.17      rillig     64:        for !mlex.EOF() {
                     65:                mkline := mlex.CurrentMkLine()
1.1       rillig     66:
1.21      rillig     67:                if (mkline.IsVarassignMaybeCommented()) && mkline.Varname() == "SUBDIR" {
1.17      rillig     68:                        mlex.Skip()
1.15      rillig     69:
                     70:                        name := mkline.Value()
                     71:                        if mkline.IsCommentedVarassign() && mkline.VarassignComment() == "" {
                     72:                                mkline.Warnf("%q commented out without giving a reason.", name)
1.1       rillig     73:                        }
                     74:
1.15      rillig     75:                        if prev := seen[name]; prev != nil {
                     76:                                mkline.Errorf("%q must only appear once, already seen in %s.", name, mkline.RefTo(prev))
1.1       rillig     77:                        }
1.15      rillig     78:                        seen[name] = mkline
1.1       rillig     79:
1.15      rillig     80:                        if len(mSubdirs) > 0 {
                     81:                                if prev := mSubdirs[len(mSubdirs)-1].name; name < prev {
                     82:                                        mkline.Warnf("%q should come before %q.", name, prev)
                     83:                                }
1.1       rillig     84:                        }
                     85:
1.15      rillig     86:                        mSubdirs = append(mSubdirs, subdir{name, mkline})
1.1       rillig     87:
                     88:                } else {
1.15      rillig     89:                        if !mkline.IsEmpty() {
                     90:                                mkline.Errorf("SUBDIR+= line or empty line expected.")
1.1       rillig     91:                        }
                     92:                        break
                     93:                }
                     94:        }
                     95:
                     96:        // To prevent unnecessary warnings about subdirectories that are
1.15      rillig     97:        // in one list but not in the other, generate the sets of
1.1       rillig     98:        // subdirs of each list.
                     99:        fCheck := make(map[string]bool)
                    100:        mCheck := make(map[string]bool)
                    101:        for _, fsub := range fSubdirs {
                    102:                fCheck[fsub] = true
                    103:        }
                    104:        for _, msub := range mSubdirs {
1.2       rillig    105:                mCheck[msub.name] = true
1.1       rillig    106:        }
                    107:
1.15      rillig    108:        fRest := fSubdirs[:]
                    109:        mRest := mSubdirs[:]
1.1       rillig    110:
1.15      rillig    111:        for len(mRest) > 0 || len(fRest) > 0 {
1.1       rillig    112:
1.15      rillig    113:                if len(fRest) > 0 && (len(mRest) == 0 || fRest[0] < mRest[0].name) {
                    114:                        fCurrent := fRest[0]
                    115:                        if !mCheck[fCurrent] {
1.20      rillig    116:                                var line *Line
1.15      rillig    117:                                if len(mRest) > 0 {
                    118:                                        line = mRest[0].line.Line
                    119:                                } else {
1.17      rillig    120:                                        line = mlex.CurrentLine()
1.15      rillig    121:                                }
1.1       rillig    122:
1.10      rillig    123:                                fix := line.Autofix()
1.15      rillig    124:                                fix.Errorf("%q exists in the file system but not in the Makefile.", fCurrent)
1.10      rillig    125:                                fix.InsertBefore("SUBDIR+=\t" + fCurrent)
                    126:                                fix.Apply()
1.2       rillig    127:                        }
1.15      rillig    128:                        fRest = fRest[1:]
1.2       rillig    129:
1.18      rillig    130:                } else if len(fRest) == 0 || mRest[0].name < fRest[0] {
1.15      rillig    131:                        if !fCheck[mRest[0].name] {
                    132:                                fix := mRest[0].line.Autofix()
                    133:                                fix.Errorf("%q exists in the Makefile but not in the file system.", mRest[0].name)
1.10      rillig    134:                                fix.Delete()
                    135:                                fix.Apply()
1.1       rillig    136:                        }
1.15      rillig    137:                        mRest = mRest[1:]
1.1       rillig    138:
1.15      rillig    139:                } else {
                    140:                        fRest = fRest[1:]
                    141:                        mRest = mRest[1:]
1.1       rillig    142:                }
                    143:        }
                    144:
                    145:        // the pkgsrc-wip category Makefile defines its own targets for
                    146:        // generating indexes and READMEs. Just skip them.
1.15      rillig    147:        if !G.Wip {
1.17      rillig    148:                mlex.SkipEmptyOrNote()
                    149:                mlex.SkipContainsOrWarn(".include \"../mk/misc/category.mk\"")
                    150:                if !mlex.EOF() {
                    151:                        mlex.CurrentLine().Errorf("The file should end here.")
1.15      rillig    152:                }
1.1       rillig    153:        }
                    154:
1.14      rillig    155:        mklines.SaveAutofixChanges()
1.1       rillig    156:
1.15      rillig    157:        if G.Opts.Recursive {
                    158:                var recurseInto []string
                    159:                for _, msub := range mSubdirs {
                    160:                        if !msub.line.IsCommentedVarassign() {
1.22    ! rillig    161:                                recurseInto = append(recurseInto, joinPath(dir, msub.name))
1.15      rillig    162:                        }
                    163:                }
                    164:                G.Todo = append(recurseInto, G.Todo...)
1.1       rillig    165:        }
                    166: }

CVSweb <webmaster@jp.NetBSD.org>