debt_ceiling 0.3.3 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.debt_ceiling.rb +1 -1
- data/.travis.yml +6 -3
- data/README.md +8 -1
- data/bin/debt_ceiling +5 -1
- data/debt_ceiling.gemspec +2 -1
- data/lib/debt_ceiling.rb +52 -3
- data/lib/debt_ceiling/archeological_dig.rb +119 -0
- data/lib/debt_ceiling/audit.rb +6 -20
- data/lib/debt_ceiling/source_control_systems/base.rb +37 -0
- data/lib/debt_ceiling/source_control_systems/double.rb +38 -0
- data/lib/debt_ceiling/source_control_systems/git.rb +84 -0
- data/lib/debt_ceiling/source_control_systems/mercurial.rb +49 -0
- data/lib/debt_ceiling/version.rb +1 -1
- metadata +23 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2d7432d28a7ec4031eecec3fa65514b9fd1ad72b
|
4
|
+
data.tar.gz: 47b5bd46ff993349004cc868951e8ae65498e05b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7046c3ebf95657217a84892680f8f394b0798308f5aa63cd00fde6a055d6b2409e7d5729810905bcd8ca7a1fce3e473b738dc4d1e2742d2b6c18f1a1d339dd10
|
7
|
+
data.tar.gz: 00a701fac5fb15dae1262910ac606c899449539f224f3f72dfc4a780afb0c42844bef0b75425506a8c6425e484a1c1b71b1c96046db3a948393737f91d4647dc
|
data/.debt_ceiling.rb
CHANGED
data/.travis.yml
CHANGED
@@ -2,9 +2,12 @@ language: ruby
|
|
2
2
|
rvm:
|
3
3
|
- 1.9.3
|
4
4
|
- jruby-19mode # JRuby in 1.9 mode
|
5
|
-
- jruby-9.0.0.0
|
5
|
+
- jruby-9.0.0.0
|
6
6
|
- 2.1.1
|
7
|
-
-
|
7
|
+
- 2.2.2
|
8
|
+
- 2.3.0
|
9
|
+
- rbx-2.8
|
8
10
|
addons:
|
9
11
|
code_climate:
|
10
|
-
repo_token: cd7df1b0973b1b3323ce8b2f09fe9c087010115889fed6
|
12
|
+
repo_token: cd7df1b0973b1b3323ce8b2f09fe9c087010115889fed6
|
13
|
+
sudo: false
|
data/README.md
CHANGED
@@ -23,6 +23,13 @@ Current features include:
|
|
23
23
|
* Adding cost for TODOs or deprecated references you specify (see [.debt_ceiling.rb.example](https://github.com/bglusman/debt_ceiling/blob/master/examples/.debt_ceiling.rb.example))
|
24
24
|
* Running from a test suite to fail if debt ceiling is exceeded
|
25
25
|
* Running from a test suite to fail if debt deadline is missed (currently only supports a single deadline, could add support for multiple targets if there's interest)
|
26
|
+
* Analyzing the history of the master branch (or current/default branch)
|
27
|
+
* Calculates total debt and pass/fail state for the state of the code at each commit.
|
28
|
+
* It will print this out as a sparkline command line graph, which is basically useless and just for kicks
|
29
|
+
* Store the entire result in Redis (if available), or return the results as a `DebtCeiling::ArcheologicalDig` object if called via `DebtCeiling.dig(path)`, which has an array of hashes available via `#results` method representing the individual commit results at the specified level of detail per commit.
|
30
|
+
* Plans to visualize this history
|
31
|
+
* Memoizes each commit's calculation, either to Redis if Redis gem is installed (specify host and port via `ENV['REDIS_HOST']` and `ENV['REDIS_PORT']` or uses defaults of localhost and 6379) or by creating git notes associated with each commit if not. Also supports Mercurial in theory, but haven't tested it, and requires Redis for Mercurial since no git notes option there.
|
32
|
+
* Run the historical analysis for a repository with `debt_ceiling dig`, defaulting to current directory.
|
26
33
|
|
27
34
|
To integrate in a test suite, set a value for `debt_ceiling`, `max_debt_per_module` and/or `reduction_target` and `reduction_date` in your configuration and call `DebtCeiling.audit` from your test helper as an additional test, or drop the call and/or configuration directly in your spec helper:
|
28
35
|
```ruby
|
@@ -46,7 +53,7 @@ Additional customization is supported via two method hooks in the debt class, wh
|
|
46
53
|
|
47
54
|
You can configure/customize the debt calculated using a few simple commands in a .debt_ceiling.rb file in the project's home directory:
|
48
55
|
|
49
|
-
```
|
56
|
+
```ruby
|
50
57
|
DebtCeiling.configure do |c|
|
51
58
|
#exceeding this will fail a test, if you run debt_ceiling binary/calculate method from test suite
|
52
59
|
c.debt_ceiling = 250
|
data/bin/debt_ceiling
CHANGED
data/debt_ceiling.gemspec
CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |s|
|
|
8
8
|
s.version = DebtCeiling::VERSION
|
9
9
|
s.platform = Gem::Platform::RUBY
|
10
10
|
s.authors = ['Brian Glusman']
|
11
|
-
s.email = ['bglusman@
|
11
|
+
s.email = ['bglusman@stridenyc.com']
|
12
12
|
s.homepage = 'https://github.com/bglusman/debt_ceiling'
|
13
13
|
s.summary = 'DebtCeiling helps you track Tech Debt'
|
14
14
|
s.rubyforge_project = 'debt_ceiling'
|
@@ -24,6 +24,7 @@ Gem::Specification.new do |s|
|
|
24
24
|
|
25
25
|
s.add_runtime_dependency 'rubycritic', '~> 1.4'
|
26
26
|
s.add_runtime_dependency 'chronic', '~> 0.10'
|
27
|
+
s.add_runtime_dependency 'sparkr', '~> 0.4.1'
|
27
28
|
s.add_runtime_dependency 'configurations', '~> 2.0'
|
28
29
|
s.add_development_dependency 'pry', '~> 0.10'
|
29
30
|
s.add_development_dependency 'rake', '~> 10.3'
|
data/lib/debt_ceiling.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'configurations'
|
2
2
|
require 'chronic'
|
3
|
+
require 'sparkr'
|
3
4
|
require 'rubycritic'
|
4
5
|
require 'rubycritic/cli/application'
|
5
6
|
require 'ostruct'
|
@@ -12,14 +13,38 @@ require_relative 'debt_ceiling/static_analysis_debt'
|
|
12
13
|
require_relative 'debt_ceiling/debt'
|
13
14
|
require_relative 'debt_ceiling/compatibility'
|
14
15
|
require_relative 'debt_ceiling/file_attributes'
|
16
|
+
require_relative 'debt_ceiling/archeological_dig'
|
15
17
|
|
16
18
|
module DebtCeiling
|
17
19
|
include Configurations
|
18
20
|
extend Forwardable
|
19
21
|
extend self
|
20
|
-
|
21
|
-
|
22
|
-
|
22
|
+
CONFIGURATION_OPTIONS = [
|
23
|
+
:extension_path,
|
24
|
+
:blacklist, :whitelist,
|
25
|
+
:max_debt_per_module,
|
26
|
+
:reduction_date,
|
27
|
+
:reduction_target,
|
28
|
+
:debt_ceiling,
|
29
|
+
:deprecated_reference_pairs,
|
30
|
+
:manual_callouts,
|
31
|
+
:grade_points,
|
32
|
+
:complexity_multiplier,
|
33
|
+
:method_count_multiplier,
|
34
|
+
:smells_multiplier,
|
35
|
+
:duplication_multiplier,
|
36
|
+
:ideal_max_line_count,
|
37
|
+
:cost_per_line_over_ideal,
|
38
|
+
:debt_types,
|
39
|
+
:archeology_detail,
|
40
|
+
:memoize_records_in_repo
|
41
|
+
]
|
42
|
+
CONFIG_FILE_NAME = ".debt_ceiling.rb"
|
43
|
+
CONFIG_LOCATIONS = ["#{Dir.pwd}/#{CONFIG_FILE_NAME}", "#{Dir.home}/#{CONFIG_FILE_NAME}"]
|
44
|
+
NO_CONFIG_FOUND = "No #{CONFIG_FILE_NAME} configuration file detected in #{Dir.pwd} or ~/, using defaults"
|
45
|
+
|
46
|
+
def_delegators :configuration, *CONFIGURATION_OPTIONS
|
47
|
+
|
23
48
|
|
24
49
|
configuration_defaults do |config|
|
25
50
|
config.extension_path = "#{Dir.pwd}/custom_debt.rb"
|
@@ -35,10 +60,34 @@ module DebtCeiling
|
|
35
60
|
config.ideal_max_line_count = 100
|
36
61
|
config.cost_per_line_over_ideal = 1
|
37
62
|
config.debt_types = [CustomDebt, StaticAnalysisDebt]
|
63
|
+
config.archeology_detail = :low
|
64
|
+
config.memoize_records_in_repo = true #is this OK as a default? effects repo
|
38
65
|
end
|
39
66
|
|
40
67
|
|
41
68
|
def audit(dir='.', opts= {})
|
42
69
|
Audit.new(dir, opts)
|
43
70
|
end
|
71
|
+
|
72
|
+
def dig(dir='.', opts={})
|
73
|
+
dig = ArcheologicalDig.new(dir, opts)
|
74
|
+
puts Sparkr.sparkline(dig.records.map {|r| r['debt'] })
|
75
|
+
dig
|
76
|
+
end
|
77
|
+
|
78
|
+
def load_configuration
|
79
|
+
config_file_location ? load(config_file_location) : puts(NO_CONFIG_FOUND)
|
80
|
+
|
81
|
+
load extension_path if extension_path && File.exist?(extension_path)
|
82
|
+
@loaded = true
|
83
|
+
end
|
84
|
+
|
85
|
+
def config_file_location
|
86
|
+
CONFIG_LOCATIONS.find {|loc| File.exist?(loc) }
|
87
|
+
end
|
88
|
+
|
89
|
+
def config_array
|
90
|
+
CONFIGURATION_OPTIONS.map {|option| public_send(option) }
|
91
|
+
end
|
92
|
+
|
44
93
|
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require_relative "source_control_systems/base"
|
2
|
+
require 'digest/sha1'
|
3
|
+
require 'json'
|
4
|
+
module DebtCeiling
|
5
|
+
class ArcheologicalDig
|
6
|
+
ARCHEOLOGY_RECORD_VERSION_NUMBER = "v0" #increment for backward incompatible changes in record format
|
7
|
+
attr_reader :source_control, :records, :redis, :path, :opts
|
8
|
+
|
9
|
+
def self.dig_json_key(path)
|
10
|
+
project_name = File.expand_path(path).split('/').last
|
11
|
+
"DebtCeiling_#{project_name}_#{ARCHEOLOGY_RECORD_VERSION_NUMBER}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(path='.', opts={})
|
15
|
+
@redis = redis_if_available
|
16
|
+
@path = path
|
17
|
+
@opts = opts
|
18
|
+
@source_control = SourceControlSystem::Base.create
|
19
|
+
DebtCeiling.load_configuration unless opts[:preconfigured]
|
20
|
+
@records = source_control.revisions_refs(path).map do |commit|
|
21
|
+
if note = config_note_present_on_commit(commit)
|
22
|
+
extract_record_from_note(note)
|
23
|
+
else
|
24
|
+
build_record(commit)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
redis.set(self.class.dig_json_key(path), records.to_json) if redis
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def build_record(commit)
|
33
|
+
result = nil
|
34
|
+
source_control.travel_to_commit(commit) do
|
35
|
+
result = Audit.new(path,
|
36
|
+
opts.merge(skip_report: true,
|
37
|
+
warn_only: true,
|
38
|
+
preconfigured: true,
|
39
|
+
silent: true
|
40
|
+
)
|
41
|
+
)
|
42
|
+
create_note_on_commit(result, commit) if DebtCeiling.memoize_records_in_repo
|
43
|
+
end
|
44
|
+
archeology_record(result, commit)
|
45
|
+
end
|
46
|
+
|
47
|
+
def redis_if_available
|
48
|
+
require 'redis'
|
49
|
+
host = ENV['REDIS_HOST'] || 'localhost'
|
50
|
+
port = ENV['REDIS_PORT'] ? ENV['REDIS_PORT'].to_i : 6379
|
51
|
+
Redis.new(host: host, port: port)
|
52
|
+
rescue LoadError
|
53
|
+
end
|
54
|
+
|
55
|
+
def read_note_on(commit)
|
56
|
+
if redis
|
57
|
+
redis.get(commit_identifier(commit))
|
58
|
+
else
|
59
|
+
source_control.read_note_on(commit)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def config_note_present_on_commit(commit)
|
64
|
+
note = read_note_on(commit)
|
65
|
+
matched = !!note.match(commit_identifier(commit)) if note
|
66
|
+
note if matched
|
67
|
+
end
|
68
|
+
|
69
|
+
def extract_record_from_note(note)
|
70
|
+
note.split("\n").each_cons(2).each do |comment, json|
|
71
|
+
return JSON.parse(json) if comment.match(config_string)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def create_note_on_commit(result, commit)
|
76
|
+
note = <<-DATA
|
77
|
+
#{commit_identifier(commit)}
|
78
|
+
#{archeology_record_json(result, commit)}
|
79
|
+
DATA
|
80
|
+
if redis
|
81
|
+
redis.set(commit_identifier(commit), note)
|
82
|
+
else
|
83
|
+
source_control.add_note_to(commit, note)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def commit_identifier(commit)
|
88
|
+
"debt_ceiling_#{commit}_#{config_string}"
|
89
|
+
end
|
90
|
+
|
91
|
+
def archeology_record_json(result, commit)
|
92
|
+
json = "#{archeology_record(result, commit).to_json}"
|
93
|
+
json.gsub!('"','\"') unless redis
|
94
|
+
json
|
95
|
+
end
|
96
|
+
|
97
|
+
def archeology_record(result, commit)
|
98
|
+
case DebtCeiling.archeology_detail
|
99
|
+
when :low
|
100
|
+
default_record(result, commit)
|
101
|
+
else
|
102
|
+
{max_debt: result.accounting.max_debt}.merge(default_record(result, commit))
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def default_record(result, commit)
|
107
|
+
{debt: result.total_debt, failed: !!result.failed_condition?, commit: commit}
|
108
|
+
end
|
109
|
+
|
110
|
+
def config_string
|
111
|
+
@config_string ||= config_hash_string + ARCHEOLOGY_RECORD_VERSION_NUMBER
|
112
|
+
end
|
113
|
+
|
114
|
+
def config_hash_string
|
115
|
+
Digest::SHA1.hexdigest(DebtCeiling.config_array.to_json)
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
end
|
data/lib/debt_ceiling/audit.rb
CHANGED
@@ -4,18 +4,15 @@ module DebtCeiling
|
|
4
4
|
include CommonMethods
|
5
5
|
undef :+
|
6
6
|
|
7
|
-
CONFIG_FILE_NAME = ".debt_ceiling.rb"
|
8
|
-
CONFIG_LOCATIONS = ["#{Dir.pwd}/#{CONFIG_FILE_NAME}", "#{Dir.home}/#{CONFIG_FILE_NAME}"]
|
9
7
|
FAILURE_MESSAGE = "DEBT CEILING FAILURE: "
|
10
8
|
TOTAL_LIMIT = "EXCEEDED TOTAL DEBT CEILING "
|
11
|
-
NO_CONFIG_FOUND = "No #{CONFIG_FILE_NAME} configuration file detected in #{Dir.pwd} or ~/, using defaults"
|
12
9
|
PER_MODULE_MESSAGE = "MAX DEBT PER MODULE EXCEEDED IN AT LEAST ONE LOCATION"
|
13
10
|
MISSED_TARGET_MESSAGE = "MISSED DEBT REDUCTION TARGET "
|
14
11
|
|
15
12
|
attr_reader :accounting, :dir, :loaded
|
16
13
|
|
17
14
|
def_delegators :configuration,
|
18
|
-
:
|
15
|
+
:debt_ceiling, :reduction_target, :reduction_date, :max_debt_per_module
|
19
16
|
|
20
17
|
def_delegator :accounting, :total_debt
|
21
18
|
|
@@ -24,25 +21,18 @@ module DebtCeiling
|
|
24
21
|
@dir = dir
|
25
22
|
@accounting = perform_accounting
|
26
23
|
accounting.print_results unless opts[:skip_report]
|
27
|
-
puts failure_message
|
24
|
+
puts failure_message unless opts[:silent]
|
28
25
|
fail_test if failed_condition? && !opts[:warn_only]
|
29
26
|
end
|
30
27
|
|
31
|
-
|
32
|
-
|
33
|
-
def load_configuration
|
34
|
-
config_file_location ? load(config_file_location) : puts(NO_CONFIG_FOUND)
|
35
|
-
|
36
|
-
load extension_path if extension_path && File.exist?(extension_path)
|
37
|
-
@loaded = true
|
28
|
+
def failed_condition?
|
29
|
+
exceeded_total_limit || missed_target || max_debt_per_module_exceeded
|
38
30
|
end
|
39
31
|
|
40
|
-
|
41
|
-
CONFIG_LOCATIONS.find {|loc| File.exist?(loc) }
|
42
|
-
end
|
32
|
+
private
|
43
33
|
|
44
34
|
def perform_accounting
|
45
|
-
load_configuration unless loaded
|
35
|
+
DebtCeiling.load_configuration unless loaded
|
46
36
|
Accounting.new(dir)
|
47
37
|
end
|
48
38
|
|
@@ -59,10 +49,6 @@ module DebtCeiling
|
|
59
49
|
deprecated_reference_pairs[string] = value
|
60
50
|
end
|
61
51
|
|
62
|
-
def failed_condition?
|
63
|
-
exceeded_total_limit || missed_target || max_debt_per_module_exceeded
|
64
|
-
end
|
65
|
-
|
66
52
|
def failure_message
|
67
53
|
<<-MESG
|
68
54
|
#{FAILURE_MESSAGE if failed_condition?}#{exceeded_total_limit}#{missed_target}
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require "shellwords"
|
2
|
+
#copied from rubycritic, hope/plan to augment, pull into seperate gem and PR as shared code?
|
3
|
+
module DebtCeiling
|
4
|
+
module SourceControlSystem
|
5
|
+
|
6
|
+
class Base
|
7
|
+
@@systems = []
|
8
|
+
|
9
|
+
def self.register_system
|
10
|
+
@@systems << self
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.systems
|
14
|
+
@@systems
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.create
|
18
|
+
supported_system = systems.find(&:supported?)
|
19
|
+
if supported_system
|
20
|
+
supported_system.new
|
21
|
+
else
|
22
|
+
puts "DebtCeiling can provide more feedback if you use a #{connected_system_names} repository."
|
23
|
+
Double.new
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.connected_system_names
|
28
|
+
"#{systems[0...-1].join(', ')} or #{systems[-1]}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
require_relative "base"
|
36
|
+
require_relative "git"
|
37
|
+
require_relative "mercurial"
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module DebtCeiling
|
2
|
+
module SourceControlSystem
|
3
|
+
class Double < Base
|
4
|
+
def revisions_count(_)
|
5
|
+
"N/A"
|
6
|
+
end
|
7
|
+
|
8
|
+
def date_of_last_commit(_)
|
9
|
+
nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def add_note_to(ref, message)
|
13
|
+
nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def read_note_on(ref)
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def travel_to_commit(ref)
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def revisions_count(path)
|
25
|
+
nil
|
26
|
+
end
|
27
|
+
|
28
|
+
def revisions_refs(path)
|
29
|
+
[]
|
30
|
+
end
|
31
|
+
|
32
|
+
def revision?
|
33
|
+
false
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module DebtCeiling
|
2
|
+
module SourceControlSystem
|
3
|
+
require 'open3'
|
4
|
+
class Git < Base
|
5
|
+
register_system
|
6
|
+
|
7
|
+
def self.supported?
|
8
|
+
`git branch 2>&1` && $?.success?
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.to_s
|
12
|
+
"Git"
|
13
|
+
end
|
14
|
+
|
15
|
+
def revisions_count(path)
|
16
|
+
revisions_refs(path).count
|
17
|
+
end
|
18
|
+
|
19
|
+
def revisions_refs(path)
|
20
|
+
popen3("git log --follow --format=%h #{path.shellescape}").split("\n")
|
21
|
+
end
|
22
|
+
|
23
|
+
def date_of_last_commit(path)
|
24
|
+
popen3("git log -1 --date=iso --format=%ad #{path.shellescape}").chomp!
|
25
|
+
end
|
26
|
+
|
27
|
+
def revision?
|
28
|
+
head_reference && $?.success?
|
29
|
+
end
|
30
|
+
|
31
|
+
def head_reference
|
32
|
+
popen3("git rev-parse --verify HEAD").chomp
|
33
|
+
end
|
34
|
+
|
35
|
+
def add_note_to(ref, message)
|
36
|
+
popen3(%Q(git notes append #{ref} -m "#{message}"))
|
37
|
+
end
|
38
|
+
|
39
|
+
def read_note_on(ref)
|
40
|
+
popen3("git notes show #{ref}")
|
41
|
+
end
|
42
|
+
|
43
|
+
def travel_to_commit(ref)
|
44
|
+
stash_successful = stash_changes
|
45
|
+
current_branch = popen3("git symbolic-ref HEAD").chomp.split('/').last
|
46
|
+
popen3("git checkout #{ref}")
|
47
|
+
yield
|
48
|
+
ensure
|
49
|
+
popen3("git checkout #{current_branch}")
|
50
|
+
travel_to_original_state if stash_successful
|
51
|
+
end
|
52
|
+
|
53
|
+
def travel_to_head
|
54
|
+
stash_successful = stash_changes
|
55
|
+
yield
|
56
|
+
ensure
|
57
|
+
travel_to_original_state if stash_successful
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def stash_changes
|
63
|
+
stashes_count_before = stashes_count
|
64
|
+
popen3("git stash")
|
65
|
+
stashes_count_after = stashes_count
|
66
|
+
stashes_count_after > stashes_count_before
|
67
|
+
end
|
68
|
+
|
69
|
+
def stashes_count
|
70
|
+
popen3("git stash list --format=%h").count("\n")
|
71
|
+
end
|
72
|
+
|
73
|
+
def travel_to_original_state
|
74
|
+
popen3("git stash pop")
|
75
|
+
end
|
76
|
+
|
77
|
+
def popen3(cmd)
|
78
|
+
Open3.popen3(cmd) do |_,stdout,error|
|
79
|
+
stdout.read if error.read.empty?
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module DebtCeiling
|
2
|
+
module SourceControlSystem
|
3
|
+
|
4
|
+
class Mercurial < Base
|
5
|
+
register_system
|
6
|
+
|
7
|
+
def self.supported?
|
8
|
+
`hg verify 2>&1` && $?.success?
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.to_s
|
12
|
+
"Mercurial"
|
13
|
+
end
|
14
|
+
|
15
|
+
def revisions_count(path)
|
16
|
+
`hg log #{path.shellescape} --template '1'`.size
|
17
|
+
end
|
18
|
+
|
19
|
+
def date_of_last_commit(path)
|
20
|
+
`hg log #{path.shellescape} --template '{date|isodate}' --limit 1`.chomp
|
21
|
+
end
|
22
|
+
|
23
|
+
def add_note_to(ref, message)
|
24
|
+
nil #unsupported AFAIK
|
25
|
+
end
|
26
|
+
|
27
|
+
def read_note_on(ref)
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
|
31
|
+
def travel_to_commit(ref)
|
32
|
+
nil #TODO
|
33
|
+
end
|
34
|
+
|
35
|
+
def revisions_count(path)
|
36
|
+
nil #TODO
|
37
|
+
end
|
38
|
+
|
39
|
+
def revisions_refs(path)
|
40
|
+
[] #TODO
|
41
|
+
end
|
42
|
+
|
43
|
+
def revision?
|
44
|
+
false
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
data/lib/debt_ceiling/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: debt_ceiling
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brian Glusman
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-12-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubycritic
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0.10'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: sparkr
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.4.1
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.4.1
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: configurations
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -111,7 +125,7 @@ dependencies:
|
|
111
125
|
description: |2
|
112
126
|
Get a grip on your technical debt
|
113
127
|
email:
|
114
|
-
- bglusman@
|
128
|
+
- bglusman@stridenyc.com
|
115
129
|
executables:
|
116
130
|
- debt_ceiling
|
117
131
|
extensions: []
|
@@ -131,12 +145,17 @@ files:
|
|
131
145
|
- examples/custom_debt.rb.example
|
132
146
|
- lib/debt_ceiling.rb
|
133
147
|
- lib/debt_ceiling/accounting.rb
|
148
|
+
- lib/debt_ceiling/archeological_dig.rb
|
134
149
|
- lib/debt_ceiling/audit.rb
|
135
150
|
- lib/debt_ceiling/common_methods.rb
|
136
151
|
- lib/debt_ceiling/compatibility.rb
|
137
152
|
- lib/debt_ceiling/custom_debt.rb
|
138
153
|
- lib/debt_ceiling/debt.rb
|
139
154
|
- lib/debt_ceiling/file_attributes.rb
|
155
|
+
- lib/debt_ceiling/source_control_systems/base.rb
|
156
|
+
- lib/debt_ceiling/source_control_systems/double.rb
|
157
|
+
- lib/debt_ceiling/source_control_systems/git.rb
|
158
|
+
- lib/debt_ceiling/source_control_systems/mercurial.rb
|
140
159
|
- lib/debt_ceiling/static_analysis_debt.rb
|
141
160
|
- lib/debt_ceiling/version.rb
|
142
161
|
- spec/debt_ceiling_spec.rb
|
@@ -168,3 +187,4 @@ signing_key:
|
|
168
187
|
specification_version: 4
|
169
188
|
summary: DebtCeiling helps you track Tech Debt
|
170
189
|
test_files: []
|
190
|
+
has_rdoc:
|