diff options
| -rw-r--r-- | README.md | 45 | ||||
| -rw-r--r-- | file.go | 25 | ||||
| -rw-r--r-- | report.go | 61 | ||||
| -rw-r--r-- | report_test.go | 29 | ||||
| -rw-r--r-- | spdxconv_test.go | 10 | ||||
| -rw-r--r-- | testdata/loadReport/ok/spdxconv.report | 9 |
6 files changed, 107 insertions, 72 deletions
@@ -135,7 +135,8 @@ Each line in the report file is formatted using CSV and has several columns separated by comma, ``` -path "," license_id "," year "," copyright_id +path "," license_id "," idx_license_id "," year "," copyright_id "," + idx_copyright_id "," comment_prefix "," comment_suffix ``` where each column has the following values, @@ -143,17 +144,14 @@ where each column has the following values, ``` path = { unicode_char } -license_id = "default" | exist_at_index | license_text - exist_at_index = "exists:" decimal_digit - license_text = 1 * { unicode_char } +license_id = "default" | "exist" | "match" +idx_license_id = 1 * decimal_digit year = "unknown" | 4 * decimal_digit | 4 * decimal_digit "-" 4*decimal_digit -copyright_id = "default" | exist_at_index | copyright_text - copyright_text = author contact - author = 1 * { unicode_char } - contact = "<" 1 * { unicode_char } ">" +copyright_id = "default" | "exist" | "match" +idx_copyright_id = 1 * decimal_digit ``` The `path` column define the path to the file that will be processed by @@ -164,11 +162,14 @@ The value either, - default - insert new identifier and using the default license_identifier value from configuration. -- exist:index - the SPDX-License-Identifier already exist in the file at - line `index`. - Positive index means from the top, and negative means from the bottom. -- license_text - the value of license_identifier from one of match-license - section. +- exist - the SPDX-License-Identifier already exist in file. +- match - one of the pattern in match-license found in file at line number + set in `idx_license_id`. + +The `idx_license_id` define the line number in file where license_id is +"exist" or "match". +Positive value means match found at the top, and negative value means match +found at the bottom. The `year` column define the copyright year for the work. The value is either, @@ -182,11 +183,17 @@ The value is either, - default - insert new identifier using the default copyright_text value from configuration. -- exist:index - the SPDX-FileCopyrightText already exist in the file at - line `index`. - Positive index means from the top, and negative means from the bottom. -- copyright_text - the value of author and contact regex match group from - one of the match-copyright pattern. +- exist - the SPDX-FileCopyrightText already exist in file. +- match - one of the pattern in the match-copyright found in file at line + number set in `idx_copyright_id`. + +The `idx_copyright_id` define the line number in file where copyright_id is +"exist" or "match". +Positive value means match found at the top, and negative value means match +found at the bottom. + +The `comment_prefix` and `comment_suffix` contains the prefix and suffix +used as comment in the file. ### spdxconv.report file groups @@ -224,7 +231,7 @@ configuration and rerun the scan command for the next cycle. ## apply command The apply command read the "spdxconv.report" and apply the license and -copyright as stated on each line in the report. +copyright in the file as stated on each line in the report. ## References @@ -17,6 +17,7 @@ import ( const ( valDefault = `default` // Use the default value from configuration. valExist = `exist` // The license/copyright exist in the file. + valMatch = `match` // One of the pattern in match-xxx found in file. valUnknown = `unknown` ) @@ -144,7 +145,7 @@ func (f *file) scanLicenseID(conv *SPDXConv) { for x, line := range f.topLines { if reLicenseID.Match(line) { f.idxLicenseID = x - f.licenseID = fmt.Sprintf("%s:%d", valExist, f.idxLicenseID) + f.licenseID = valExist if f.hasSheBang && x == 1 { return } @@ -154,18 +155,20 @@ func (f *file) scanLicenseID(conv *SPDXConv) { return } if cml.rePattern.Match(line) { - f.licenseID = cml.LicenseIdentifier + f.idxLicenseID = x + f.licenseID = valMatch return } } for x, line := range f.bottomLines { if reLicenseID.Match(line) { - f.idxLicenseID = x * -1 - f.licenseID = fmt.Sprintf("%s:%d", valExist, f.idxLicenseID) + f.idxLicenseID = x - conv.cfg.MaxLineMatch + f.licenseID = valExist return } if cml.rePattern.Match(line) { - f.licenseID = cml.LicenseIdentifier + f.idxLicenseID = x - conv.cfg.MaxLineMatch + f.licenseID = valMatch return } } @@ -178,7 +181,7 @@ func (f *file) scanCopyrightText(conv *SPDXConv) { for x, line := range f.topLines { if reCopyrightText.Match(line) { f.idxCopyrightText = x - f.copyrightText = fmt.Sprintf("%s:%d", valExist, f.idxCopyrightText) + f.copyrightText = valExist if f.hasSheBang && x == 1 { return } @@ -188,18 +191,20 @@ func (f *file) scanCopyrightText(conv *SPDXConv) { return } if cmc.match(string(line)) { - f.copyrightText = cmc.String() + f.idxCopyrightText = x + f.copyrightText = valMatch return } } for x, line := range f.bottomLines { if reLicenseID.Match(line) { - f.idxCopyrightText = x * -1 - f.licenseID = fmt.Sprintf("%s:%d", valExist, f.idxCopyrightText) + f.idxCopyrightText = x - conv.cfg.MaxLineMatch + f.licenseID = valExist return } if cmc.match(string(line)) { - f.copyrightText = cmc.String() + f.idxCopyrightText = x - conv.cfg.MaxLineMatch + f.copyrightText = valMatch return } } @@ -26,7 +26,8 @@ const ( reportGroupUnknown = `unknown` ) -const v1FieldsPerRecord = 4 +// v1FieldsPerRecord fixed number of columns in report. +const v1FieldsPerRecord = 8 type report struct { listRegular []*file @@ -52,7 +53,6 @@ func loadReport() (rep *report, err error) { rep = &report{} var group string var record []string - var fields []string var f *file var n int @@ -74,31 +74,29 @@ func loadReport() (rep *report, err error) { f = &file{ path: record[0], - copyrightYear: record[2], + licenseID: record[1], + copyrightYear: record[3], + copyrightText: record[4], + commentPrefix: record[6], + commentSuffix: record[7], } - fields = strings.Split(record[1], `:`) - f.licenseID = fields[0] - if len(fields) == 2 && fields[0] == valExist { - f.idxLicenseID, err = strconv.Atoi(fields[1]) - if err != nil { - return nil, fmt.Errorf(`%s: line %d: %w`, logp, n, err) - } + f.idxLicenseID, err = strconv.Atoi(record[2]) + if err != nil { + return nil, fmt.Errorf(`%s: line %d: %w`, logp, n, err) } - fields = strings.Split(record[3], `:`) - f.copyrightText = fields[0] - if len(fields) == 2 && fields[0] == valExist { - f.idxCopyrightText, err = strconv.Atoi(fields[1]) - if err != nil { - return nil, fmt.Errorf(`%s: line %d: %w`, logp, n, err) - } + f.idxCopyrightText, err = strconv.Atoi(record[5]) + if err != nil { + return nil, fmt.Errorf(`%s: line %d: %w`, logp, n, err) } switch group { case reportGroupRegular: rep.listRegular = append(rep.listRegular, f) case reportGroupBinary: + f.isBinary = true rep.listBinary = append(rep.listBinary, f) case reportGroupUnknown: + f.isUnknown = true rep.listUnknown = append(rep.listUnknown, f) } next: @@ -138,17 +136,22 @@ func (rep *report) scan(conv *SPDXConv, listFile []string) (err error) { func (rep *report) write() (err error) { var buf bytes.Buffer buf.WriteString(reportMetaPrefix + "version:v1\n") - buf.WriteString(reportMetaPrefix + "header:path,license_id,year,copyright_id\n") + buf.WriteString(reportMetaPrefix + + "header:path,license_id,idx_license_id,year,copyright_id,idx_copyright_id\n") var csvw = csv.NewWriter(&buf) - var record = make([]string, 4) + var record = make([]string, v1FieldsPerRecord) buf.WriteString(reportMetaPrefix + reportGroupRegular + "\n") for _, file := range rep.listRegular { record[0] = file.path record[1] = file.licenseID - record[2] = file.copyrightYear - record[3] = file.copyrightText + record[2] = strconv.Itoa(file.idxLicenseID) + record[3] = file.copyrightYear + record[4] = file.copyrightText + record[5] = strconv.Itoa(file.idxCopyrightText) + record[6] = file.commentPrefix + record[7] = file.commentSuffix err = csvw.Write(record) if err != nil { return err @@ -160,8 +163,12 @@ func (rep *report) write() (err error) { for _, file := range rep.listBinary { record[0] = file.path record[1] = file.licenseID - record[2] = file.copyrightYear - record[3] = file.copyrightText + record[2] = strconv.Itoa(file.idxLicenseID) + record[3] = file.copyrightYear + record[4] = file.copyrightText + record[5] = strconv.Itoa(file.idxCopyrightText) + record[6] = file.commentPrefix + record[7] = file.commentSuffix err = csvw.Write(record) if err != nil { return err @@ -173,8 +180,12 @@ func (rep *report) write() (err error) { for _, file := range rep.listUnknown { record[0] = file.path record[1] = file.licenseID - record[2] = file.copyrightYear - record[3] = file.copyrightText + record[2] = strconv.Itoa(file.idxLicenseID) + record[3] = file.copyrightYear + record[4] = file.copyrightText + record[5] = strconv.Itoa(file.idxCopyrightText) + record[6] = file.commentPrefix + record[7] = file.commentSuffix err = csvw.Write(record) if err != nil { return err diff --git a/report_test.go b/report_test.go index 74d1f7a..db43739 100644 --- a/report_test.go +++ b/report_test.go @@ -23,6 +23,7 @@ func TestLoadReport(t *testing.T) { licenseID: valDefault, copyrightYear: valUnknown, copyrightText: valDefault, + commentPrefix: `# `, }, { path: `file R2`, licenseID: valExist, @@ -30,20 +31,30 @@ func TestLoadReport(t *testing.T) { copyrightYear: `2024`, copyrightText: valExist, idxCopyrightText: -1, + commentPrefix: `// `, + }, { + path: `fileR3`, + licenseID: valMatch, + idxLicenseID: -2, + copyrightYear: `2000-2026`, + copyrightText: valMatch, + idxCopyrightText: -3, + commentPrefix: `<!-- `, + commentSuffix: ` -->`, }}, listBinary: []*file{{ path: `fileB1`, - licenseID: `BSD-3-Clause`, - copyrightYear: `2000-2026`, - copyrightText: `Author <contact@email.local>`, + licenseID: valDefault, + copyrightYear: valUnknown, + copyrightText: valDefault, + isBinary: true, }}, listUnknown: []*file{{ - path: `fileU1`, - licenseID: valExist, - idxLicenseID: -1, - copyrightYear: `2000`, - copyrightText: valExist, - idxCopyrightText: 2, + path: `fileU1`, + licenseID: valDefault, + copyrightYear: valUnknown, + copyrightText: valDefault, + isUnknown: true, }}, } test.Assert(t, workDir, exp, got) diff --git a/spdxconv_test.go b/spdxconv_test.go index 969f4ca..f002ef2 100644 --- a/spdxconv_test.go +++ b/spdxconv_test.go @@ -43,12 +43,12 @@ func TestScan(t *testing.T) { } exp := `//spdxconv:version:v1 -//spdxconv:header:path,license_id,year,copyright_id +//spdxconv:header:path,license_id,idx_license_id,year,copyright_id,idx_copyright_id //spdxconv:regular -.gitignore,exist:0,unknown,exist:1 -test.go,BSD-3-Clause,unknown,Shulhan <ms@kilabit.info> -test.html,default,unknown,default -test.sh,BSD-3-Clause,unknown,Shulhan <ms@kilabit.info> +.gitignore,exist,0,unknown,exist,1,# , +test.go,match,1,unknown,match,0,// , +test.html,default,0,unknown,default,0,<!-- ," -->" +test.sh,match,1,unknown,match,0,# , //spdxconv:binary //spdxconv:unknown` diff --git a/testdata/loadReport/ok/spdxconv.report b/testdata/loadReport/ok/spdxconv.report index ab58899..a83ade4 100644 --- a/testdata/loadReport/ok/spdxconv.report +++ b/testdata/loadReport/ok/spdxconv.report @@ -1,13 +1,14 @@ // comment //spdxconv:regular -fileR1,default,unknown,default -file R2,exist:1,2024,exist:-1 +fileR1,default,0,unknown,default,0,# , +file R2,exist,1,2024,exist,-1,// , +fileR3,match,-2,2000-2026,match,-3,<!-- ," -->" //spdxconv:binary -fileB1,BSD-3-Clause,2000-2026,Author <contact@email.local> +fileB1,default,0,unknown,default,0,, // comment //spdxconv:unknown // comment -fileU1,exist:-1,2000,exist:2 +fileU1,default,0,unknown,default,0,, |
