Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Fixed

- `pnpm` version 5 parser including metadata in package versions
- Platform-specific dependencies ignored by the `Gemfile.lock` parser

## 7.1.4 - 2024-11-07

Expand Down
8 changes: 4 additions & 4 deletions lockfile/src/parsers/gem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ use crate::{Package, PackageVersion, ThirdPartyVersion};
const DEFAULT_REGISTRY: &str = "https://rubygems.org/";

/// Legal non-alphanumeric characters in loose version specifications.
const LOOSE_VERSION_CHARS: &[char] = &[' ', ',', '<', '>', '=', '~', '!', '.', '-', '+'];
const LOOSE_VERSION_CHARS: &[char] = &[' ', ',', '<', '>', '=', '~', '!', '.', '-', '+', '_'];

/// Legal non-alphanumeric characters in strict version specifications.
const STRICT_VERSION_CHARS: &[char] = &['.', '-', '+'];
const STRICT_VERSION_CHARS: &[char] = &['.'];

#[derive(Debug)]
struct Section<'a> {
Expand Down Expand Up @@ -224,7 +224,7 @@ fn package_name(input: &str) -> IResult<&str, &str> {
}

/// Parser allowing for loose `(>= 1.2.0, < 2.0, != 1.2.3)` and strict
/// `(1.2.3-alpha+build3)` versions.
/// `(1.2.3.alpha.1)` versions.
fn loose_package_version(input: &str) -> IResult<&str, &str> {
// Versions can be completely omitted for sub-dependencies.
if input.is_empty() {
Expand All @@ -241,7 +241,7 @@ fn loose_package_version(input: &str) -> IResult<&str, &str> {
)(input)
}

/// Parser allowing only strict `1.2.3-alpha+build3` versions.
/// Parser allowing only strict `1.2.3.alpha.1` versions.
fn strict_package_version(input: &str) -> IResult<&str, &str> {
let (input, _) = space0(input)?;
recognize(many1(satisfy(|c: char| {
Expand Down
22 changes: 19 additions & 3 deletions lockfile/src/ruby.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,17 @@ pub struct GemLock;
impl Parse for GemLock {
/// Parses `Gemfile.lock` files into a vec of packages
fn parse(&self, data: &str) -> anyhow::Result<Vec<Package>> {
let (_, entries) = gem::parse(data)
let (_, mut packages) = gem::parse(data)
.finish()
.map_err(|e| anyhow!(convert_error(data, e)))
.context("Failed to parse gem lockfile")?;
Ok(entries)

// Remove duplicate dependencies, which can occur when a dependency is included
// with multiple different platform suffixes.
packages.sort_unstable();
packages.dedup();

Ok(packages)
}

fn is_path_lockfile(&self, path: &Path) -> bool {
Expand All @@ -48,7 +54,7 @@ mod tests {
#[test]
fn lock_parse_gem() {
let pkgs = GemLock.parse(include_str!("../../tests/fixtures/Gemfile.lock")).unwrap();
assert_eq!(pkgs.len(), 11);
assert_eq!(pkgs.len(), 13);

let expected_pkgs = [
Package {
Expand Down Expand Up @@ -84,6 +90,16 @@ mod tests {
}),
package_type: PackageType::RubyGems,
},
Package {
name: "ffi".into(),
version: PackageVersion::FirstParty("1.17.0".into()),
package_type: PackageType::RubyGems,
},
Package {
name: "fake".into(),
version: PackageVersion::FirstParty("1.2.3".into()),
package_type: PackageType::RubyGems,
},
];

for expected_pkg in expected_pkgs {
Expand Down
5 changes: 4 additions & 1 deletion tests/fixtures/Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ GEM
rspec-core (~> 3.11.0)
rspec-expectations (~> 3.11.0)
rspec-mocks (~> 3.11.0)
rspec-core (3.11.0-alpha+build3)
rspec-core (3.11.0)
rspec-support (~> 3.11.0)
rspec-expectations (3.11.1)
diff-lcs (>= 1.2.0, < 2.0)
Expand All @@ -48,6 +48,9 @@ GEM
remote: https://rubygems.org/
specs:
wirble (0.1.3)
ffi (1.17.0)
ffi (1.17.0-x86_64-linux-gnu)
fake (1.2.3-x86_64-linux-gnu)

DEPENDENCIES
benchmark!
Expand Down