churn 0.0.34 → 0.0.35

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b1ef198f417e616080e9ada053a19596286c0ceb
4
+ data.tar.gz: d42960ccea815f89f846123808fd346fb5f5f65b
5
+ SHA512:
6
+ metadata.gz: e92d32eade6ace59e1ed9b663f12d90ba1d1fe91de7d6675fa4910c4e8bb2e95df14d8cf20f53a1dd574c3ed5ea737c965f72c955188399c86ca41d2442bd376
7
+ data.tar.gz: 4a69afaa2311f8847089b8e1b28ee820679e790b9795bbfc843554db832b6d5c48c540930529b4c29ee0ba7a30b0d5559f36fc32ddd6cf5b919c59159a04cc2a
@@ -1,7 +1,6 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
- - rbx-18mode
5
- - rbx-19mode
6
- - 1.8.7
7
- - 2.0.0
4
+ - rbx
5
+ - 2.0.0
6
+ - jruby-19mode
@@ -1,11 +1,12 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- churn (0.0.34)
4
+ churn (0.0.35)
5
5
  chronic (>= 0.2.3)
6
6
  hirb
7
7
  json_pure
8
8
  main
9
+ rest-client (>= 1.6.0)
9
10
  ruby_parser (~> 3.0)
10
11
  sexp_processor (~> 4.1)
11
12
 
@@ -15,33 +16,30 @@ GEM
15
16
  activesupport (3.2.10)
16
17
  i18n (~> 0.6)
17
18
  multi_json (~> 1.0)
18
- arrayfields (4.7.4)
19
- chronic (0.9.0)
19
+ arrayfields (4.9.0)
20
+ chronic (0.10.2)
20
21
  fattr (2.2.1)
21
- git (1.2.5)
22
22
  hirb (0.7.1)
23
23
  i18n (0.6.1)
24
- jeweler (1.8.4)
25
- bundler (~> 1.0)
26
- git (>= 1.2.5)
27
- rake
28
- rdoc
29
- json (1.7.6)
30
- json_pure (1.7.6)
31
- main (5.1.1)
24
+ json (1.8.1)
25
+ json_pure (1.8.0)
26
+ main (5.2.0)
32
27
  arrayfields (>= 4.7.4)
33
28
  chronic (>= 0.6.2)
34
29
  fattr (>= 2.2.0)
35
30
  map (>= 5.1.0)
36
- map (6.2.0)
31
+ map (6.5.1)
32
+ mime-types (1.25)
37
33
  mocha (0.9.12)
38
34
  multi_json (1.5.0)
39
35
  rake (10.0.3)
40
- rdoc (3.12)
36
+ rdoc (4.0.1)
41
37
  json (~> 1.4)
42
- ruby_parser (3.1.1)
38
+ rest-client (1.6.7)
39
+ mime-types (>= 1.16)
40
+ ruby_parser (3.2.2)
43
41
  sexp_processor (~> 4.1)
44
- sexp_processor (4.1.4)
42
+ sexp_processor (4.3.0)
45
43
  shoulda (3.3.2)
46
44
  shoulda-context (~> 1.0.1)
47
45
  shoulda-matchers (~> 1.4.1)
@@ -59,9 +57,9 @@ PLATFORMS
59
57
 
60
58
  DEPENDENCIES
61
59
  churn!
62
- jeweler
63
60
  mocha (~> 0.9.5)
64
61
  rake
62
+ rdoc
65
63
  shoulda
66
64
  simplecov
67
65
  test-construct
data/README.md CHANGED
@@ -4,7 +4,7 @@ Churn
4
4
  A Project to give the churn file, class, and method for a project for a given checkin. Over time the tool adds up the history of churns to give the number of times a file, class, or method is changing during the life of a project.
5
5
  Churn for files is immediate, but classes and methods requires buildings up a history using churn between revisions. The history is stored in ./tmp
6
6
 
7
- Currently has full Git, Mercurial (hg), and Bazaar (bzr) support, and partial SVN support (supports only file level churn currently)
7
+ Currently has full Git, Mercurial (hg), Bazaar (bzr) support, and partial SVN support (supports only file level churn currently)
8
8
 
9
9
  File changes can be calculated on any single commit to look at method changes you need to be running churn over time. Using a git post-commit hook, configuring your CI to run churn, or using [churn-site](http://churn.picoappz.com) is the best way to build up your churn history. See the --past_history (-p) option to do a one time run building up past class and method level churn.
10
10
 
@@ -38,15 +38,18 @@ The reason you want require false is that when required by default churn is expe
38
38
  * then run`rake churn` or `bundle exec rake churn`
39
39
  * use environment variables to control churn defaults
40
40
 
41
+ ``` ruby
41
42
  ENV['CHURN_MINIMUM_CHURN_COUNT']
42
43
  ENV['CHURN_START_DATE']
43
44
  ENV['CHURN_IGNORE_FILES']
45
+ ```
44
46
 
45
47
  * CLI:
46
48
  * on command line run `churn` or `bundle exec churn`
47
49
  * need help run `churn -h` to get additional information
48
50
  * run the executable passing in options to override defaults
49
-
51
+
52
+ ``` bash
50
53
  churn -i "churn.gemspec, Gemfile" #ignore files
51
54
  churn -y #output yaml format opposed to text
52
55
  churn -c 10 #set minimum churn count on a file to 10
@@ -54,7 +57,7 @@ The reason you want require false is that when required by default churn is expe
54
57
  churn --start_date "6 months ago" #Start looking at file changes from 6 months ago
55
58
  churn -p "4 months ago" #churn the past history to build up data for the last 4 months
56
59
  churn --past_history #churn the past history for default 3 months to build up data
57
-
60
+ ```
58
61
 
59
62
  ## Example Output
60
63
 
@@ -124,7 +127,7 @@ The reason you want require false is that when required by default churn is expe
124
127
  | lib/churn/churn_calculator.rb | ChurnCalculator | ChurnCalculator#to_s | 1 |
125
128
  +-------------------------------+-----------------+-----------------------------------------+---------------+
126
129
 
127
- ## Options
130
+ ## CLI Options
128
131
 
129
132
  [~/projects/churn] churn -h
130
133
  NAME
@@ -142,6 +145,23 @@ The reason you want require false is that when required by default churn is expe
142
145
  --data_directory=[data_directory], -d (0 ~> string(data_directory=))
143
146
  --past_history=[past_history], -p (0 ~> string(past_history=))
144
147
  --help, -h
148
+
149
+ ## Library Options
150
+
151
+ All the CLI options are parsed and just passed into the library. If you want to run the library directly from other code. The best way to see current options is where the [churn executable](https://github.com/danmayer/churn/blob/master/bin/churn) passes the parsed options into the `ChurnCalculator` class
152
+
153
+ ###
154
+ # Available options
155
+ ###
156
+ options = {:minimum_churn_count => params['minimum_churn_count'].value,
157
+ :ignore_files => params['ignore_files'].value,
158
+ :start_date => params['start_date'].value,
159
+ :data_directory => params['data_directory'].value,
160
+ :history => params['past_history'].value,
161
+ :report => params['report'].value,
162
+ :name => params['name'].value
163
+ }
164
+ result = Churn::ChurnCalculator.new(options).report(false)
145
165
 
146
166
  ## Notes on Patches/Pull Requests
147
167
 
data/bin/churn CHANGED
@@ -1,4 +1,13 @@
1
1
  #! /usr/bin/env ruby
2
+ # resolve bin path, ignoring symlinks
3
+ require "pathname"
4
+ bin_file = Pathname.new(__FILE__).realpath
5
+
6
+ # add self to libpath
7
+ puts File.expand_path("../../lib", bin_file)
8
+ $:.unshift File.expand_path("../../lib", bin_file)
9
+
10
+ require 'churn/calculator'
2
11
  require 'main'
3
12
  require 'yaml'
4
13
 
@@ -21,6 +30,19 @@ Main do
21
30
  default ''
22
31
  end
23
32
 
33
+ option('report', 'r') do
34
+ cast :string
35
+ argument :optional
36
+ default ''
37
+ end
38
+
39
+ option('name', 'n') do
40
+ cast :string
41
+ argument :optional
42
+ default ''
43
+ description 'name is require if remotely reporting churn results. If available as a github project, pass name in the form of username/project_name'
44
+ end
45
+
24
46
  option('start_date', 's') do
25
47
  cast :string
26
48
  argument :optional
@@ -41,12 +63,13 @@ Main do
41
63
  end
42
64
 
43
65
  def report_churn(output_string)
44
- require File.join(File.dirname(__FILE__), '..', 'lib', 'churn', 'churn_calculator')
45
66
  options = {:minimum_churn_count => params['minimum_churn_count'].value,
46
67
  :ignore_files => params['ignore_files'].value,
47
68
  :start_date => params['start_date'].value,
48
69
  :data_directory => params['data_directory'].value,
49
- :history => params['past_history'].value
70
+ :history => params['past_history'].value,
71
+ :report => params['report'].value,
72
+ :name => params['name'].value
50
73
  }
51
74
  result = Churn::ChurnCalculator.new(options).report(output_string)
52
75
  unless output_string
@@ -27,11 +27,11 @@ Gem::Specification.new do |s|
27
27
  ]
28
28
 
29
29
  s.add_development_dependency(%q<shoulda>, [">= 0"])
30
- s.add_development_dependency(%q<jeweler>, [">= 0"])
31
30
  s.add_development_dependency(%q<test-construct>, [">= 0"])
32
31
  s.add_development_dependency(%q<rake>, [">= 0"])
33
32
  s.add_development_dependency(%q<mocha>, ["~> 0.9.5"])
34
33
  s.add_development_dependency(%q<simplecov>,[">= 0"])
34
+ s.add_development_dependency(%q<rdoc>,[">= 0"])
35
35
  #s.add_development_dependency(%q<ruby-debug>, ["~> 0.10.4"])
36
36
  s.add_runtime_dependency(%q<main>, [">= 0"])
37
37
  s.add_runtime_dependency(%q<json_pure>, [">= 0"])
@@ -39,5 +39,5 @@ Gem::Specification.new do |s|
39
39
  s.add_runtime_dependency(%q<sexp_processor>, ["~> 4.1"])
40
40
  s.add_runtime_dependency(%q<ruby_parser>, ["~> 3.0"])
41
41
  s.add_runtime_dependency(%q<hirb>, [">= 0"])
42
-
42
+ s.add_runtime_dependency(%q<rest-client>, [">= 1.6.0"])
43
43
  end
@@ -4,16 +4,18 @@ require 'ruby_parser'
4
4
  require 'json'
5
5
  require 'hirb'
6
6
  require 'fileutils'
7
+ require 'rest_client'
7
8
 
8
9
  $LOAD_PATH.unshift(File.dirname(__FILE__))
9
- require 'source_control'
10
- require 'git_analyzer'
11
- require 'svn_analyzer'
12
- require 'hg_analyzer'
13
- require 'bzr_analyzer'
10
+ require 'scm/source_control'
11
+ require 'scm/git_analyzer'
12
+ require 'scm/svn_analyzer'
13
+ require 'scm/hg_analyzer'
14
+ require 'scm/bzr_analyzer'
15
+
14
16
  require 'location_mapping'
15
- require 'churn_history'
16
- require 'churn_options'
17
+ require 'history'
18
+ require 'options'
17
19
 
18
20
  module Churn
19
21
 
@@ -30,8 +32,7 @@ module Churn
30
32
 
31
33
  @minimum_churn_count = @churn_options.minimum_churn_count
32
34
  @ignore_files = @churn_options.ignore_files
33
- start_date = @churn_options.start_date
34
- @source_control = set_source_control(start_date)
35
+ @source_control = SourceControl.set_source_control(@churn_options.start_date)
35
36
 
36
37
  @changes = {}
37
38
  @revision_changes = {}
@@ -47,12 +48,23 @@ module Churn
47
48
  if @churn_options.history
48
49
  generate_history
49
50
  else
50
- self.emit
51
- self.analyze
51
+ emit
52
+ analyze
53
+ remote_report
52
54
  print ? self.to_s : self.to_h
53
55
  end
54
56
  end
55
57
 
58
+ def remote_report
59
+ if @churn_options.report_host
60
+ puts "posting churn results to #{@churn_options.report_host}"
61
+ data = {:name => @churn_options.name, :revision => @revisions.first, :data => self.to_h}.to_json
62
+ RestClient.post @churn_options.report_host, {"results" => data}, :content_type => :json, :accept => :json
63
+ end
64
+ rescue Errno::ECONNREFUSED
65
+ puts "error posting churn results connection refused to host: #{@churn_options.report_host}"
66
+ end
67
+
56
68
  # this method generates the past history of a churn project from first commit to current
57
69
  # running the report for oldest commits first so they are built up correctly
58
70
  def generate_history
@@ -124,23 +136,22 @@ module Churn
124
136
  result = seperator
125
137
  result +="* Revision Changes \n"
126
138
  result += seperator
127
- result += "Files: \n"
128
- result += display_array(hash[:changed_files], :fields=>[:to_str], :headers=>{:to_str=>'file'})
129
- result += "\nClasses: \n"
130
- result += display_array(hash[:changed_classes])
131
- result += "\nMethods: \n"
132
- result += display_array(hash[:changed_methods]) + "\n"
139
+ result += display_array("Files", hash[:changed_files], :fields=>[:to_str], :headers=>{:to_str=>'file'})
140
+ result += "\n"
141
+ result += display_array("Classes", hash[:changed_classes])
142
+ result += "\n"
143
+ result += display_array("Methods", hash[:changed_methods]) + "\n"
133
144
  result += seperator
134
145
  result +="* Project Churn \n"
135
146
  result += seperator
136
- result += "Files: \n"
137
- result += display_array(hash[:changes])
138
- result += "\nClasses: \n"
147
+ result += "\n"
148
+ result += display_array("Files", hash[:changes])
149
+ result += "\n"
139
150
  class_churn = collect_items(hash[:class_churn], 'klass')
140
- result += display_array(class_churn)
141
- result += "\nMethods: \n"
151
+ result += display_array("Classes", class_churn)
152
+ result += "\n"
142
153
  method_churn = collect_items(hash[:method_churn], 'method')
143
- result += display_array(method_churn)
154
+ result += display_array("Methods", method_churn)
144
155
  end
145
156
 
146
157
  private
@@ -158,40 +169,19 @@ module Churn
158
169
  /.*\.rb/
159
170
  end
160
171
 
161
- def self.display_array(array, options={})
162
- array ? Hirb::Helpers::AutoTable.render(array, options.merge(:description=>false)) + "\n" : ''
172
+ def self.display_array(title, array, options={})
173
+ response = ''
174
+ if array && array.length > 0
175
+ response = "#{title}\n"
176
+ response << Hirb::Helpers::AutoTable.render(array, options.merge(:description=>false)) + "\n"
177
+ end
178
+ response
163
179
  end
164
180
 
165
181
  def self.seperator
166
182
  "*"*70+"\n"
167
183
  end
168
184
 
169
- def self.git?
170
- !!(`git branch 2>&1` && $?.success?)
171
- end
172
-
173
- def self.hg?
174
- !!(`hg branch 2>&1` && $?.success?)
175
- end
176
-
177
- def self.bzr?
178
- !!(`bzr nick 2>&1` && $?.success?)
179
- end
180
-
181
- def set_source_control(start_date)
182
- if self.class.git?
183
- GitAnalyzer.new(start_date)
184
- elsif self.class.hg?
185
- HgAnalyzer.new(start_date)
186
- elsif self.class.bzr?
187
- BzrAnalyzer.new(start_date)
188
- elsif File.exist?(".svn")
189
- SvnAnalyzer.new(start_date)
190
- else
191
- raise "Churning requires a bazaar, git, mercurial, or subversion repo"
192
- end
193
- end
194
-
195
185
  def calculate_revision_changes
196
186
  @revisions.each do |revision|
197
187
  if revision == @revisions.first
@@ -8,8 +8,9 @@ module Churn
8
8
  DEFAULT_CHURN_DIRECTORY = "tmp/churn"
9
9
  DEFAULT_MINIMUM_CHURN_COUNT = 5
10
10
  DEFAULT_START_TIME = '3 months ago'
11
+ DEFAULT_REPORT_HOST = 'http://churn.picoappz.com'
11
12
 
12
- attr_accessor :data_directory, :minimum_churn_count, :ignore_files, :start_date, :history
13
+ attr_accessor :data_directory, :minimum_churn_count, :ignore_files, :start_date, :history, :report_host, :name
13
14
 
14
15
  def initialize()
15
16
  @data_directory = DEFAULT_CHURN_DIRECTORY
@@ -17,6 +18,8 @@ module Churn
17
18
  @ignore_files = ['/dev/null']
18
19
  @start_date = DEFAULT_START_TIME
19
20
  @history = nil
21
+ @report_host = nil
22
+ @name = nil
20
23
  end
21
24
 
22
25
  def set_options(options = {})
@@ -29,6 +32,17 @@ module Churn
29
32
  if @history=='true'
30
33
  @history = DEFAULT_START_TIME
31
34
  end
35
+ if !options[:report].nil? && options[:report]!=''
36
+ @report_host = options[:report]
37
+ if @report_host=='true'
38
+ @report_host = DEFAULT_REPORT_HOST
39
+ end
40
+ end
41
+
42
+ @name = options[:name] if !options[:name].nil? && options[:name]!=''
43
+ if !@report_host.nil? && @name.nil?
44
+ raise ArgumentError.new "If you are reporting churn results you must pass a valid github project name in the form of username/project_name"
45
+ end
32
46
 
33
47
  self
34
48
  end
@@ -2,6 +2,11 @@ module Churn
2
2
 
3
3
  #analizes Bzr / Bazaar SCM to find recently changed files, and what lines have been altered
4
4
  class BzrAnalyzer < SourceControl
5
+
6
+ def self.supported?
7
+ !!(`bzr nick 2>&1` && $?.success?)
8
+ end
9
+
5
10
  def get_logs
6
11
  `bzr log -v --short #{date_range}`.split("\n").reject{|line| line !~ /^[ ]*(M|A) /}.map{|line| line.strip.split(" ")[1..-1]}.flatten
7
12
  end
@@ -2,6 +2,11 @@ module Churn
2
2
 
3
3
  #analizes git SCM to find recently changed files, and what lines have been altered
4
4
  class GitAnalyzer < SourceControl
5
+
6
+ def self.supported?
7
+ !!(`git branch 2>&1` && $?.success?)
8
+ end
9
+
5
10
  def get_logs
6
11
  `git log #{date_range} --name-only --pretty=format:`.split(/\n/).reject{|line| line == ""}
7
12
  end
@@ -2,6 +2,11 @@ module Churn
2
2
 
3
3
  #analizes Hg / Mercurial SCM to find recently changed files, and what lines have been altered
4
4
  class HgAnalyzer < SourceControl
5
+
6
+ def self.supported?
7
+ !!(`hg branch 2>&1` && $?.success?)
8
+ end
9
+
5
10
  def get_logs
6
11
  `hg log -v#{date_range}`.split("\n").reject{|line| line !~ /^files:/}.map{|line| line.split(" ")[1..-1]}.flatten
7
12
  end
@@ -2,10 +2,37 @@ module Churn
2
2
 
3
3
  # Base clase for analyzing various SCM systems like git, HG, and SVN
4
4
  class SourceControl
5
+
6
+ def self.set_source_control(start_date)
7
+ if GitAnalyzer.supported?
8
+ GitAnalyzer.new(start_date)
9
+ elsif HgAnalyzer.supported?
10
+ HgAnalyzer.new(start_date)
11
+ elsif BzrAnalyzer.supported?
12
+ BzrAnalyzer.new(start_date)
13
+ elsif SvnAnalyzer.supported?
14
+ SvnAnalyzer.new(start_date)
15
+ else
16
+ raise "Churn requires a bazaar, git, mercurial, or subversion source control"
17
+ end
18
+ end
19
+
20
+ def self.supported?
21
+ raise "child class must implement"
22
+ end
23
+
5
24
  def initialize(start_date=nil)
6
25
  @start_date = start_date
7
26
  end
8
27
 
28
+ def get_logs
29
+ raise "child class must implement"
30
+ end
31
+
32
+ def get_revisions
33
+ raise "child class must implement"
34
+ end
35
+
9
36
  def get_updated_files_change_info(revision, revisions)
10
37
  updated = {}
11
38
  logs = get_updated_files_from_log(revision, revisions)
@@ -2,15 +2,24 @@ module Churn
2
2
 
3
3
  #analizes SVN SCM to find recently changed files, and what lines have been altered
4
4
  class SvnAnalyzer < SourceControl
5
+
6
+ def self.supported?
7
+ File.exist?(".svn")
8
+ end
9
+
5
10
  def get_logs
6
- `svn log #{date_range} --verbose`.split(/\n/).map { |line| clean_up_svn_line(line) }.compact
11
+ `svn log --verbose#{date_range}#{svn_credentials}`.split(/\n/).map { |line| clean_up_svn_line(line) }.compact
7
12
  end
8
13
 
9
14
  private
15
+ def svn_credentials
16
+ " --username #{ENV['SVN_USR']} --password #{ENV['SVN_PWD']}" if ENV['SVN_PWD'] && ENV['SVN_USR']
17
+ end
18
+
10
19
  def date_range
11
20
  if @start_date
12
21
  date = Chronic.parse(@start_date)
13
- "--revision {#{date.strftime('%Y-%m-%d')}}:{#{Time.now.strftime('%Y-%m-%d')}}"
22
+ " --revision {#{date.strftime('%Y-%m-%d')}}:{#{Time.now.strftime('%Y-%m-%d')}}"
14
23
  end
15
24
  end
16
25
 
@@ -1,3 +1,3 @@
1
1
  module Churn
2
- VERSION = "0.0.34"
2
+ VERSION = "0.0.35"
3
3
  end
@@ -1,13 +1,13 @@
1
1
  if defined?(RakeFileUtils) # self.respond_to?(:desc)
2
2
  def report_churn()
3
- require File.join(File.dirname(__FILE__), '..', 'churn', 'churn_calculator')
4
- params = {}
3
+ require File.join(File.dirname(__FILE__), '..', 'churn', 'calculator')
4
+ options = {}
5
5
  { :minimum_churn_count => ENV['CHURN_MINIMUM_CHURN_COUNT'],
6
6
  :start_date => ENV['CHURN_START_DATE'],
7
7
  :ignore_files => ENV['CHURN_IGNORE_FILES'],
8
8
  :data_directory => ENV['CHURN_DATA_DIRECTORY'],
9
- }.each {|k,v| params[k] = v unless v.nil? }
10
- Churn::ChurnCalculator.new(params).report
9
+ }.each {|k,v| options[k] = v unless v.nil? }
10
+ Churn::ChurnCalculator.new(options).report
11
11
  end
12
12
 
13
13
  desc "Report the current churn for the project"
@@ -13,7 +13,7 @@ end
13
13
 
14
14
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
15
15
  $LOAD_PATH.unshift(File.dirname(__FILE__))
16
- require 'churn/churn_calculator'
16
+ require 'churn/calculator'
17
17
  Mocha::Configuration.prevent(:stubbing_non_existent_method)
18
18
 
19
19
  class Test::Unit::TestCase
@@ -4,7 +4,7 @@ class ChurnCalculatorTest < Test::Unit::TestCase
4
4
 
5
5
  should "use minimum churn count" do
6
6
  within_construct do |container|
7
- Churn::ChurnCalculator.stubs(:git?).returns(true)
7
+ Churn::GitAnalyzer.stubs(:supported?).returns(true)
8
8
  churn = Churn::ChurnCalculator.new({:minimum_churn_count => 3})
9
9
 
10
10
  churn.stubs(:parse_log_for_changes).returns([['file.rb', 4],['less.rb',1]])
@@ -18,7 +18,7 @@ class ChurnCalculatorTest < Test::Unit::TestCase
18
18
 
19
19
  should "ensure that minimum churn count is initialized as a Fixnum" do
20
20
  within_construct do |container|
21
- Churn::ChurnCalculator.stubs(:git?).returns(true)
21
+ Churn::GitAnalyzer.stubs(:supported?).returns(true)
22
22
  churn = Churn::ChurnCalculator.new({:minimum_churn_count => "3"})
23
23
 
24
24
  assert_equal 3, churn.instance_variable_get(:@minimum_churn_count)
@@ -27,7 +27,7 @@ class ChurnCalculatorTest < Test::Unit::TestCase
27
27
 
28
28
  should "use ignore_files filter" do
29
29
  within_construct do |container|
30
- Churn::ChurnCalculator.stubs(:git?).returns(true)
30
+ Churn::GitAnalyzer.stubs(:supported?).returns(true)
31
31
  churn = Churn::ChurnCalculator.new({:ignore_files => "file.rb"})
32
32
 
33
33
  churn.stubs(:parse_log_for_changes).returns([['file.rb', 10],['new.rb',11]])
@@ -41,7 +41,7 @@ class ChurnCalculatorTest < Test::Unit::TestCase
41
41
 
42
42
  should "analize sorts changes" do
43
43
  within_construct do |container|
44
- Churn::ChurnCalculator.stubs(:git?).returns(true)
44
+ Churn::GitAnalyzer.stubs(:supported?).returns(true)
45
45
  churn = Churn::ChurnCalculator.new({:minimum_churn_count => 3})
46
46
 
47
47
  churn.stubs(:parse_log_for_changes).returns([['file.rb', 4],['most.rb', 9],['less.rb',1]])
@@ -57,7 +57,7 @@ class ChurnCalculatorTest < Test::Unit::TestCase
57
57
 
58
58
  should "have correct changed_files data" do
59
59
  within_construct do |container|
60
- Churn::ChurnCalculator.stubs(:git?).returns(true)
60
+ Churn::GitAnalyzer.stubs(:supported?).returns(true)
61
61
  churn = Churn::ChurnCalculator.new({:minimum_churn_count => 3})
62
62
 
63
63
  churn.stubs(:parse_log_for_changes).returns([['less.rb',1]])
@@ -70,7 +70,7 @@ class ChurnCalculatorTest < Test::Unit::TestCase
70
70
 
71
71
  should "have correct changed classes and methods data" do
72
72
  within_construct do |container|
73
- Churn::ChurnCalculator.stubs(:git?).returns(true)
73
+ Churn::GitAnalyzer.stubs(:supported?).returns(true)
74
74
  churn = Churn::ChurnCalculator.new({:minimum_churn_count => 3})
75
75
 
76
76
  churn.stubs(:parse_log_for_changes).returns([['less.rb',1]])
@@ -87,7 +87,7 @@ class ChurnCalculatorTest < Test::Unit::TestCase
87
87
 
88
88
  should "have correct churn method and classes at 1 change" do
89
89
  within_construct do |container|
90
- Churn::ChurnCalculator.stubs(:git?).returns(true)
90
+ Churn::GitAnalyzer.stubs(:supported?).returns(true)
91
91
  churn = Churn::ChurnCalculator.new({:minimum_churn_count => 3})
92
92
 
93
93
  churn.stubs(:parse_log_for_changes).returns([['less.rb',1]])
@@ -117,40 +117,37 @@ class ChurnCalculatorTest < Test::Unit::TestCase
117
117
  end
118
118
 
119
119
  should "initialize a churn calculator for hg repositories" do
120
- Churn::ChurnCalculator.stubs(:git?).returns(false)
121
- Churn::ChurnCalculator.expects(:`).with("hg branch 2>&1").returns(true) #` fix syntax hilighting
120
+ Churn::GitAnalyzer.stubs(:supported?).returns(false)
121
+ Churn::HgAnalyzer.expects(:`).with("hg branch 2>&1").returns(true) #` fix syntax hilighting
122
122
  churn = Churn::ChurnCalculator.new({:minimum_churn_count => 3})
123
123
  assert churn.instance_variable_get(:@source_control).is_a?(Churn::HgAnalyzer)
124
124
  end
125
125
 
126
126
  should "initialize a churn calculator for bzr repositories" do
127
- Churn::ChurnCalculator.stubs(:git?).returns(false)
128
- Churn::ChurnCalculator.stubs(:hg?).returns(false)
129
- Churn::ChurnCalculator.expects(:`).with("bzr nick 2>&1").returns(true) #` fix syntax hilighting
127
+ Churn::GitAnalyzer.stubs(:supported?).returns(false)
128
+ Churn::HgAnalyzer.stubs(:supported?).returns(false)
129
+ Churn::BzrAnalyzer.expects(:`).with("bzr nick 2>&1").returns(true) #` fix syntax hilighting
130
130
  churn = Churn::ChurnCalculator.new({:minimum_churn_count => 3})
131
131
  assert churn.instance_variable_get(:@source_control).is_a?(Churn::BzrAnalyzer)
132
132
  end
133
133
 
134
134
  should "initialize a churn calculator for svn repositories" do
135
- Churn::ChurnCalculator.stubs(:git?).returns(false)
136
- Churn::ChurnCalculator.stubs(:hg?).returns(false)
137
- Churn::ChurnCalculator.stubs(:bzr?).returns(false)
135
+ Churn::GitAnalyzer.stubs(:supported?).returns(false)
136
+ Churn::HgAnalyzer.stubs(:supported?).returns(false)
137
+ Churn::BzrAnalyzer.stubs(:supported?).returns(false)
138
138
  File.stubs(:exist?).returns(true)
139
139
  churn = Churn::ChurnCalculator.new({:minimum_churn_count => 3})
140
140
  assert churn.instance_variable_get(:@source_control).is_a?(Churn::SvnAnalyzer)
141
141
  end
142
142
 
143
143
  should "raise exception on a churn calculator for unknown repositories" do
144
- Churn::ChurnCalculator.stubs(:git?).returns(false)
145
- Churn::ChurnCalculator.stubs(:hg?).returns(false)
146
- Churn::ChurnCalculator.stubs(:bzr?).returns(false)
144
+ Churn::GitAnalyzer.stubs(:supported?).returns(false)
145
+ Churn::HgAnalyzer.stubs(:supported?).returns(false)
146
+ Churn::BzrAnalyzer.stubs(:supported?).returns(false)
147
147
  File.stubs(:exist?).returns(false)
148
148
  assert_raises RuntimeError do
149
149
  churn = Churn::ChurnCalculator.new({:minimum_churn_count => 3})
150
150
  end
151
151
  end
152
152
 
153
-
154
-
155
-
156
153
  end
@@ -21,7 +21,32 @@ class SvnAnalyzerTest < Test::Unit::TestCase
21
21
 
22
22
  should "run date range correctly" do
23
23
  svn_analyzer = Churn::SvnAnalyzer.new(Date.parse('3/3/2010'))
24
- assert_equal "--revision {2010-03-03}:{#{Date.today.to_s}}", svn_analyzer.send(:date_range)
24
+ assert_equal " --revision {2010-03-03}:{#{Date.today.to_s}}", svn_analyzer.send(:date_range)
25
+ end
26
+
27
+ context "SvnAnalyzer#get_logs" do
28
+ should "return a list of changed files" do
29
+ ENV['SVN_PWD']= nil
30
+ ENV['SVN_USR']= nil
31
+ svn_analyzer = Churn::SvnAnalyzer.new
32
+ svn_analyzer.expects(:`).with('svn log --verbose').returns('
33
+ A /file1.rb
34
+ A /dir/file2.rb
35
+ A /file3.rb
36
+ M /file1.rb')
37
+ assert_equal ['/file1.rb', '/dir/file2.rb', '/file3.rb', '/file1.rb'], svn_analyzer.get_logs
38
+ end
39
+ should "invoke with svn credentials " do
40
+ ENV['SVN_PWD']= '123qwe'
41
+ ENV['SVN_USR']= 'user123'
42
+ svn_analyzer = Churn::SvnAnalyzer.new
43
+ svn_analyzer.expects(:`).with('svn log --verbose --username user123 --password 123qwe').returns('
44
+ A /file1.rb
45
+ A /dir/file2.rb
46
+ A /file3.rb
47
+ M /file1.rb')
48
+ assert_equal ['/file1.rb', '/dir/file2.rb', '/file3.rb', '/file1.rb'], svn_analyzer.get_logs
49
+ end
25
50
  end
26
51
 
27
52
  protected
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: churn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.34
5
- prerelease:
4
+ version: 0.0.35
6
5
  platform: ruby
7
6
  authors:
8
7
  - Dan Mayer
@@ -14,151 +13,132 @@ dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: shoulda
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0'
22
20
  type: :development
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - '>='
28
25
  - !ruby/object:Gem::Version
29
26
  version: '0'
30
27
  - !ruby/object:Gem::Dependency
31
- name: jeweler
28
+ name: test-construct
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - '>='
36
32
  - !ruby/object:Gem::Version
37
33
  version: '0'
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ! '>='
38
+ - - '>='
44
39
  - !ruby/object:Gem::Version
45
40
  version: '0'
46
41
  - !ruby/object:Gem::Dependency
47
- name: test-construct
42
+ name: rake
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
45
+ - - '>='
52
46
  - !ruby/object:Gem::Version
53
47
  version: '0'
54
48
  type: :development
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ! '>='
52
+ - - '>='
60
53
  - !ruby/object:Gem::Version
61
54
  version: '0'
62
55
  - !ruby/object:Gem::Dependency
63
- name: rake
56
+ name: mocha
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
- - - ! '>='
59
+ - - ~>
68
60
  - !ruby/object:Gem::Version
69
- version: '0'
61
+ version: 0.9.5
70
62
  type: :development
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
- - - ! '>='
66
+ - - ~>
76
67
  - !ruby/object:Gem::Version
77
- version: '0'
68
+ version: 0.9.5
78
69
  - !ruby/object:Gem::Dependency
79
- name: mocha
70
+ name: simplecov
80
71
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
72
  requirements:
83
- - - ~>
73
+ - - '>='
84
74
  - !ruby/object:Gem::Version
85
- version: 0.9.5
75
+ version: '0'
86
76
  type: :development
87
77
  prerelease: false
88
78
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
79
  requirements:
91
- - - ~>
80
+ - - '>='
92
81
  - !ruby/object:Gem::Version
93
- version: 0.9.5
82
+ version: '0'
94
83
  - !ruby/object:Gem::Dependency
95
- name: simplecov
84
+ name: rdoc
96
85
  requirement: !ruby/object:Gem::Requirement
97
- none: false
98
86
  requirements:
99
- - - ! '>='
87
+ - - '>='
100
88
  - !ruby/object:Gem::Version
101
89
  version: '0'
102
90
  type: :development
103
91
  prerelease: false
104
92
  version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
93
  requirements:
107
- - - ! '>='
94
+ - - '>='
108
95
  - !ruby/object:Gem::Version
109
96
  version: '0'
110
97
  - !ruby/object:Gem::Dependency
111
98
  name: main
112
99
  requirement: !ruby/object:Gem::Requirement
113
- none: false
114
100
  requirements:
115
- - - ! '>='
101
+ - - '>='
116
102
  - !ruby/object:Gem::Version
117
103
  version: '0'
118
104
  type: :runtime
119
105
  prerelease: false
120
106
  version_requirements: !ruby/object:Gem::Requirement
121
- none: false
122
107
  requirements:
123
- - - ! '>='
108
+ - - '>='
124
109
  - !ruby/object:Gem::Version
125
110
  version: '0'
126
111
  - !ruby/object:Gem::Dependency
127
112
  name: json_pure
128
113
  requirement: !ruby/object:Gem::Requirement
129
- none: false
130
114
  requirements:
131
- - - ! '>='
115
+ - - '>='
132
116
  - !ruby/object:Gem::Version
133
117
  version: '0'
134
118
  type: :runtime
135
119
  prerelease: false
136
120
  version_requirements: !ruby/object:Gem::Requirement
137
- none: false
138
121
  requirements:
139
- - - ! '>='
122
+ - - '>='
140
123
  - !ruby/object:Gem::Version
141
124
  version: '0'
142
125
  - !ruby/object:Gem::Dependency
143
126
  name: chronic
144
127
  requirement: !ruby/object:Gem::Requirement
145
- none: false
146
128
  requirements:
147
- - - ! '>='
129
+ - - '>='
148
130
  - !ruby/object:Gem::Version
149
131
  version: 0.2.3
150
132
  type: :runtime
151
133
  prerelease: false
152
134
  version_requirements: !ruby/object:Gem::Requirement
153
- none: false
154
135
  requirements:
155
- - - ! '>='
136
+ - - '>='
156
137
  - !ruby/object:Gem::Version
157
138
  version: 0.2.3
158
139
  - !ruby/object:Gem::Dependency
159
140
  name: sexp_processor
160
141
  requirement: !ruby/object:Gem::Requirement
161
- none: false
162
142
  requirements:
163
143
  - - ~>
164
144
  - !ruby/object:Gem::Version
@@ -166,7 +146,6 @@ dependencies:
166
146
  type: :runtime
167
147
  prerelease: false
168
148
  version_requirements: !ruby/object:Gem::Requirement
169
- none: false
170
149
  requirements:
171
150
  - - ~>
172
151
  - !ruby/object:Gem::Version
@@ -174,7 +153,6 @@ dependencies:
174
153
  - !ruby/object:Gem::Dependency
175
154
  name: ruby_parser
176
155
  requirement: !ruby/object:Gem::Requirement
177
- none: false
178
156
  requirements:
179
157
  - - ~>
180
158
  - !ruby/object:Gem::Version
@@ -182,7 +160,6 @@ dependencies:
182
160
  type: :runtime
183
161
  prerelease: false
184
162
  version_requirements: !ruby/object:Gem::Requirement
185
- none: false
186
163
  requirements:
187
164
  - - ~>
188
165
  - !ruby/object:Gem::Version
@@ -190,20 +167,32 @@ dependencies:
190
167
  - !ruby/object:Gem::Dependency
191
168
  name: hirb
192
169
  requirement: !ruby/object:Gem::Requirement
193
- none: false
194
170
  requirements:
195
- - - ! '>='
171
+ - - '>='
196
172
  - !ruby/object:Gem::Version
197
173
  version: '0'
198
174
  type: :runtime
199
175
  prerelease: false
200
176
  version_requirements: !ruby/object:Gem::Requirement
201
- none: false
202
177
  requirements:
203
- - - ! '>='
178
+ - - '>='
204
179
  - !ruby/object:Gem::Version
205
180
  version: '0'
206
- description: ! 'High method and class churn has been shown to have increased bug and
181
+ - !ruby/object:Gem::Dependency
182
+ name: rest-client
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - '>='
186
+ - !ruby/object:Gem::Version
187
+ version: 1.6.0
188
+ type: :runtime
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - '>='
193
+ - !ruby/object:Gem::Version
194
+ version: 1.6.0
195
+ description: 'High method and class churn has been shown to have increased bug and
207
196
  error rates. This gem helps you know what is changing a lot so you can do additional
208
197
  testing, code review, or refactoring to try to tame the volatile code. '
209
198
  email: dan@mayerdan.com
@@ -226,16 +215,16 @@ files:
226
215
  - bin/churn
227
216
  - churn.gemspec
228
217
  - lib/churn.rb
229
- - lib/churn/bzr_analyzer.rb
230
- - lib/churn/churn_calculator.rb
231
- - lib/churn/churn_history.rb
232
- - lib/churn/git_analyzer.rb
233
- - lib/churn/hg_analyzer.rb
218
+ - lib/churn/calculator.rb
219
+ - lib/churn/history.rb
234
220
  - lib/churn/location_mapping.rb
235
- - lib/churn/source_control.rb
236
- - lib/churn/svn_analyzer.rb
221
+ - lib/churn/options.rb
222
+ - lib/churn/scm/bzr_analyzer.rb
223
+ - lib/churn/scm/git_analyzer.rb
224
+ - lib/churn/scm/hg_analyzer.rb
225
+ - lib/churn/scm/source_control.rb
226
+ - lib/churn/scm/svn_analyzer.rb
237
227
  - lib/churn/version.rb
238
- - lib/churn_options.rb
239
228
  - lib/tasks/churn_tasks.rb
240
229
  - man/churn.1
241
230
  - man/churn.html
@@ -254,41 +243,25 @@ files:
254
243
  homepage: http://github.com/danmayer/churn
255
244
  licenses:
256
245
  - MIT
246
+ metadata: {}
257
247
  post_install_message:
258
248
  rdoc_options: []
259
249
  require_paths:
260
250
  - lib
261
251
  required_ruby_version: !ruby/object:Gem::Requirement
262
- none: false
263
252
  requirements:
264
- - - ! '>='
253
+ - - '>='
265
254
  - !ruby/object:Gem::Version
266
255
  version: '0'
267
- segments:
268
- - 0
269
- hash: 837759494224756390
270
256
  required_rubygems_version: !ruby/object:Gem::Requirement
271
- none: false
272
257
  requirements:
273
- - - ! '>='
258
+ - - '>='
274
259
  - !ruby/object:Gem::Version
275
260
  version: '0'
276
261
  requirements: []
277
262
  rubyforge_project: churn
278
- rubygems_version: 1.8.25
263
+ rubygems_version: 2.0.3
279
264
  signing_key:
280
- specification_version: 3
265
+ specification_version: 4
281
266
  summary: Providing additional churn metrics over the original metric_fu churn
282
- test_files:
283
- - test/data/churn_calculator.rb
284
- - test/data/test_helper.rb
285
- - test/test_helper.rb
286
- - test/unit/bzr_analyzer_test.rb
287
- - test/unit/churn_calculator_test.rb
288
- - test/unit/churn_history_test.rb
289
- - test/unit/churn_options_test.rb
290
- - test/unit/git_analyzer_test.rb
291
- - test/unit/hg_analyzer_test.rb
292
- - test/unit/location_mapping_test.rb
293
- - test/unit/source_control_test.rb
294
- - test/unit/svn_analyzer_test.rb
267
+ test_files: []