lib/cutting_edge/workers/dependency.rb in cutting_edge-0.1 vs lib/cutting_edge/workers/dependency.rb in cutting_edge-0.2
- old
+ new
@@ -1,46 +1,87 @@
require 'rubygems'
require 'http'
require File.expand_path('../../versions.rb', __FILE__)
require File.expand_path('../../langs.rb', __FILE__)
require File.expand_path('../helpers.rb', __FILE__)
+require 'hashdiff'
class DependencyWorker < GenericWorker
include VersionRequirementComparator
# Order is significant for purposes of calculating results[:outdated]
STATUS_TYPES = [:outdated_major, :outdated_minor, :outdated_patch, :ok, :no_requirement, :unknown]
OUTDATED_TYPES = STATUS_TYPES[0..-4] # Which types indicate an outdated dependency. Used to calculate the total number of out-of-date dependencies.
-
+ EMPTY_STATUS_HASH = STATUS_TYPES.inject({}){|result, type| result[type] = []; result}
+
def perform(identifier, lang, locations, dependency_types, to_addr, auth_token = nil)
log_info 'Running Worker!'
@lang = get_lang(lang)
@provider = get_provider(identifier)
@auth_token = auth_token
- old_dependencies = get_from_store(identifier)
+ old_dependencies = get_from_store(identifier) || {}
begin
dependencies = {:locations => {}}
locations.each do |name, url|
contents = http_get(url)
dependencies[:locations][name] = get_results(@lang.parse_file(name, contents), dependency_types)
end
dependencies.merge!(generate_stats(dependencies[:locations]))
@nothing_changed = dependencies == old_dependencies
- add_to_store(identifier, dependencies) unless @nothing_changed
+ unless @nothing_changed
+ add_to_store(identifier, dependencies)
+ add_to_store("diff-#{identifier}", diff_dependencies(old_dependencies[:locations], dependencies[:locations]))
+ end
ensure
unless @nothing_changed
badge_worker(identifier)
- mail_worker(identifier, to_addr) if to_addr
+ mail_worker(identifier, to_addr) if to_addr && (!old_dependencies.empty? || ::CuttingEdge::ALWAYS_MAIL)
end
GC.start
end
end
private
-
+
+ def diff_dependencies(old, new)
+ base = old ? old : new.transform_values {|_v| empty_status_hash }
+ diff = Hashdiff.diff(base, new)
+ additions = diff.select {|x| x.first == '+'}
+ deletions = diff.select {|x| x.first == '-'}
+ result = {}
+
+ additions.each do |addition|
+ status = parse_diff_status(addition[1])
+ name = addition.last[:name]
+ old_status = deletions.find {|x| x.last[:name] == name}
+ old_status = parse_diff_status(old_status[1]) if old_status
+ result[name] = change_type(old_status, status)
+ end
+ result
+ end
+
+ def parse_diff_status(str)
+ # Hashdiff generates strings of the form "gemfile.ok[1]" to indicate this is the first change to the Hash under the :ok key
+ str.split('.').last.split('[').first.to_sym
+ end
+
+ def change_type(old_status, new_status)
+ case
+ when new_status == :ok
+ :good_change
+ when outdated_type?(new_status) && old_status && STATUS_TYPES.find_index(new_status) > STATUS_TYPES.find_index(old_status)
+ :good_change
+ else
+ :bad_change
+ end
+ end
+
+ def empty_status_hash
+ STATUS_TYPES.inject({}) {|result, type| result[type] = []; result }
+ end
+
def get_results(dependencies, dependency_types)
- results = {}
- STATUS_TYPES.each {|type| results[type] = []}
+ results = empty_status_hash
if dependencies
dependencies.select! {|dep| dependency_types.include?(dep.first.type)}
dependencies.each do |dep, latest_version|
dependency_hash = dependency(dep.name, dep.requirement.to_s, latest_version.to_s, dep.type)
if dependency_hash[:required] == 'unknown'
\ No newline at end of file