git-pkgs 0.5.0 → 0.6.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.
@@ -23,19 +23,19 @@ module Git
23
23
 
24
24
  # Search for dependencies matching the pattern
25
25
  query = Models::DependencyChange
26
- .joins(:manifest)
27
- .where("dependency_changes.name LIKE ?", "%#{pattern}%")
26
+ .join(:manifests, id: :manifest_id)
27
+ .where(Sequel.like(Sequel[:dependency_changes][:name], "%#{pattern}%"))
28
28
 
29
29
  if @options[:ecosystem]
30
- query = query.where(ecosystem: @options[:ecosystem])
30
+ query = query.where(Sequel[:dependency_changes][:ecosystem] => @options[:ecosystem])
31
31
  end
32
32
 
33
33
  if @options[:direct]
34
- query = query.where(manifests: { kind: "manifest" })
34
+ query = query.where(Sequel[:manifests][:kind] => "manifest")
35
35
  end
36
36
 
37
37
  # Get unique dependency names
38
- matches = query.distinct.pluck(:name, :ecosystem)
38
+ matches = query.distinct.select_map([Sequel[:dependency_changes][:name], Sequel[:dependency_changes][:ecosystem]])
39
39
 
40
40
  if matches.empty?
41
41
  empty_result "No dependencies found matching '#{pattern}'"
@@ -70,12 +70,14 @@ module Git
70
70
  results = matches.map do |name, platform|
71
71
  changes = Models::DependencyChange
72
72
  .where(name: name, ecosystem: platform)
73
- .includes(:commit)
74
- .order("commits.committed_at ASC")
73
+ .eager(:commit)
74
+ .association_join(:commit)
75
+ .order(Sequel[:commits][:committed_at])
76
+ .all
75
77
 
76
78
  first = changes.first
77
79
  last = changes.last
78
- current = changes.where(change_type: %w[added modified]).last
80
+ current = changes.select { |c| %w[added modified].include?(c.change_type) }.last
79
81
 
80
82
  {
81
83
  name: name,
@@ -94,8 +96,10 @@ module Git
94
96
  def dependency_summary(name, platform)
95
97
  changes = Models::DependencyChange
96
98
  .where(name: name, ecosystem: platform)
97
- .includes(:commit)
98
- .order("commits.committed_at ASC")
99
+ .eager(:commit)
100
+ .association_join(:commit)
101
+ .order(Sequel[:commits][:committed_at])
102
+ .all
99
103
 
100
104
  first = changes.first
101
105
  last = changes.last
@@ -106,7 +110,7 @@ module Git
106
110
  if last.change_type == "removed"
107
111
  parts << "removed #{last.commit.committed_at.strftime('%Y-%m-%d')}"
108
112
  else
109
- current = changes.where(change_type: %w[added modified]).last
113
+ current = changes.select { |c| %w[added modified].include?(c.change_type) }.last
110
114
  parts << "current: #{current&.requirement || 'unknown'}"
111
115
  end
112
116
 
@@ -26,13 +26,15 @@ module Git
26
26
  error "Commit '#{sha[0..7]}' not in database. Run 'git pkgs update' to index new commits." unless commit
27
27
 
28
28
  changes = Models::DependencyChange
29
- .includes(:commit, :manifest)
29
+ .eager(:commit, :manifest)
30
30
  .where(commit_id: commit.id)
31
31
 
32
32
  if @options[:ecosystem]
33
33
  changes = changes.where(ecosystem: @options[:ecosystem])
34
34
  end
35
35
 
36
+ changes = changes.all
37
+
36
38
  if changes.empty?
37
39
  empty_result "No dependency changes in #{commit.short_sha}"
38
40
  return
@@ -18,12 +18,12 @@ module Git
18
18
  Database.connect(repo.git_dir)
19
19
 
20
20
  branch_name = @options[:branch] || repo.default_branch
21
- branch = Models::Branch.find_by(name: branch_name)
21
+ branch = Models::Branch.first(name: branch_name)
22
22
 
23
23
  error "No analysis found for branch '#{branch_name}'. Run 'git pkgs init' first." unless branch&.last_analyzed_sha
24
24
 
25
- current_commit = Models::Commit.find_by(sha: branch.last_analyzed_sha)
26
- snapshots = current_commit&.dependency_snapshots&.includes(:manifest) || []
25
+ current_commit = Models::Commit.first(sha: branch.last_analyzed_sha)
26
+ snapshots = current_commit&.dependency_snapshots&.eager(:manifest) || []
27
27
 
28
28
  if @options[:ecosystem]
29
29
  snapshots = snapshots.where(ecosystem: @options[:ecosystem])
@@ -40,7 +40,7 @@ module Git
40
40
  names = snapshots.map(&:name).uniq
41
41
 
42
42
  all_changes = Models::DependencyChange
43
- .includes(:commit)
43
+ .eager(:commit)
44
44
  .where(manifest_id: manifest_ids, name: names)
45
45
  .to_a
46
46
 
@@ -18,7 +18,7 @@ module Git
18
18
  Database.connect(repo.git_dir)
19
19
 
20
20
  branch_name = @options[:branch] || repo.default_branch
21
- branch = Models::Branch.find_by(name: branch_name)
21
+ branch = Models::Branch.first(name: branch_name)
22
22
 
23
23
  if @options[:by_author]
24
24
  output_by_author
@@ -39,9 +39,9 @@ module Git
39
39
  since_time = @options[:since] ? parse_time(@options[:since]) : nil
40
40
  until_time = @options[:until] ? parse_time(@options[:until]) : nil
41
41
 
42
- commits = branch&.commits || Models::Commit.none
43
- commits = commits.where("committed_at >= ?", since_time) if since_time
44
- commits = commits.where("committed_at <= ?", until_time) if until_time
42
+ commits = branch ? branch.commits_dataset : Models::Commit.where(false)
43
+ commits = commits.where { committed_at >= since_time } if since_time
44
+ commits = commits.where { committed_at <= until_time } if until_time
45
45
 
46
46
  data = {
47
47
  branch: branch_name,
@@ -57,52 +57,62 @@ module Git
57
57
  }
58
58
 
59
59
  if branch&.last_analyzed_sha
60
- current_commit = Models::Commit.find_by(sha: branch.last_analyzed_sha)
61
- snapshots = current_commit&.dependency_snapshots || []
60
+ current_commit = Models::Commit.first(sha: branch.last_analyzed_sha)
61
+ snapshots = current_commit ? current_commit.dependency_snapshots_dataset : Models::DependencySnapshot.where(false)
62
62
  snapshots = snapshots.where(ecosystem: ecosystem) if ecosystem
63
63
 
64
64
  data[:current_dependencies] = {
65
65
  total: snapshots.count,
66
- by_platform: snapshots.group(:ecosystem).count,
67
- by_type: snapshots.group(:dependency_type).count
66
+ by_platform: snapshots.group_and_count(:ecosystem).as_hash(:ecosystem, :count),
67
+ by_type: snapshots.group_and_count(:dependency_type).as_hash(:dependency_type, :count)
68
68
  }
69
69
  end
70
70
 
71
- changes = Models::DependencyChange.joins(:commit)
72
- changes = changes.where(ecosystem: ecosystem) if ecosystem
73
- changes = changes.where("commits.committed_at >= ?", since_time) if since_time
74
- changes = changes.where("commits.committed_at <= ?", until_time) if until_time
71
+ changes = Models::DependencyChange.join(:commits, id: :commit_id)
72
+ changes = changes.where(Sequel[:dependency_changes][:ecosystem] => ecosystem) if ecosystem
73
+ changes = changes.where { Sequel[:commits][:committed_at] >= since_time } if since_time
74
+ changes = changes.where { Sequel[:commits][:committed_at] <= until_time } if until_time
75
75
 
76
76
  data[:changes] = {
77
77
  total: changes.count,
78
- by_type: changes.group(:change_type).count
78
+ by_type: changes.group_and_count(Sequel[:dependency_changes][:change_type]).as_hash(:change_type, :count)
79
79
  }
80
80
 
81
81
  most_changed = changes
82
- .group(:name, :ecosystem)
83
- .order("count_all DESC")
82
+ .group(Sequel[:dependency_changes][:name], Sequel[:dependency_changes][:ecosystem])
83
+ .order(Sequel.desc(:count))
84
84
  .limit(10)
85
- .count
85
+ .select_append { count.function.*.as(:count) }
86
+ .select_map([:name, :ecosystem, :count])
86
87
 
87
- data[:most_changed] = most_changed.map do |(name, eco), count|
88
+ data[:most_changed] = most_changed.map do |name, eco, count|
88
89
  { name: name, ecosystem: eco, changes: count }
89
90
  end
90
91
 
91
- manifests = Models::Manifest.all
92
+ manifests = Models::Manifest.dataset
92
93
  manifests = manifests.where(ecosystem: ecosystem) if ecosystem
93
94
 
94
- manifest_ids = manifests.pluck(:id)
95
+ manifest_ids = manifests.select_map(:id)
95
96
  change_counts_query = Models::DependencyChange
96
- .joins(:commit)
97
- .where(manifest_id: manifest_ids)
98
- change_counts_query = change_counts_query.where("commits.committed_at >= ?", since_time) if since_time
99
- change_counts_query = change_counts_query.where("commits.committed_at <= ?", until_time) if until_time
100
- change_counts = change_counts_query.group(:manifest_id).count
97
+ .join(:commits, id: :commit_id)
98
+ .where(Sequel[:dependency_changes][:manifest_id] => manifest_ids)
99
+ change_counts_query = change_counts_query.where { Sequel[:commits][:committed_at] >= since_time } if since_time
100
+ change_counts_query = change_counts_query.where { Sequel[:commits][:committed_at] <= until_time } if until_time
101
+ change_counts = change_counts_query.group_and_count(Sequel[:dependency_changes][:manifest_id]).as_hash(:manifest_id, :count)
101
102
 
102
- data[:manifests] = manifests.map do |manifest|
103
+ data[:manifests] = manifests.all.map do |manifest|
103
104
  { path: manifest.path, ecosystem: manifest.ecosystem, changes: change_counts[manifest.id] || 0 }
104
105
  end
105
106
 
107
+ top_authors = changes
108
+ .where(Sequel[:dependency_changes][:change_type] => "added")
109
+ .group_and_count(Sequel[:commits][:author_name])
110
+ .order(Sequel.desc(:count))
111
+ .limit(5)
112
+ .as_hash(:author_name, :count)
113
+
114
+ data[:top_authors] = top_authors.map { |name, count| { name: name, added: count } }
115
+
106
116
  data
107
117
  end
108
118
 
@@ -159,6 +169,15 @@ module Git
159
169
  data[:manifests].each do |m|
160
170
  puts " #{m[:path]} (#{m[:ecosystem]}): #{m[:changes]} changes"
161
171
  end
172
+
173
+ if data[:top_authors]&.any?
174
+ puts
175
+ puts "Top Authors (by deps added)"
176
+ puts "-" * 27
177
+ data[:top_authors].each do |author|
178
+ puts " #{author[:added].to_s.rjust(4)} #{author[:name]}"
179
+ end
180
+ end
162
181
  end
163
182
 
164
183
  def output_by_author
@@ -166,18 +185,18 @@ module Git
166
185
  until_time = @options[:until] ? parse_time(@options[:until]) : nil
167
186
 
168
187
  changes = Models::DependencyChange
169
- .joins(:commit)
170
- .where(change_type: "added")
188
+ .join(:commits, id: :commit_id)
189
+ .where(Sequel[:dependency_changes][:change_type] => "added")
171
190
 
172
- changes = changes.where(ecosystem: @options[:ecosystem]) if @options[:ecosystem]
173
- changes = changes.where("commits.committed_at >= ?", since_time) if since_time
174
- changes = changes.where("commits.committed_at <= ?", until_time) if until_time
191
+ changes = changes.where(Sequel[:dependency_changes][:ecosystem] => @options[:ecosystem]) if @options[:ecosystem]
192
+ changes = changes.where { Sequel[:commits][:committed_at] >= since_time } if since_time
193
+ changes = changes.where { Sequel[:commits][:committed_at] <= until_time } if until_time
175
194
 
176
195
  counts = changes
177
- .group("commits.author_name")
178
- .order("count_all DESC")
196
+ .group_and_count(Sequel[:commits][:author_name])
197
+ .order(Sequel.desc(:count))
179
198
  .limit(@options[:limit] || 20)
180
- .count
199
+ .as_hash(:author_name, :count)
181
200
 
182
201
  if counts.empty?
183
202
  empty_result "No dependency additions found"
@@ -24,21 +24,23 @@ module Git
24
24
  error "No dependency data for commit #{commit_sha[0, 7]}. Run 'git pkgs update' to index new commits." unless commit
25
25
 
26
26
  # Get current snapshots
27
- snapshots = commit.dependency_snapshots.includes(:manifest)
27
+ snapshots = commit.dependency_snapshots_dataset.eager(:manifest)
28
28
 
29
29
  if @options[:ecosystem]
30
30
  snapshots = snapshots.where(ecosystem: @options[:ecosystem])
31
31
  end
32
32
 
33
- if snapshots.empty?
33
+ snapshots_list = snapshots.all
34
+
35
+ if snapshots_list.empty?
34
36
  empty_result "No dependencies found"
35
37
  return
36
38
  end
37
39
 
38
40
  # Group by manifest and build tree
39
- grouped = snapshots.group_by { |s| s.manifest }
41
+ grouped = snapshots_list.group_by { |s| s.manifest }
40
42
 
41
- paginate { output_text(grouped, snapshots) }
43
+ paginate { output_text(grouped, snapshots_list) }
42
44
  end
43
45
 
44
46
  def output_text(grouped, snapshots)
@@ -73,19 +75,20 @@ module Git
73
75
  end
74
76
 
75
77
  def find_commit_with_snapshot(sha, repo)
76
- commit = Models::Commit.find_by(sha: sha) ||
77
- Models::Commit.where("sha LIKE ?", "#{sha}%").first
78
+ commit = Models::Commit.first(sha: sha) ||
79
+ Models::Commit.where(Sequel.like(:sha, "#{sha}%")).first
78
80
  return commit if commit&.dependency_snapshots&.any?
79
81
 
80
82
  # Find most recent commit with a snapshot
81
83
  branch_name = @options[:branch] || repo.default_branch
82
- branch = Models::Branch.find_by(name: branch_name)
84
+ branch = Models::Branch.first(name: branch_name)
83
85
  return nil unless branch
84
86
 
85
- branch.commits
86
- .joins(:dependency_snapshots)
87
- .where("commits.committed_at <= ?", commit&.committed_at || Time.now)
88
- .order(committed_at: :desc)
87
+ target_time = commit&.committed_at || Time.now
88
+ branch.commits_dataset
89
+ .join(:dependency_snapshots, commit_id: :id)
90
+ .where { Sequel[:commits][:committed_at] <= target_time }
91
+ .order(Sequel.desc(Sequel[:commits][:committed_at]))
89
92
  .distinct
90
93
  .first
91
94
  end
@@ -18,7 +18,7 @@ module Git
18
18
  Database.connect(repo.git_dir)
19
19
 
20
20
  branch_name = @options[:branch] || repo.default_branch
21
- branch = Models::Branch.find_by(name: branch_name)
21
+ branch = Models::Branch.first(name: branch_name)
22
22
 
23
23
  error "Branch '#{branch_name}' not in database. Run 'git pkgs init --branch=#{branch_name}' first." unless branch
24
24
 
@@ -33,11 +33,11 @@ module Git
33
33
  analyzer = Analyzer.new(repo)
34
34
 
35
35
  # Get current snapshot from last analyzed commit
36
- last_commit = Models::Commit.find_by(sha: since_sha)
36
+ last_commit = Models::Commit.first(sha: since_sha)
37
37
  snapshot = {}
38
38
 
39
39
  if last_commit
40
- last_commit.dependency_snapshots.includes(:manifest).each do |s|
40
+ last_commit.dependency_snapshots.each do |s|
41
41
  key = [s.manifest.path, s.name]
42
42
  snapshot[key] = {
43
43
  ecosystem: s.ecosystem,
@@ -54,24 +54,23 @@ module Git
54
54
 
55
55
  processed = 0
56
56
  dependency_commits = 0
57
- last_position = Models::BranchCommit.where(branch: branch).maximum(:position) || 0
57
+ last_position = Models::BranchCommit.where(branch: branch).max(:position) || 0
58
58
 
59
- info "Updating branch: #{branch_name}"
60
- info "Found #{total} new commits"
59
+ print "Updating #{branch_name}..." unless Git::Pkgs.quiet
61
60
 
62
- ActiveRecord::Base.transaction do
61
+ Database.db.transaction do
63
62
  commits.each do |rugged_commit|
64
63
  processed += 1
65
- print "\rProcessing commit #{processed}/#{total}..." unless Git::Pkgs.quiet
66
64
 
67
65
  result = analyzer.analyze_commit(rugged_commit, snapshot)
68
66
 
69
67
  commit = Models::Commit.find_or_create_from_rugged(rugged_commit)
70
- Models::BranchCommit.find_or_create_by(
68
+ Models::BranchCommit.find_or_create(
71
69
  branch: branch,
72
- commit: commit,
73
- position: last_position + processed
74
- )
70
+ commit: commit
71
+ ) do |bc|
72
+ bc.position = last_position + processed
73
+ end
75
74
 
76
75
  if result && result[:changes].any?
77
76
  dependency_commits += 1
@@ -84,7 +83,7 @@ module Git
84
83
  kind: change[:kind]
85
84
  )
86
85
 
87
- Models::DependencyChange.create!(
86
+ Models::DependencyChange.create(
88
87
  commit: commit,
89
88
  manifest: manifest,
90
89
  name: change[:name],
@@ -99,8 +98,8 @@ module Git
99
98
  snapshot = result[:snapshot]
100
99
 
101
100
  snapshot.each do |(manifest_path, name), dep_info|
102
- manifest = Models::Manifest.find_by(path: manifest_path)
103
- Models::DependencySnapshot.find_or_create_by(
101
+ manifest = Models::Manifest.first(path: manifest_path)
102
+ Models::DependencySnapshot.find_or_create(
104
103
  commit: commit,
105
104
  manifest: manifest,
106
105
  name: name
@@ -116,9 +115,7 @@ module Git
116
115
  branch.update(last_analyzed_sha: current_sha)
117
116
  end
118
117
 
119
- info "\nDone!"
120
- info "Processed #{total} new commits"
121
- info "Found #{dependency_commits} commits with dependency changes"
118
+ info "\r#{' ' * 40}\rUpdated #{branch_name}: #{total} commits (#{dependency_commits} with dependency changes)"
122
119
  end
123
120
 
124
121
  def parse_options
@@ -22,7 +22,7 @@ module Git
22
22
  Database.connect(repo.git_dir)
23
23
 
24
24
  workdir = File.dirname(repo.git_dir)
25
- branch = Models::Branch.find_by(name: @options[:branch] || repo.default_branch)
25
+ branch = Models::Branch.first(name: @options[:branch] || repo.default_branch)
26
26
 
27
27
  unless branch
28
28
  error "Branch not found. Run 'git pkgs init' first."
@@ -31,7 +31,10 @@ module Git
31
31
  snapshots = Models::DependencySnapshot.current_for_branch(branch)
32
32
  snapshots = snapshots.where(ecosystem: @options[:ecosystem]) if @options[:ecosystem]
33
33
 
34
- manifest_paths = snapshots.for_package(name).joins(:manifest).pluck("manifests.path").uniq
34
+ manifest_paths = snapshots.for_package(name)
35
+ .join(:manifests, id: :manifest_id)
36
+ .select_map(Sequel[:manifests][:path])
37
+ .uniq
35
38
 
36
39
  if manifest_paths.empty?
37
40
  empty_result "Package '#{name}' not found in current dependencies"
@@ -23,7 +23,7 @@ module Git
23
23
 
24
24
  # Find the first time this package was added
25
25
  added_change = Models::DependencyChange
26
- .includes(:commit, :manifest)
26
+ .eager(:commit, :manifest)
27
27
  .for_package(package_name)
28
28
  .added
29
29
  .order("commits.committed_at ASC")
@@ -5,9 +5,6 @@ require "bibliothecary"
5
5
  module Git
6
6
  module Pkgs
7
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
8
  # File patterns ignored by default (SBOM formats not supported)
12
9
  DEFAULT_IGNORED_FILES = %w[
13
10
  cyclonedx.xml
@@ -41,24 +38,12 @@ module Git
41
38
  end
42
39
 
43
40
  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
41
  return false if ecosystems.empty?
53
42
 
54
- # Otherwise, only allow explicitly listed ecosystems
43
+ platform_lower = platform.to_s.downcase
55
44
  !ecosystems.map(&:downcase).include?(platform_lower)
56
45
  end
57
46
 
58
- def self.remote_ecosystem?(platform)
59
- REMOTE_ECOSYSTEMS.include?(platform.to_s.downcase)
60
- end
61
-
62
47
  def self.reset!
63
48
  @ignored_dirs = nil
64
49
  @ignored_files = nil