@@ -13,9 +13,7 @@ def initialize(args)
1313
1414 def run
1515 repo = Repository . new
16- require_database ( repo )
17-
18- Database . connect ( repo . git_dir )
16+ use_stateless = @options [ :stateless ] || !Database . exists? ( repo . git_dir )
1917
2018 from_ref , to_ref = parse_range_argument
2119 from_ref ||= @options [ :from ]
@@ -30,6 +28,46 @@ def run
3028 error "Could not resolve '#{ from_ref } '. Check that the ref exists." unless from_sha
3129 error "Could not resolve '#{ to_ref } '. Check that the ref exists." unless to_sha
3230
31+ if use_stateless
32+ run_stateless ( repo , from_sha , to_sha )
33+ else
34+ run_with_database ( repo , from_sha , to_sha )
35+ end
36+ end
37+
38+ def run_stateless ( repo , from_sha , to_sha )
39+ from_commit = repo . lookup ( from_sha )
40+ to_commit = repo . lookup ( to_sha )
41+
42+ analyzer = Analyzer . new ( repo )
43+ diff = analyzer . diff_commits ( from_commit , to_commit )
44+
45+ if @options [ :ecosystem ]
46+ diff [ :added ] = diff [ :added ] . select { |d | d [ :ecosystem ] == @options [ :ecosystem ] }
47+ diff [ :modified ] = diff [ :modified ] . select { |d | d [ :ecosystem ] == @options [ :ecosystem ] }
48+ diff [ :removed ] = diff [ :removed ] . select { |d | d [ :ecosystem ] == @options [ :ecosystem ] }
49+ end
50+
51+ if diff [ :added ] . empty? && diff [ :modified ] . empty? && diff [ :removed ] . empty?
52+ if @options [ :format ] == "json"
53+ require "json"
54+ puts JSON . pretty_generate ( { from : from_sha [ 0 ..7 ] , to : to_sha [ 0 ..7 ] , added : [ ] , modified : [ ] , removed : [ ] } )
55+ else
56+ empty_result "No dependency changes between #{ from_sha [ 0 ..7 ] } and #{ to_sha [ 0 ..7 ] } "
57+ end
58+ return
59+ end
60+
61+ if @options [ :format ] == "json"
62+ output_json_stateless ( from_sha , to_sha , diff )
63+ else
64+ paginate { output_text_stateless ( from_sha , to_sha , diff ) }
65+ end
66+ end
67+
68+ def run_with_database ( repo , from_sha , to_sha )
69+ Database . connect ( repo . git_dir )
70+
3371 from_commit = Models ::Commit . find_or_create_from_repo ( repo , from_sha )
3472 to_commit = Models ::Commit . find_or_create_from_repo ( repo , to_sha )
3573
@@ -154,6 +192,81 @@ def output_json(from_commit, to_commit, changes)
154192 puts JSON . pretty_generate ( data )
155193 end
156194
195+ def output_text_stateless ( from_sha , to_sha , diff )
196+ puts "Dependency changes from #{ from_sha [ 0 ..7 ] } to #{ to_sha [ 0 ..7 ] } :"
197+ puts
198+
199+ if diff [ :added ] . any?
200+ puts Color . green ( "Added:" )
201+ diff [ :added ] . group_by { |d | d [ :name ] } . each do |name , pkg_changes |
202+ latest = pkg_changes . last
203+ puts Color . green ( " + #{ name } #{ latest [ :requirement ] } (#{ latest [ :manifest_path ] } )" )
204+ end
205+ puts
206+ end
207+
208+ if diff [ :modified ] . any?
209+ puts Color . yellow ( "Modified:" )
210+ diff [ :modified ] . group_by { |d | d [ :name ] } . each do |name , pkg_changes |
211+ latest = pkg_changes . last
212+ puts Color . yellow ( " ~ #{ name } #{ latest [ :previous_requirement ] } -> #{ latest [ :requirement ] } " )
213+ end
214+ puts
215+ end
216+
217+ if diff [ :removed ] . any?
218+ puts Color . red ( "Removed:" )
219+ diff [ :removed ] . group_by { |d | d [ :name ] } . each do |name , pkg_changes |
220+ latest = pkg_changes . last
221+ puts Color . red ( " - #{ name } (was #{ latest [ :requirement ] } )" )
222+ end
223+ puts
224+ end
225+
226+ added_count = Color . green ( "+#{ diff [ :added ] . map { |d | d [ :name ] } . uniq . count } " )
227+ removed_count = Color . red ( "-#{ diff [ :removed ] . map { |d | d [ :name ] } . uniq . count } " )
228+ modified_count = Color . yellow ( "~#{ diff [ :modified ] . map { |d | d [ :name ] } . uniq . count } " )
229+ puts "Summary: #{ added_count } #{ removed_count } #{ modified_count } "
230+ end
231+
232+ def output_json_stateless ( from_sha , to_sha , diff )
233+ require "json"
234+
235+ format_change = lambda do |change |
236+ {
237+ name : change [ :name ] ,
238+ ecosystem : change [ :ecosystem ] ,
239+ requirement : change [ :requirement ] ,
240+ manifest : change [ :manifest_path ]
241+ }
242+ end
243+
244+ format_modified = lambda do |change |
245+ {
246+ name : change [ :name ] ,
247+ ecosystem : change [ :ecosystem ] ,
248+ previous_requirement : change [ :previous_requirement ] ,
249+ requirement : change [ :requirement ] ,
250+ manifest : change [ :manifest_path ]
251+ }
252+ end
253+
254+ data = {
255+ from : from_sha [ 0 ..7 ] ,
256+ to : to_sha [ 0 ..7 ] ,
257+ added : diff [ :added ] . map { |c | format_change . call ( c ) } ,
258+ modified : diff [ :modified ] . map { |c | format_modified . call ( c ) } ,
259+ removed : diff [ :removed ] . map { |c | format_change . call ( c ) } ,
260+ summary : {
261+ added : diff [ :added ] . map { |d | d [ :name ] } . uniq . count ,
262+ modified : diff [ :modified ] . map { |d | d [ :name ] } . uniq . count ,
263+ removed : diff [ :removed ] . map { |d | d [ :name ] } . uniq . count
264+ }
265+ }
266+
267+ puts JSON . pretty_generate ( data )
268+ end
269+
157270 def parse_range_argument
158271 return [ nil , nil ] if @args . empty?
159272
@@ -203,6 +316,10 @@ def parse_options
203316 options [ :no_pager ] = true
204317 end
205318
319+ opts . on ( "--stateless" , "Parse manifests directly without database" ) do
320+ options [ :stateless ] = true
321+ end
322+
206323 opts . on ( "-h" , "--help" , "Show this help" ) do
207324 puts opts
208325 exit
0 commit comments