Skip to content

Commit 9e71721

Browse files
authored
Cleanup last release (#80)
1 parent 68ac93d commit 9e71721

File tree

4 files changed

+98
-159
lines changed

4 files changed

+98
-159
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88

99
<!-- next-header -->
1010
## [Unreleased] - ReleaseDate
11+
### Changed
12+
- [PR#80](https://github.com/EmbarkStudios/spdx/pull/80) changed how `Licensee::satisfies` works for GNU licenses again, it now requires that the license ids match exactly. This is incredibly pedantic but means it's up to consumers if the want to have a smarter comparison, I just don't want to have to care about GNU licenses, ever.
13+
14+
### Fixed
15+
- [PR#80](https://github.com/EmbarkStudios/spdx/pull/80) reverted a change introduced in [PR#78] that would auto-fixup GNU licenses to their non-deprecated forms eg. `GPL-2.0` => `GPL-2.0-only`. This is no longer done, resolving [#79](https://github.com/EmbarkStudios/spdx/issues/79).
16+
1117
## [0.11.0] - 2025-08-08
1218
### Changed
1319
- [PR#78] removed `ParseMode::allow_lower_case_operators`, newer revisions of the SPDX spec allow all lower-case operators, making the option pointless.

src/expression/parser.rs

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -196,26 +196,16 @@ impl Expression {
196196
match &lt.token {
197197
Token::Spdx(id) => match last_token {
198198
None | Some(Token::And | Token::Or | Token::OpenParen) => {
199-
let id = if id.is_gnu() {
200-
crate::gnu_license_id(id.name, false).ok_or_else(|| ParseError {
199+
if !mode.allow_deprecated && id.is_deprecated() {
200+
return Err(ParseError {
201201
original: original.to_owned(),
202-
span: lt.span.clone(),
203-
reason: Reason::UnknownLicense,
204-
})?
205-
} else {
206-
if !mode.allow_deprecated && id.is_deprecated() {
207-
return Err(ParseError {
208-
original: original.to_owned(),
209-
span: lt.span,
210-
reason: Reason::DeprecatedLicenseId,
211-
});
212-
}
213-
214-
*id
215-
};
202+
span: lt.span,
203+
reason: Reason::DeprecatedLicenseId,
204+
});
205+
}
216206

217207
expr_queue.push(ExprNode::Req(ExpressionReq {
218-
req: LicenseReq::from(id),
208+
req: LicenseReq::from(*id),
219209
span: lt.span.start as u32..lt.span.end as u32,
220210
}));
221211
}

src/licensee.rs

Lines changed: 2 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use std::fmt;
1111
///
1212
/// ```
1313
/// let licensee = spdx::Licensee::parse("GPL-2.0-or-later").unwrap();
14-
/// let req = spdx::LicenseReq::from(spdx::license_id("GPL-2.0-only").unwrap());
14+
/// let req = spdx::LicenseReq::from(spdx::license_id("GPL-2.0-or-later").unwrap());
1515
///
1616
/// assert!(licensee.satisfies(&req));
1717
/// ```
@@ -89,7 +89,7 @@ impl Licensee {
8989
})??;
9090

9191
match lt.token {
92-
Token::Spdx(mut id) => {
92+
Token::Spdx(id) => {
9393
if !mode.allow_deprecated && id.is_deprecated() {
9494
return Err(ParseError {
9595
original: original.to_owned(),
@@ -98,15 +98,6 @@ impl Licensee {
9898
});
9999
}
100100

101-
if id.is_gnu() && !id.name.ends_with("-or-later") && !id.name.ends_with("-only")
102-
{
103-
id = crate::gnu_license_id(id.name, false).ok_or_else(|| ParseError {
104-
original: original.to_owned(),
105-
span: lt.span,
106-
reason: Reason::UnknownLicense,
107-
})?;
108-
}
109-
110101
LicenseItem::Spdx {
111102
id,
112103
or_later: false,
@@ -211,37 +202,6 @@ impl Licensee {
211202
_ => return false,
212203
}
213204
}
214-
} else if a.is_gnu() && b.is_gnu() {
215-
let abn = a.base();
216-
let bbn = b.base();
217-
218-
if abn != bbn {
219-
return false;
220-
}
221-
222-
// GFDL has the annoying -no -invariants...variants, both
223-
// sides have to agree on all or none
224-
if abn == "GFDL"
225-
&& a.name.contains("-invariants") ^ b.name.contains("-invariants")
226-
|| a.name.contains("-no-") ^ b.name.contains("-no-")
227-
{
228-
return false;
229-
}
230-
231-
let Some(av) = a.version() else {
232-
return false;
233-
};
234-
let Some(bv) = b.version() else {
235-
return false;
236-
};
237-
238-
if b.name.ends_with("-or-later") {
239-
if av < bv {
240-
return false;
241-
}
242-
} else if abn != bbn || av != bv {
243-
return false;
244-
}
245205
} else {
246206
return false;
247207
}

tests/check.rs

Lines changed: 83 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ fn complex() {
8484
false && (false || false) => |req| exact!(req, "Apache-2.0"),
8585
true && (false || false) => |req| exact!(req, "MIT"),
8686
true && (false || true) => |req| exact!(req, "MIT") || exact!(req, "BSD-3-Clause"),
87-
true && (true || false) => |req| exact!(req, "MIT") || exact!(req, "LGPL-3.0-or-later"),
87+
true && (true || false) => |req| exact!(req, "MIT") || exact!(req, "LGPL-2.1-or-later"),
8888
]);
8989
}
9090

@@ -171,24 +171,13 @@ fn or_later() {
171171
fn lgpl_only() {
172172
check!("LGPL-2.1-only" => [
173173
false => |req| exact!(req, "LGPL-2.0"),
174-
true => |req| exact!(req, "LGPL-2.1"),
174+
false => |req| exact!(req, "LGPL-2.1"),
175+
true => |req| exact!(req, "LGPL-2.1-only"),
175176
false => |req| exact!(req, "LGPL-3.0"),
176177
//false => |req| exact!(req, "LGPL-4.0"),
177178
]);
178179
}
179180

180-
#[test]
181-
fn gpl_or_later() {
182-
check!("GPL-3.0-or-later" => [
183-
false => |req| exact!(req, "GPL-1.0"),
184-
false => |req| exact!(req, "GPL-2.0"),
185-
true => |req| exact!(req, "GPL-3.0-only"),
186-
true => |req| exact!(req, "GPL-3.0"),
187-
true => |req| exact!(req, "GPL-3.0-or-later"),
188-
//true => |req| exact!(req, "GPL-4.0"),
189-
]);
190-
}
191-
192181
#[test]
193182
fn gpl_or_later_plus_strict() {
194183
spdx::Expression::parse("GPL-2.0+").unwrap_err();
@@ -201,104 +190,95 @@ fn gpl_or_later_plus_lax() {
201190

202191
#[test]
203192
fn gpl_pedantic() {
204-
// | Licensee | GPL-1.0-only | GPL-1.0-or-later | GPL-2.0-only | GPL-2.0-or-later | GPL-3.0-only | GPL-3.0-or-later |
205-
// | ----------------- | -- | -- | -- | -- | -- | -- |
206-
// | GPL-1.0-only | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
207-
// | GPL-1.0-or-later | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
208-
// | GPL-2.0-only | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ |
209-
// | GPL-2.0-or-later | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ |
210-
// | GPL-3.0-only | ❌ | ✅ | ❌ | ✅ | ✅ | ✅ |
211-
// | GPL-3.0-or-later | ❌ | ✅ | ❌ | ✅ | ✅ | ✅ |
212-
213193
const ONE_ONLY: &str = "GPL-1.0-only";
214194
const ONE_LATER: &str = "GPL-1.0-or-later";
215195
const TWO_ONLY: &str = "GPL-2.0-only";
216196
const TWO_LATER: &str = "GPL-2.0-or-later";
217197
const THREE_ONLY: &str = "GPL-3.0-only";
218198
const THREE_LATER: &str = "GPL-3.0-or-later";
219199

200+
const COLUMNS: &[&str] = &[
201+
ONE_ONLY,
202+
ONE_LATER,
203+
TWO_ONLY,
204+
TWO_LATER,
205+
THREE_ONLY,
206+
THREE_LATER,
207+
];
208+
220209
let table = [
221-
(
222-
ONE_ONLY,
223-
[
224-
(ONE_ONLY, true),
225-
(ONE_LATER, true),
226-
(TWO_ONLY, false),
227-
(TWO_LATER, false),
228-
(THREE_ONLY, false),
229-
(THREE_LATER, false),
230-
],
231-
),
232-
(
233-
ONE_LATER,
234-
[
235-
(ONE_ONLY, true),
236-
(ONE_LATER, true),
237-
(TWO_ONLY, false),
238-
(TWO_LATER, false),
239-
(THREE_ONLY, false),
240-
(THREE_LATER, false),
241-
],
242-
),
243-
(
244-
TWO_ONLY,
245-
[
246-
(ONE_ONLY, false),
247-
(ONE_LATER, true),
248-
(TWO_ONLY, true),
249-
(TWO_LATER, true),
250-
(THREE_ONLY, false),
251-
(THREE_LATER, false),
252-
],
253-
),
254-
(
255-
TWO_LATER,
256-
[
257-
(ONE_ONLY, false),
258-
(ONE_LATER, true),
259-
(TWO_ONLY, true),
260-
(TWO_LATER, true),
261-
(THREE_ONLY, false),
262-
(THREE_LATER, false),
263-
],
264-
),
265-
(
266-
THREE_ONLY,
267-
[
268-
(ONE_ONLY, false),
269-
(ONE_LATER, true),
270-
(TWO_ONLY, false),
271-
(TWO_LATER, true),
272-
(THREE_ONLY, true),
273-
(THREE_LATER, true),
274-
],
275-
),
276-
(
277-
THREE_LATER,
278-
[
279-
(ONE_ONLY, false),
280-
(ONE_LATER, true),
281-
(TWO_ONLY, false),
282-
(TWO_LATER, true),
283-
(THREE_ONLY, true),
284-
(THREE_LATER, true),
285-
],
286-
),
210+
(ONE_ONLY, [true, false, false, false, false, false]),
211+
(ONE_LATER, [false, true, false, false, false, false]),
212+
(TWO_ONLY, [false, false, true, false, false, false]),
213+
(TWO_LATER, [false, false, false, true, false, false]),
214+
(THREE_ONLY, [false, false, false, false, true, false]),
215+
(THREE_LATER, [false, false, false, false, false, true]),
287216
];
288217

218+
fn header(s: &mut String) {
219+
s.push_str("| Licensee | GPL-1.0-only | GPL-1.0-or-later | GPL-2.0-only | GPL-2.0-or-later | GPL-3.0-only | GPL-3.0-or-later |\n");
220+
s.push_str("| ---------------- | ------------ | ---------------- | ------------ | ---------------- | ------------ | ---------------- |\n");
221+
}
222+
223+
fn fill(s: &mut String, c: &str, len: usize) {
224+
for _ in 0..len - c.len() {
225+
s.push(' ');
226+
}
227+
}
228+
229+
fn lic(s: &mut String, lic: &str) {
230+
s.push_str("| ");
231+
s.push_str(lic);
232+
fill(s, lic, 16);
233+
s.push_str(" | ");
234+
}
235+
289236
for (licensee, items) in table {
237+
let mut expected = String::new();
238+
let exp = &mut expected;
239+
header(exp);
240+
241+
let mut actual = String::new();
242+
let act = &mut actual;
243+
header(act);
244+
245+
lic(exp, licensee);
246+
lic(act, licensee);
247+
290248
let lic = spdx::Licensee::parse(licensee).unwrap();
291249

292-
for (req, passes) in items {
250+
let mut fail = false;
251+
for (col, passes) in COLUMNS.iter().zip(items.iter()) {
293252
let req = spdx::LicenseReq {
294253
license: spdx::LicenseItem::Spdx {
295-
id: spdx::license_id(req).unwrap(),
254+
id: spdx::license_id(col).unwrap(),
296255
or_later: false,
297256
},
298257
exception: None,
299258
};
300259

301-
assert_eq!(lic.satisfies(&req), passes);
260+
exp.push_str(if *passes { "+" } else { "-" });
261+
fill(exp, " ", col.len());
262+
263+
exp.push_str(" | ");
264+
265+
let satisfies = lic.satisfies(&req);
266+
267+
act.push_str(if satisfies { "+" } else { "-" });
268+
fill(act, " ", col.len());
269+
act.push_str(" | ");
270+
271+
fail |= *passes != satisfies;
272+
}
273+
274+
exp.push('\n');
275+
act.push('\n');
276+
277+
if fail {
278+
panic!(
279+
"{}",
280+
similar_asserts::SimpleDiff::from_str(exp, act, "expected", "calculated")
281+
);
302282
}
303283
}
304284
}
@@ -307,11 +287,11 @@ fn gpl_pedantic() {
307287
fn gfdl() {
308288
check!("GFDL-1.2-or-later" => [
309289
false => |req| exact!(req, "GFDL-1.1"),
310-
true => |req| exact!(req, "GFDL-1.2"),
311-
true => |req| exact!(req, "GFDL-1.3"),
290+
false => |req| exact!(req, "GFDL-1.2"),
291+
false => |req| exact!(req, "GFDL-1.3"),
312292
false => |req| exact!(req, "GFDL-1.1-or-later"),
313293
true => |req| exact!(req, "GFDL-1.2-or-later"),
314-
true => |req| exact!(req, "GFDL-1.3-or-later"),
294+
false => |req| exact!(req, "GFDL-1.3-or-later"),
315295
]);
316296

317297
check!("GFDL-1.2-invariants-or-later" => [
@@ -320,23 +300,24 @@ fn gfdl() {
320300
false => |req| exact!(req, "GFDL-1.2"),
321301
true => |req| exact!(req, "GFDL-1.2-invariants-or-later"),
322302
false => |req| exact!(req, "GFDL-1.3"),
323-
true => |req| exact!(req, "GFDL-1.3-invariants-only"),
303+
false => |req| exact!(req, "GFDL-1.3-invariants-only"),
324304
]);
325305

326306
check_lax!("GFDL-1.1-invariants+" => [
327307
false => |req| exact!(req, "GFDL-1.1"),
328308
true => |req| exact!(req, "GFDL-1.1-invariants-or-later"),
329309
false => |req| exact!(req, "GFDL-1.2"),
330-
true => |req| exact!(req, "GFDL-1.2-invariants-or-later"),
310+
false => |req| exact!(req, "GFDL-1.2-invariants-or-later"),
331311
false => |req| exact!(req, "GFDL-1.3"),
332-
true => |req| exact!(req, "GFDL-1.3-invariants-or-later"),
312+
false => |req| exact!(req, "GFDL-1.3-invariants-or-later"),
333313
]);
334314

335315
check!("GFDL-1.2-invariants" => [
336316
false => |req| exact!(req, "GFDL-1.1"),
337317
false => |req| exact!(req, "GFDL-1.1-invariants"),
338318
false => |req| exact!(req, "GFDL-1.2"),
339319
true => |req| exact!(req, "GFDL-1.2-invariants"),
320+
false => |req| exact!(req, "GFDL-1.2-invariants-only"),
340321
false => |req| exact!(req, "GFDL-1.3"),
341322
false => |req| exact!(req, "GFDL-1.3-invariants"),
342323
]);
@@ -345,7 +326,8 @@ fn gfdl() {
345326
false => |req| exact!(req, "GFDL-1.1"),
346327
false => |req| exact!(req, "GFDL-1.1-invariants"),
347328
false => |req| exact!(req, "GFDL-1.2"),
348-
true => |req| exact!(req, "GFDL-1.2-invariants"),
329+
false => |req| exact!(req, "GFDL-1.2-invariants"),
330+
true => |req| exact!(req, "GFDL-1.2-invariants-only"),
349331
false => |req| exact!(req, "GFDL-1.3"),
350332
false => |req| exact!(req, "GFDL-1.3-invariants"),
351333
]);
@@ -355,7 +337,8 @@ fn gfdl() {
355337
false => |req| exact!(req, "GFDL-1.1-invariants"),
356338
false => |req| exact!(req, "GFDL-1.2"),
357339
false => |req| exact!(req, "GFDL-1.2-invariants"),
358-
true => |req| exact!(req, "GFDL-1.3"),
340+
false => |req| exact!(req, "GFDL-1.3"),
341+
true => |req| exact!(req, "GFDL-1.3-only"),
359342
false => |req| exact!(req, "GFDL-1.3-invariants"),
360343
]);
361344
}

0 commit comments

Comments
 (0)