• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

spdx / tools-golang / 5008105195

17 May 2023 09:34PM UTC coverage: 94.782% (-0.04%) from 94.822%
5008105195

Pull #215

github

Brandon Lum
change packageVerification code for 2.1,2.2 to omitempty
Pull Request #215: Fixing some optional params: copyrightText, licenseListVersion, packageVerificationCode

7157 of 7551 relevant lines covered (94.78%)

15.09 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

75.86
/spdx/v2/common/identifier.go
1
// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
2

3
package common
4

5
import (
6
        "encoding/json"
7
        "fmt"
8
        "strings"
9
)
10

11
const (
12
        spdxRefPrefix     = "SPDXRef-"
13
        documentRefPrefix = "DocumentRef-"
14
)
15

16
// ElementID represents the identifier string portion of an SPDX element
17
// identifier. DocElementID should be used for any attributes which can
18
// contain identifiers defined in a different SPDX document.
19
// ElementIDs should NOT contain the mandatory 'SPDXRef-' portion.
20
type ElementID string
21

22
// MarshalJSON returns an SPDXRef- prefixed JSON string
23
func (d ElementID) MarshalJSON() ([]byte, error) {
4✔
24
        return json.Marshal(prefixElementId(d))
4✔
25
}
4✔
26

27
// UnmarshalJSON validates SPDXRef- prefixes and removes them when processing ElementIDs
28
func (d *ElementID) UnmarshalJSON(data []byte) error {
4✔
29
        // SPDX identifier will simply be a string
4✔
30
        idStr := string(data)
4✔
31
        idStr = strings.Trim(idStr, "\"")
4✔
32

4✔
33
        e, err := trimElementIdPrefix(idStr)
4✔
34
        if err != nil {
6✔
35
                return err
2✔
36
        }
2✔
37
        *d = e
2✔
38
        return nil
2✔
39
}
40

41
// prefixElementId adds the SPDXRef- prefix to an element ID if it does not have one
42
func prefixElementId(id ElementID) string {
6✔
43
        val := string(id)
6✔
44
        if !strings.HasPrefix(val, spdxRefPrefix) {
10✔
45
                return spdxRefPrefix + val
4✔
46
        }
4✔
47
        return val
2✔
48
}
49

50
// trimElementIdPrefix removes the SPDXRef- prefix from an element ID string or returns an error if it
51
// does not start with SPDXRef-
52
func trimElementIdPrefix(id string) (ElementID, error) {
8✔
53
        // handle SPDXRef-
8✔
54
        idFields := strings.SplitN(id, spdxRefPrefix, 2)
8✔
55
        if len(idFields) != 2 {
12✔
56
                return "", fmt.Errorf("failed to parse SPDX identifier '%s'", id)
4✔
57
        }
4✔
58

59
        e := ElementID(idFields[1])
4✔
60
        return e, nil
4✔
61
}
62

63
// DocElementID represents an SPDX element identifier that could be defined
64
// in a different SPDX document, and therefore could have a "DocumentRef-"
65
// portion, such as Relationships and Annotations.
66
// ElementID is used for attributes in which a "DocumentRef-" portion cannot
67
// appear, such as a Package or File definition (since it is necessarily
68
// being defined in the present document).
69
// DocumentRefID will be the empty string for elements defined in the
70
// present document.
71
// DocElementIDs should NOT contain the mandatory 'DocumentRef-' or
72
// 'SPDXRef-' portions.
73
// SpecialID is used ONLY if the DocElementID matches a defined set of
74
// permitted special values for a particular field, e.g. "NONE" or
75
// "NOASSERTION" for the right-hand side of Relationships. If SpecialID
76
// is set, DocumentRefID and ElementRefID should be empty (and vice versa).
77
type DocElementID struct {
78
        DocumentRefID string
79
        ElementRefID  ElementID
80
        SpecialID     string
81
}
82

83
// MarshalJSON converts the receiver into a slice of bytes representing a DocElementID in string form.
84
// This function is also used when marshalling to YAML
85
func (d DocElementID) MarshalJSON() ([]byte, error) {
4✔
86
        if d.DocumentRefID != "" && d.ElementRefID != "" {
5✔
87
                idStr := prefixElementId(d.ElementRefID)
1✔
88
                return json.Marshal(fmt.Sprintf("%s%s:%s", documentRefPrefix, d.DocumentRefID, idStr))
1✔
89
        } else if d.ElementRefID != "" {
5✔
90
                return json.Marshal(prefixElementId(d.ElementRefID))
1✔
91
        } else if d.SpecialID != "" {
4✔
92
                return json.Marshal(d.SpecialID)
1✔
93
        }
1✔
94

95
        return []byte{}, fmt.Errorf("failed to marshal empty DocElementID")
1✔
96
}
97

98
// UnmarshalJSON takes a SPDX Identifier string parses it into a DocElementID struct.
99
// This function is also used when unmarshalling YAML
100
func (d *DocElementID) UnmarshalJSON(data []byte) (err error) {
7✔
101
        // SPDX identifier will simply be a string
7✔
102
        idStr := string(data)
7✔
103
        idStr = strings.Trim(idStr, "\"")
7✔
104

7✔
105
        // handle special cases
7✔
106
        if idStr == "NONE" || idStr == "NOASSERTION" {
9✔
107
                d.SpecialID = idStr
2✔
108
                return nil
2✔
109
        }
2✔
110

111
        var idFields []string
5✔
112
        // handle DocumentRef- if present
5✔
113
        if strings.HasPrefix(idStr, documentRefPrefix) {
8✔
114
                // strip out the "DocumentRef-" so we can get the value
3✔
115
                idFields = strings.SplitN(idStr, documentRefPrefix, 2)
3✔
116
                idStr = idFields[1]
3✔
117

3✔
118
                // an SPDXRef can appear after a DocumentRef, separated by a colon
3✔
119
                idFields = strings.SplitN(idStr, ":", 2)
3✔
120
                d.DocumentRefID = idFields[0]
3✔
121

3✔
122
                if len(idFields) == 2 {
5✔
123
                        idStr = idFields[1]
2✔
124
                } else {
3✔
125
                        return nil
1✔
126
                }
1✔
127
        }
128

129
        d.ElementRefID, err = trimElementIdPrefix(idStr)
4✔
130
        return err
4✔
131
}
132

133
// TODO: add equivalents for LicenseRef- identifiers
134

135
// MakeDocElementID takes strings (without prefixes) for the DocumentRef-
136
// and SPDXRef- identifiers, and returns a DocElementID. An empty string
137
// should be used for the DocumentRef- portion if it is referring to the
138
// present document.
139
func MakeDocElementID(docRef string, eltRef string) DocElementID {
×
140
        return DocElementID{
×
141
                DocumentRefID: docRef,
×
142
                ElementRefID:  ElementID(eltRef),
×
143
        }
×
144
}
×
145

146
// MakeDocElementSpecial takes a "special" string (e.g. "NONE" or
147
// "NOASSERTION" for the right side of a Relationship), nd returns
148
// a DocElementID with it in the SpecialID field. Other fields will
149
// be empty.
150
func MakeDocElementSpecial(specialID string) DocElementID {
×
151
        return DocElementID{SpecialID: specialID}
×
152
}
×
153

154
// RenderElementID takes an ElementID and returns the string equivalent,
155
// with the SPDXRef- prefix reinserted.
156
func RenderElementID(eID ElementID) string {
×
157
        return spdxRefPrefix + string(eID)
×
158
}
×
159

160
// RenderDocElementID takes a DocElementID and returns the string equivalent,
161
// with the SPDXRef- prefix (and, if applicable, the DocumentRef- prefix)
162
// reinserted. If a SpecialID is present, it will be rendered verbatim and
163
// DocumentRefID and ElementRefID will be ignored.
164
func RenderDocElementID(deID DocElementID) string {
×
165
        if deID.SpecialID != "" {
×
166
                return deID.SpecialID
×
167
        }
×
168
        prefix := ""
×
169
        if deID.DocumentRefID != "" {
×
170
                prefix = documentRefPrefix + deID.DocumentRefID + ":"
×
171
        }
×
172
        return prefix + spdxRefPrefix + string(deID.ElementRefID)
×
173
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc