ecosystems-bibliothecary 15.1.0 → 15.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +24 -0
  3. data/README.md +137 -120
  4. data/lib/bibliothecary/analyser.rb +4 -0
  5. data/lib/bibliothecary/parsers/actions.rb +4 -0
  6. data/lib/bibliothecary/parsers/bentoml.rb +4 -0
  7. data/lib/bibliothecary/parsers/bower.rb +4 -0
  8. data/lib/bibliothecary/parsers/cargo.rb +4 -0
  9. data/lib/bibliothecary/parsers/carthage.rb +4 -0
  10. data/lib/bibliothecary/parsers/clojars.rb +4 -0
  11. data/lib/bibliothecary/parsers/cocoapods.rb +4 -0
  12. data/lib/bibliothecary/parsers/cog.rb +4 -0
  13. data/lib/bibliothecary/parsers/conan.rb +4 -0
  14. data/lib/bibliothecary/parsers/conda.rb +4 -0
  15. data/lib/bibliothecary/parsers/cpan.rb +190 -2
  16. data/lib/bibliothecary/parsers/cran.rb +4 -0
  17. data/lib/bibliothecary/parsers/deno.rb +98 -0
  18. data/lib/bibliothecary/parsers/docker.rb +4 -0
  19. data/lib/bibliothecary/parsers/dub.rb +4 -0
  20. data/lib/bibliothecary/parsers/dvc.rb +4 -0
  21. data/lib/bibliothecary/parsers/elm.rb +4 -0
  22. data/lib/bibliothecary/parsers/go.rb +4 -0
  23. data/lib/bibliothecary/parsers/hackage.rb +55 -0
  24. data/lib/bibliothecary/parsers/haxelib.rb +4 -0
  25. data/lib/bibliothecary/parsers/hex.rb +89 -0
  26. data/lib/bibliothecary/parsers/homebrew.rb +4 -0
  27. data/lib/bibliothecary/parsers/julia.rb +55 -0
  28. data/lib/bibliothecary/parsers/luarocks.rb +4 -0
  29. data/lib/bibliothecary/parsers/maven.rb +4 -0
  30. data/lib/bibliothecary/parsers/meteor.rb +4 -0
  31. data/lib/bibliothecary/parsers/mlflow.rb +4 -0
  32. data/lib/bibliothecary/parsers/nimble.rb +4 -0
  33. data/lib/bibliothecary/parsers/nix.rb +205 -0
  34. data/lib/bibliothecary/parsers/npm.rb +4 -0
  35. data/lib/bibliothecary/parsers/nuget.rb +4 -0
  36. data/lib/bibliothecary/parsers/ollama.rb +4 -0
  37. data/lib/bibliothecary/parsers/packagist.rb +4 -0
  38. data/lib/bibliothecary/parsers/pub.rb +4 -0
  39. data/lib/bibliothecary/parsers/pypi.rb +9 -0
  40. data/lib/bibliothecary/parsers/rubygems.rb +4 -0
  41. data/lib/bibliothecary/parsers/shard.rb +4 -0
  42. data/lib/bibliothecary/parsers/swift_pm.rb +4 -0
  43. data/lib/bibliothecary/parsers/vcpkg.rb +4 -0
  44. data/lib/bibliothecary/version.rb +1 -1
  45. data/lib/bibliothecary.rb +7 -0
  46. metadata +3 -1
@@ -0,0 +1,205 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ module Bibliothecary
6
+ module Parsers
7
+ class Nix
8
+ include Bibliothecary::Analyser
9
+
10
+ def self.file_patterns
11
+ [
12
+ "flake.nix",
13
+ "flake.lock",
14
+ "nix/sources.json",
15
+ "npins/sources.json",
16
+ ]
17
+ end
18
+
19
+ def self.mapping
20
+ {
21
+ match_filename("flake.nix") => {
22
+ kind: "manifest",
23
+ parser: :parse_flake_nix,
24
+ },
25
+ match_filename("flake.lock") => {
26
+ kind: "lockfile",
27
+ parser: :parse_flake_lock,
28
+ },
29
+ match_filename("nix/sources.json") => {
30
+ kind: "lockfile",
31
+ parser: :parse_niv_sources,
32
+ },
33
+ match_filename("npins/sources.json") => {
34
+ kind: "lockfile",
35
+ parser: :parse_npins_sources,
36
+ },
37
+ }
38
+ end
39
+
40
+ # Parse flake.nix manifest file
41
+ # Extracts inputs from the Nix expression using regex
42
+ def self.parse_flake_nix(file_contents, options: {})
43
+ source = options.fetch(:filename, nil)
44
+ dependencies = []
45
+
46
+ # Pattern 1: name.url = "...";
47
+ # e.g., nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
48
+ file_contents.scan(/^\s*([\w][\w-]*)\.url\s*=\s*"([^"]+)"/) do |name, url|
49
+ requirement = parse_flake_url(url)
50
+ dependencies << Dependency.new(
51
+ name: name,
52
+ requirement: requirement,
53
+ type: "runtime",
54
+ source: source,
55
+ platform: platform_name
56
+ )
57
+ end
58
+
59
+ # Pattern 2: name = { url = "..."; ... };
60
+ # e.g., home-manager = { url = "github:nix-community/home-manager"; };
61
+ file_contents.scan(/^\s*([\w][\w-]*)\s*=\s*\{\s*\n?\s*url\s*=\s*"([^"]+)"/) do |name, url|
62
+ requirement = parse_flake_url(url)
63
+ dependencies << Dependency.new(
64
+ name: name,
65
+ requirement: requirement,
66
+ type: "runtime",
67
+ source: source,
68
+ platform: platform_name
69
+ )
70
+ end
71
+
72
+ ParserResult.new(dependencies: dependencies)
73
+ end
74
+
75
+ # Parse flake.lock lockfile
76
+ def self.parse_flake_lock(file_contents, options: {})
77
+ source = options.fetch(:filename, nil)
78
+ lock = JSON.parse(file_contents)
79
+ dependencies = []
80
+
81
+ nodes = lock.fetch("nodes", {})
82
+ root_node = nodes.fetch("root", {})
83
+ root_inputs = root_node.fetch("inputs", {})
84
+
85
+ root_inputs.each do |name, node_key|
86
+ # node_key can be a string or an array (for follows)
87
+ node_key = node_key.first if node_key.is_a?(Array)
88
+ node = nodes[node_key]
89
+ next unless node
90
+
91
+ locked = node.fetch("locked", {})
92
+ requirement = format_locked_version(locked)
93
+
94
+ dependencies << Dependency.new(
95
+ name: name,
96
+ requirement: requirement,
97
+ type: "runtime",
98
+ source: source,
99
+ platform: platform_name
100
+ )
101
+ end
102
+
103
+ ParserResult.new(dependencies: dependencies)
104
+ end
105
+
106
+ # Parse niv sources.json lockfile
107
+ def self.parse_niv_sources(file_contents, options: {})
108
+ source = options.fetch(:filename, nil)
109
+ sources = JSON.parse(file_contents)
110
+ dependencies = []
111
+
112
+ sources.each do |name, attrs|
113
+ next unless attrs.is_a?(Hash)
114
+
115
+ requirement = format_niv_version(attrs)
116
+
117
+ dependencies << Dependency.new(
118
+ name: name,
119
+ requirement: requirement,
120
+ type: "runtime",
121
+ source: source,
122
+ platform: platform_name
123
+ )
124
+ end
125
+
126
+ ParserResult.new(dependencies: dependencies)
127
+ end
128
+
129
+ # Parse npins sources.json lockfile
130
+ def self.parse_npins_sources(file_contents, options: {})
131
+ source = options.fetch(:filename, nil)
132
+ data = JSON.parse(file_contents)
133
+ dependencies = []
134
+
135
+ pins = data.fetch("pins", {})
136
+
137
+ pins.each do |name, attrs|
138
+ next unless attrs.is_a?(Hash)
139
+
140
+ requirement = format_npins_version(attrs)
141
+
142
+ dependencies << Dependency.new(
143
+ name: name,
144
+ requirement: requirement,
145
+ type: "runtime",
146
+ source: source,
147
+ platform: platform_name
148
+ )
149
+ end
150
+
151
+ ParserResult.new(dependencies: dependencies)
152
+ end
153
+
154
+ # Parse a flake URL into a version/requirement string
155
+ # Examples:
156
+ # "github:NixOS/nixpkgs/nixos-unstable" => "nixos-unstable"
157
+ # "github:NixOS/nixpkgs" => "*"
158
+ # "git+https://github.com/foo/bar?ref=v1.0" => "v1.0"
159
+ def self.parse_flake_url(url)
160
+ case url
161
+ when /^github:([^\/]+)\/([^\/\?]+)(?:\/([^\?]+))?/
162
+ $3 || "*"
163
+ when /^gitlab:([^\/]+)\/([^\/\?]+)(?:\/([^\?]+))?/
164
+ $3 || "*"
165
+ when /\?ref=([^&]+)/
166
+ $1
167
+ when /\?rev=([^&]+)/
168
+ $1
169
+ else
170
+ "*"
171
+ end
172
+ end
173
+
174
+ # Format locked version from flake.lock node
175
+ def self.format_locked_version(locked)
176
+ rev = locked["rev"]
177
+ return rev[0..6] if rev # Short commit hash
178
+
179
+ locked["version"] || "*"
180
+ end
181
+
182
+ # Format version from niv sources.json entry
183
+ def self.format_niv_version(attrs)
184
+ if attrs["rev"]
185
+ attrs["rev"][0..6]
186
+ elsif attrs["version"]
187
+ attrs["version"]
188
+ else
189
+ "*"
190
+ end
191
+ end
192
+
193
+ # Format version from npins sources.json entry
194
+ def self.format_npins_version(attrs)
195
+ if attrs["revision"]
196
+ attrs["revision"][0..6]
197
+ elsif attrs["version"]
198
+ attrs["version"]
199
+ else
200
+ "*"
201
+ end
202
+ end
203
+ end
204
+ end
205
+ end
@@ -10,6 +10,10 @@ module Bibliothecary
10
10
  # Max depth to recurse into the "dependencies" property of package-lock.json
11
11
  PACKAGE_LOCK_JSON_MAX_DEPTH = 10
12
12
 
13
+ def self.file_patterns
14
+ ["package.json", "package-lock.json", "npm-shrinkwrap.json", "yarn.lock", "pnpm-lock.yaml", "bun.lock", "npm-ls.json"]
15
+ end
16
+
13
17
  def self.mapping
14
18
  {
15
19
  match_filename("package.json") => {
@@ -8,6 +8,10 @@ module Bibliothecary
8
8
  class Nuget
9
9
  include Bibliothecary::Analyser
10
10
 
11
+ def self.file_patterns
12
+ ["Project.json", "Project.lock.json", "packages.lock.json", "packages.config", "*.nuspec", "*.csproj", "paket.lock", "project.assets.json", "*.deps.json"]
13
+ end
14
+
11
15
  def self.mapping
12
16
  {
13
17
  match_filename("Project.json") => {
@@ -5,6 +5,10 @@ module Bibliothecary
5
5
  class Ollama
6
6
  include Bibliothecary::Analyser
7
7
 
8
+ def self.file_patterns
9
+ ["Modelfile"]
10
+ end
11
+
8
12
  def self.mapping
9
13
  {
10
14
  match_filename("Modelfile") => {
@@ -7,6 +7,10 @@ module Bibliothecary
7
7
  class Packagist
8
8
  include Bibliothecary::Analyser
9
9
 
10
+ def self.file_patterns
11
+ ["composer.json", "composer.lock"]
12
+ end
13
+
10
14
  def self.mapping
11
15
  {
12
16
  match_filename("composer.json") => {
@@ -7,6 +7,10 @@ module Bibliothecary
7
7
  class Pub
8
8
  include Bibliothecary::Analyser
9
9
 
10
+ def self.file_patterns
11
+ ["pubspec.yaml", "pubspec.lock"]
12
+ end
13
+
10
14
  def self.mapping
11
15
  {
12
16
  match_filename("pubspec.yaml", case_insensitive: true) => {
@@ -24,6 +24,15 @@ module Bibliothecary
24
24
  # https://packaging.python.org/en/latest/specifications/pylock-toml/
25
25
  PEP_751_LOCKFILE_REGEXP = /^pylock(\.[^.]+)?\.toml$/
26
26
 
27
+ def self.file_patterns
28
+ [
29
+ "setup.py", "requirements*.txt", "requirements*.pip", "requirements*.in",
30
+ "requirements.frozen", "Pipfile", "Pipfile.lock", "pyproject.toml",
31
+ "poetry.lock", "uv.lock", "pylock.toml", "pdm.lock",
32
+ "pip-resolved-dependencies.txt", "pip-dependency-graph.json"
33
+ ]
34
+ end
35
+
27
36
  def self.mapping
28
37
  {
29
38
  match_filenames("requirements-dev.txt", "requirements/dev.txt",
@@ -19,6 +19,10 @@ module Bibliothecary
19
19
  # Gemspec pattern - captures type in first group
20
20
  GEMSPEC_DEPENDENCY = /\.add_(development_|runtime_)?dependency\s*\(?\s*['"]([^'"]+)['"]\s*(?:,\s*['"]([^'"]+)['"])?(?:\s*,\s*['"]([^'"]+)['"])?\s*\)?/
21
21
 
22
+ def self.file_patterns
23
+ ["Gemfile", "Gemfile.lock", "gems.rb", "gems.locked", "*.gemspec"]
24
+ end
25
+
22
26
  def self.mapping
23
27
  {
24
28
  match_filenames("Gemfile", "gems.rb") => {
@@ -7,6 +7,10 @@ module Bibliothecary
7
7
  class Shard
8
8
  include Bibliothecary::Analyser
9
9
 
10
+ def self.file_patterns
11
+ ["shard.yml", "shard.lock"]
12
+ end
13
+
10
14
  def self.mapping
11
15
  {
12
16
  match_filename("shard.yml", case_insensitive: true) => {
@@ -12,6 +12,10 @@ module Bibliothecary
12
12
  PACKAGE_REGEXP_EXACT = /\.package\s*\(\s*(?:name:\s*"[^"]+",\s*)?url:\s*"([^"]+)"[^)]*(?:\.exact|exact)\s*\(\s*"([^"]+)"\s*\)/i
13
13
  PACKAGE_REGEXP_RANGE = /\.package\s*\(\s*(?:name:\s*"[^"]+",\s*)?url:\s*"([^"]+)"[^)]*"([^"]+)"\s*(?:\.\.|\.\.\.)\s*"([^"]+)"/i
14
14
 
15
+ def self.file_patterns
16
+ ["Package.swift", "Package.resolved"]
17
+ end
18
+
15
19
  def self.mapping
16
20
  {
17
21
  match_filename("Package.swift", case_insensitive: true) => {
@@ -3,6 +3,10 @@ module Bibliothecary
3
3
  class Vcpkg
4
4
  include Bibliothecary::Analyser
5
5
 
6
+ def self.file_patterns
7
+ ["vcpkg.json", "_generated-vcpkg-list.json"]
8
+ end
9
+
6
10
  def self.mapping
7
11
  {
8
12
  match_filename("vcpkg.json", case_insensitive: true) => {
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bibliothecary
4
- VERSION = "15.1.0"
4
+ VERSION = "15.2.0"
5
5
  end
data/lib/bibliothecary.rb CHANGED
@@ -57,6 +57,13 @@ module Bibliothecary
57
57
  runner.package_managers
58
58
  end
59
59
 
60
+ def self.supported_files
61
+ package_managers.each_with_object({}) do |pm, hash|
62
+ patterns = pm.file_patterns
63
+ hash[pm.platform_name] = patterns unless patterns.empty?
64
+ end
65
+ end
66
+
60
67
  def self.find_manifests(path)
61
68
  runner.find_manifests(path)
62
69
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ecosystems-bibliothecary
3
3
  version: !ruby/object:Gem::Version
4
- version: 15.1.0
4
+ version: 15.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Nesbitt
@@ -128,6 +128,7 @@ files:
128
128
  - lib/bibliothecary/parsers/conda.rb
129
129
  - lib/bibliothecary/parsers/cpan.rb
130
130
  - lib/bibliothecary/parsers/cran.rb
131
+ - lib/bibliothecary/parsers/deno.rb
131
132
  - lib/bibliothecary/parsers/docker.rb
132
133
  - lib/bibliothecary/parsers/dub.rb
133
134
  - lib/bibliothecary/parsers/dvc.rb
@@ -143,6 +144,7 @@ files:
143
144
  - lib/bibliothecary/parsers/meteor.rb
144
145
  - lib/bibliothecary/parsers/mlflow.rb
145
146
  - lib/bibliothecary/parsers/nimble.rb
147
+ - lib/bibliothecary/parsers/nix.rb
146
148
  - lib/bibliothecary/parsers/npm.rb
147
149
  - lib/bibliothecary/parsers/nuget.rb
148
150
  - lib/bibliothecary/parsers/ollama.rb