git-pkgs 0.5.0 → 0.6.1

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[:commit][: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[:commit][: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,17 +18,22 @@ 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
+
27
+ return empty_result("No dependencies found") unless current_commit
28
+
29
+ snapshots = current_commit.dependency_snapshots_dataset.eager(:manifest)
27
30
 
28
31
  if @options[:ecosystem]
29
32
  snapshots = snapshots.where(ecosystem: @options[:ecosystem])
30
33
  end
31
34
 
35
+ snapshots = snapshots.all
36
+
32
37
  if snapshots.empty?
33
38
  empty_result "No dependencies found"
34
39
  return
@@ -40,7 +45,7 @@ module Git
40
45
  names = snapshots.map(&:name).uniq
41
46
 
42
47
  all_changes = Models::DependencyChange
43
- .includes(:commit)
48
+ .eager(:commit)
44
49
  .where(manifest_id: manifest_ids, name: names)
45
50
  .to_a
46
51
 
@@ -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,63 @@ 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
+ .select(Sequel[:dependency_changes][:name], Sequel[:dependency_changes][:ecosystem])
83
+ .select_append { count.function.*.as(:change_count) }
84
+ .group(Sequel[:dependency_changes][:name], Sequel[:dependency_changes][:ecosystem])
85
+ .order(Sequel.desc(:change_count))
84
86
  .limit(10)
85
- .count
87
+ .all
86
88
 
87
- data[:most_changed] = most_changed.map do |(name, eco), count|
88
- { name: name, ecosystem: eco, changes: count }
89
+ data[:most_changed] = most_changed.map do |row|
90
+ { name: row[:name], ecosystem: row[:ecosystem], changes: row[:change_count] }
89
91
  end
90
92
 
91
- manifests = Models::Manifest.all
93
+ manifests = Models::Manifest.dataset
92
94
  manifests = manifests.where(ecosystem: ecosystem) if ecosystem
93
95
 
94
- manifest_ids = manifests.pluck(:id)
96
+ manifest_ids = manifests.select_map(:id)
95
97
  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
98
+ .join(:commits, id: :commit_id)
99
+ .where(Sequel[:dependency_changes][:manifest_id] => manifest_ids)
100
+ change_counts_query = change_counts_query.where { Sequel[:commits][:committed_at] >= since_time } if since_time
101
+ change_counts_query = change_counts_query.where { Sequel[:commits][:committed_at] <= until_time } if until_time
102
+ change_counts = change_counts_query.group_and_count(Sequel[:dependency_changes][:manifest_id]).as_hash(:manifest_id, :count)
101
103
 
102
- data[:manifests] = manifests.map do |manifest|
104
+ data[:manifests] = manifests.all.map do |manifest|
103
105
  { path: manifest.path, ecosystem: manifest.ecosystem, changes: change_counts[manifest.id] || 0 }
104
106
  end
105
107
 
108
+ top_authors = changes
109
+ .where(Sequel[:dependency_changes][:change_type] => "added")
110
+ .group_and_count(Sequel[:commits][:author_name])
111
+ .order(Sequel.desc(:count))
112
+ .limit(5)
113
+ .as_hash(:author_name, :count)
114
+
115
+ data[:top_authors] = top_authors.map { |name, count| { name: name, added: count } }
116
+
106
117
  data
107
118
  end
108
119
 
@@ -159,6 +170,15 @@ module Git
159
170
  data[:manifests].each do |m|
160
171
  puts " #{m[:path]} (#{m[:ecosystem]}): #{m[:changes]} changes"
161
172
  end
173
+
174
+ if data[:top_authors]&.any?
175
+ puts
176
+ puts "Top Authors (by deps added)"
177
+ puts "-" * 27
178
+ data[:top_authors].each do |author|
179
+ puts " #{author[:added].to_s.rjust(4)} #{author[:name]}"
180
+ end
181
+ end
162
182
  end
163
183
 
164
184
  def output_by_author
@@ -166,18 +186,18 @@ module Git
166
186
  until_time = @options[:until] ? parse_time(@options[:until]) : nil
167
187
 
168
188
  changes = Models::DependencyChange
169
- .joins(:commit)
170
- .where(change_type: "added")
189
+ .join(:commits, id: :commit_id)
190
+ .where(Sequel[:dependency_changes][:change_type] => "added")
171
191
 
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
192
+ changes = changes.where(Sequel[:dependency_changes][:ecosystem] => @options[:ecosystem]) if @options[:ecosystem]
193
+ changes = changes.where { Sequel[:commits][:committed_at] >= since_time } if since_time
194
+ changes = changes.where { Sequel[:commits][:committed_at] <= until_time } if until_time
175
195
 
176
196
  counts = changes
177
- .group("commits.author_name")
178
- .order("count_all DESC")
197
+ .group_and_count(Sequel[:commits][:author_name])
198
+ .order(Sequel.desc(:count))
179
199
  .limit(@options[:limit] || 20)
180
- .count
200
+ .as_hash(:author_name, :count)
181
201
 
182
202
  if counts.empty?
183
203
  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