Skip to content
This repository was archived by the owner on Jan 22, 2026. It is now read-only.

Commit c040a11

Browse files
committed
Add configuration options for ecosystems and ignored files/directories
1 parent e5f8b17 commit c040a11

File tree

6 files changed

+308
-3
lines changed

6 files changed

+308
-3
lines changed

lib/git/pkgs.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
require_relative "pkgs/version"
44
require_relative "pkgs/output"
55
require_relative "pkgs/color"
6+
require_relative "pkgs/config"
67
require_relative "pkgs/cli"
78
require_relative "pkgs/database"
89
require_relative "pkgs/repository"

lib/git/pkgs/analyzer.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ class Analyzer
2424
Podfile Podfile.lock *.podspec *.podspec.json
2525
packages.config packages.lock.json Project.json Project.lock.json
2626
*.nuspec paket.lock *.csproj project.assets.json
27-
cyclonedx.xml cyclonedx.json *.cdx.xml *.cdx.json
28-
*.spdx *.spdx.json
2927
bower.json bentofile.yaml
3028
META.json META.yml
3129
environment.yml environment.yaml
@@ -56,6 +54,7 @@ class Analyzer
5654
def initialize(repository)
5755
@repository = repository
5856
@blob_cache = {}
57+
Config.configure_bibliothecary
5958
end
6059

6160
# Quick check if any paths might be manifests (fast regex check)
@@ -262,6 +261,7 @@ def parse_manifest_by_oid(blob_oid, manifest_path)
262261
return nil unless content
263262

264263
result = Bibliothecary.analyse_file(manifest_path, content).first
264+
result = nil if result && Config.filter_ecosystem?(result[:platform])
265265
@blob_cache[cache_key] = { result: result, hits: 0 }
266266
result
267267
end

lib/git/pkgs/commands/diff_driver.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class DiffDriver
4242
def initialize(args)
4343
@args = args
4444
@options = parse_options
45+
Config.configure_bibliothecary
4546
end
4647

4748
def run
@@ -132,6 +133,7 @@ def parse_deps(path, content)
132133

133134
result = Bibliothecary.analyse_file(path, content).first
134135
return {} unless result
136+
return {} if Config.filter_ecosystem?(result[:platform])
135137

136138
result[:dependencies].map { |d| [d[:name], d] }.to_h
137139
rescue StandardError

lib/git/pkgs/commands/info.rb

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ def initialize(args)
1212
end
1313

1414
def run
15+
if @options[:ecosystems]
16+
output_ecosystems
17+
return
18+
end
19+
1520
repo = Repository.new
1621
require_database(repo)
1722

@@ -77,6 +82,61 @@ def run
7782
end
7883
end
7984

85+
def output_ecosystems
86+
require "bibliothecary"
87+
88+
all_ecosystems = Bibliothecary::Parsers.constants.map do |c|
89+
parser = Bibliothecary::Parsers.const_get(c)
90+
parser.platform_name if parser.respond_to?(:platform_name)
91+
end.compact.sort
92+
93+
configured = Config.ecosystems
94+
filtering = configured.any?
95+
96+
puts "Available Ecosystems"
97+
puts "=" * 40
98+
puts
99+
100+
enabled_ecos = []
101+
disabled_ecos = []
102+
103+
all_ecosystems.each do |eco|
104+
if Config.filter_ecosystem?(eco)
105+
remote = Config.remote_ecosystem?(eco)
106+
disabled_ecos << { name: eco, remote: remote }
107+
else
108+
enabled_ecos << eco
109+
end
110+
end
111+
112+
puts "Enabled:"
113+
if enabled_ecos.any?
114+
enabled_ecos.each { |eco| puts " #{Color.green(eco)}" }
115+
else
116+
puts " (none)"
117+
end
118+
119+
puts
120+
puts "Disabled:"
121+
if disabled_ecos.any?
122+
disabled_ecos.each do |eco|
123+
suffix = eco[:remote] ? " (remote)" : ""
124+
puts " #{eco[:name]}#{suffix}"
125+
end
126+
else
127+
puts " (none)"
128+
end
129+
130+
puts
131+
if filtering
132+
puts "Filtering: only #{configured.join(', ')}"
133+
else
134+
puts "All local ecosystems enabled"
135+
end
136+
puts "Remote ecosystems require explicit opt-in"
137+
puts "Configure with: git config --add pkgs.ecosystems <name>"
138+
end
139+
80140
def format_size(bytes)
81141
units = %w[B KB MB GB]
82142
unit_index = 0
@@ -94,7 +154,11 @@ def parse_options
94154
options = {}
95155

96156
parser = OptionParser.new do |opts|
97-
opts.banner = "Usage: git pkgs info"
157+
opts.banner = "Usage: git pkgs info [options]"
158+
159+
opts.on("--ecosystems", "Show available ecosystems and filter status") do
160+
options[:ecosystems] = true
161+
end
98162

99163
opts.on("-h", "--help", "Show this help") do
100164
puts opts

lib/git/pkgs/config.rb

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# frozen_string_literal: true
2+
3+
require "bibliothecary"
4+
5+
module Git
6+
module Pkgs
7+
module Config
8+
# Ecosystems that require remote parsing services - disabled by default
9+
REMOTE_ECOSYSTEMS = %w[carthage clojars hackage hex swiftpm].freeze
10+
11+
# File patterns ignored by default (SBOM formats not supported)
12+
DEFAULT_IGNORED_FILES = %w[
13+
cyclonedx.xml
14+
cyclonedx.json
15+
*.cdx.xml
16+
*.cdx.json
17+
*.spdx
18+
*.spdx.json
19+
].freeze
20+
21+
def self.ignored_dirs
22+
@ignored_dirs ||= read_config_list("pkgs.ignoredDirs")
23+
end
24+
25+
def self.ignored_files
26+
@ignored_files ||= read_config_list("pkgs.ignoredFiles")
27+
end
28+
29+
def self.ecosystems
30+
@ecosystems ||= read_config_list("pkgs.ecosystems")
31+
end
32+
33+
def self.configure_bibliothecary
34+
dirs = ignored_dirs
35+
files = DEFAULT_IGNORED_FILES + ignored_files
36+
37+
Bibliothecary.configure do |config|
38+
config.ignored_dirs += dirs unless dirs.empty?
39+
config.ignored_files += files
40+
end
41+
end
42+
43+
def self.filter_ecosystem?(platform)
44+
platform_lower = platform.to_s.downcase
45+
46+
# Remote ecosystems are disabled unless explicitly enabled
47+
if REMOTE_ECOSYSTEMS.include?(platform_lower)
48+
return !ecosystems.map(&:downcase).include?(platform_lower)
49+
end
50+
51+
# If no filter configured, allow all non-remote ecosystems
52+
return false if ecosystems.empty?
53+
54+
# Otherwise, only allow explicitly listed ecosystems
55+
!ecosystems.map(&:downcase).include?(platform_lower)
56+
end
57+
58+
def self.remote_ecosystem?(platform)
59+
REMOTE_ECOSYSTEMS.include?(platform.to_s.downcase)
60+
end
61+
62+
def self.reset!
63+
@ignored_dirs = nil
64+
@ignored_files = nil
65+
@ecosystems = nil
66+
end
67+
68+
def self.read_config_list(key)
69+
`git config --get-all #{key} 2>/dev/null`.split("\n").map(&:strip).reject(&:empty?)
70+
end
71+
end
72+
end
73+
end

test/git/pkgs/test_config.rb

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
# frozen_string_literal: true
2+
3+
require "test_helper"
4+
5+
class Git::Pkgs::TestConfig < Minitest::Test
6+
include TestHelpers
7+
8+
def setup
9+
create_test_repo
10+
Git::Pkgs::Config.reset!
11+
end
12+
13+
def teardown
14+
cleanup_test_repo
15+
Git::Pkgs::Config.reset!
16+
end
17+
18+
def test_ignored_dirs_returns_empty_array_when_not_configured
19+
Dir.chdir(@test_dir) do
20+
assert_equal [], Git::Pkgs::Config.ignored_dirs
21+
end
22+
end
23+
24+
def test_ignored_dirs_returns_configured_values
25+
Dir.chdir(@test_dir) do
26+
system("git config --add pkgs.ignoredDirs third_party", out: File::NULL)
27+
system("git config --add pkgs.ignoredDirs external", out: File::NULL)
28+
Git::Pkgs::Config.reset!
29+
30+
assert_equal ["third_party", "external"], Git::Pkgs::Config.ignored_dirs
31+
end
32+
end
33+
34+
def test_ignored_files_returns_empty_array_when_not_configured
35+
Dir.chdir(@test_dir) do
36+
assert_equal [], Git::Pkgs::Config.ignored_files
37+
end
38+
end
39+
40+
def test_ignored_files_returns_configured_values
41+
Dir.chdir(@test_dir) do
42+
system("git config --add pkgs.ignoredFiles test/fixtures/package.json", out: File::NULL)
43+
Git::Pkgs::Config.reset!
44+
45+
assert_equal ["test/fixtures/package.json"], Git::Pkgs::Config.ignored_files
46+
end
47+
end
48+
49+
def test_ecosystems_returns_empty_array_when_not_configured
50+
Dir.chdir(@test_dir) do
51+
assert_equal [], Git::Pkgs::Config.ecosystems
52+
end
53+
end
54+
55+
def test_ecosystems_returns_configured_values
56+
Dir.chdir(@test_dir) do
57+
system("git config --add pkgs.ecosystems rubygems", out: File::NULL)
58+
system("git config --add pkgs.ecosystems npm", out: File::NULL)
59+
Git::Pkgs::Config.reset!
60+
61+
assert_equal ["rubygems", "npm"], Git::Pkgs::Config.ecosystems
62+
end
63+
end
64+
65+
def test_filter_ecosystem_returns_false_for_local_when_no_ecosystems_configured
66+
Dir.chdir(@test_dir) do
67+
refute Git::Pkgs::Config.filter_ecosystem?("rubygems")
68+
refute Git::Pkgs::Config.filter_ecosystem?("npm")
69+
end
70+
end
71+
72+
def test_filter_ecosystem_returns_true_for_remote_when_no_ecosystems_configured
73+
Dir.chdir(@test_dir) do
74+
assert Git::Pkgs::Config.filter_ecosystem?("carthage")
75+
assert Git::Pkgs::Config.filter_ecosystem?("clojars")
76+
assert Git::Pkgs::Config.filter_ecosystem?("hackage")
77+
assert Git::Pkgs::Config.filter_ecosystem?("hex")
78+
assert Git::Pkgs::Config.filter_ecosystem?("swiftpm")
79+
end
80+
end
81+
82+
def test_filter_ecosystem_allows_remote_when_explicitly_enabled
83+
Dir.chdir(@test_dir) do
84+
system("git config --add pkgs.ecosystems carthage", out: File::NULL)
85+
Git::Pkgs::Config.reset!
86+
87+
refute Git::Pkgs::Config.filter_ecosystem?("carthage")
88+
end
89+
end
90+
91+
def test_filter_ecosystem_returns_false_for_included_ecosystem
92+
Dir.chdir(@test_dir) do
93+
system("git config --add pkgs.ecosystems rubygems", out: File::NULL)
94+
system("git config --add pkgs.ecosystems npm", out: File::NULL)
95+
Git::Pkgs::Config.reset!
96+
97+
refute Git::Pkgs::Config.filter_ecosystem?("rubygems")
98+
refute Git::Pkgs::Config.filter_ecosystem?("npm")
99+
end
100+
end
101+
102+
def test_filter_ecosystem_returns_true_for_excluded_ecosystem
103+
Dir.chdir(@test_dir) do
104+
system("git config --add pkgs.ecosystems rubygems", out: File::NULL)
105+
Git::Pkgs::Config.reset!
106+
107+
assert Git::Pkgs::Config.filter_ecosystem?("npm")
108+
assert Git::Pkgs::Config.filter_ecosystem?("pypi")
109+
end
110+
end
111+
112+
def test_filter_ecosystem_is_case_insensitive
113+
Dir.chdir(@test_dir) do
114+
system("git config --add pkgs.ecosystems RubyGems", out: File::NULL)
115+
Git::Pkgs::Config.reset!
116+
117+
refute Git::Pkgs::Config.filter_ecosystem?("rubygems")
118+
refute Git::Pkgs::Config.filter_ecosystem?("RUBYGEMS")
119+
end
120+
end
121+
122+
def test_remote_ecosystem_returns_true_for_remote_ecosystems
123+
assert Git::Pkgs::Config.remote_ecosystem?("carthage")
124+
assert Git::Pkgs::Config.remote_ecosystem?("clojars")
125+
assert Git::Pkgs::Config.remote_ecosystem?("hackage")
126+
assert Git::Pkgs::Config.remote_ecosystem?("hex")
127+
assert Git::Pkgs::Config.remote_ecosystem?("swiftpm")
128+
end
129+
130+
def test_remote_ecosystem_returns_false_for_local_ecosystems
131+
refute Git::Pkgs::Config.remote_ecosystem?("rubygems")
132+
refute Git::Pkgs::Config.remote_ecosystem?("npm")
133+
refute Git::Pkgs::Config.remote_ecosystem?("pypi")
134+
end
135+
136+
def test_configure_bibliothecary_adds_ignored_dirs
137+
Dir.chdir(@test_dir) do
138+
system("git config --add pkgs.ignoredDirs my_vendor", out: File::NULL)
139+
Git::Pkgs::Config.reset!
140+
141+
original_dirs = Bibliothecary.configuration.ignored_dirs.dup
142+
Git::Pkgs::Config.configure_bibliothecary
143+
144+
assert_includes Bibliothecary.configuration.ignored_dirs, "my_vendor"
145+
146+
# Clean up
147+
Bibliothecary.configuration.ignored_dirs = original_dirs
148+
end
149+
end
150+
151+
def test_configure_bibliothecary_adds_ignored_files
152+
Dir.chdir(@test_dir) do
153+
system("git config --add pkgs.ignoredFiles fixtures/Gemfile", out: File::NULL)
154+
Git::Pkgs::Config.reset!
155+
156+
original_files = Bibliothecary.configuration.ignored_files.dup
157+
Git::Pkgs::Config.configure_bibliothecary
158+
159+
assert_includes Bibliothecary.configuration.ignored_files, "fixtures/Gemfile"
160+
161+
# Clean up
162+
Bibliothecary.configuration.ignored_files = original_files
163+
end
164+
end
165+
end

0 commit comments

Comments
 (0)