git_fame 1.6.0 → 1.7.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0b26bdf2f4da7bdd079f978625dd588c62129595
4
- data.tar.gz: f0f316759efda81f61fdee295afe76e1cac9dc7f
3
+ metadata.gz: f884e24c83b7a966af59ab96a045ea3ece06b6ff
4
+ data.tar.gz: fa4e2967c967867b568ace60dc7bd62bf1a191d4
5
5
  SHA512:
6
- metadata.gz: e646b20e3fca5711245540a3c2d1996adbfbeeeed14e59ff9c1a26324d5cbbf5b8c303c87fb8b9aed287884d19be85d9ab2d67379d1a2992fd7046e77096b9a2
7
- data.tar.gz: 4105beaa8b3e8d0000a6dbe00ce6a434012345e1f204f579344ce80c58a2dbf6cd744856e95b46eca4c17057457e6dfee7e577f5c0ae5089879f257e8854b564
6
+ metadata.gz: a3f5a220b5e3a6211c3d8aad13d881bcb500e1e0bff4ad8b16bf984e0038c3acd1f4d1673ee6577a495d7be8387fe5c24d33b6f6f612010cee8d0e5084781d79
7
+ data.tar.gz: 53101b66a4a44b3eabf739c43bbabf33664e5ccbcee1225566e2dcf41aeb47217eac3225b945f2870de0549c7e89854c8fca6ddf29c31c82d4fb1846b441dab3
data/.gitignore CHANGED
@@ -15,3 +15,4 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ .byebug_history
data/.rspec CHANGED
@@ -1,5 +1,5 @@
1
1
  --color
2
- -fs
3
2
  -Ilib
4
3
  -Ispec
5
- --require spec_helper
4
+ --require spec_helper
5
+ --exclude-pattern spec/fixtures/**/*_spec.rb
data/README.md CHANGED
@@ -131,7 +131,10 @@ The list of authors may include duplicate people. If a git user's configured nam
131
131
  ## Testing
132
132
 
133
133
  1. Download fixtures (`spec/fixtures`) using `git submodule update --init`.
134
- 2. Run rspec using `rspec spec/git_fame_spec.rb`.
134
+ 2. Run rspec using `bundle exec rspec`.
135
+
136
+ Note that `puts` has been disabled to avoid unnecessary output during testing.
137
+ Visit `spec/spec_helper.rb` to enable it again.
135
138
 
136
139
  ## Requirements
137
140
 
@@ -18,7 +18,6 @@ opts = Trollop::options do
18
18
  opt :format, "Format (pretty/csv)", default: "pretty", type: String
19
19
  end
20
20
 
21
- Trollop::die :repository, "is not a git repository" unless GitFame::Base.git_repository?(opts[:repository])
22
21
  Trollop::die :sort, "must be one of the following; #{sort.join(", ")}" unless sort.include?(opts[:sort])
23
22
  fame = GitFame::Base.new({
24
23
  repository: opts[:repository],
@@ -28,12 +28,10 @@ Generates data like:
28
28
  gem.add_dependency("trollop")
29
29
  gem.add_dependency("hirb")
30
30
  gem.add_dependency("mimer_plus")
31
+ gem.add_dependency("scrub_rb")
31
32
 
32
- if RUBY_VERSION.to_f < 2.1
33
- gem.add_dependency("scrub_rb")
34
- end
35
-
36
- gem.add_development_dependency("rspec", "2.10.0")
33
+ gem.add_development_dependency("rspec", "~> 3.0")
34
+ gem.add_development_dependency("rspec-collection_matchers")
37
35
  gem.add_development_dependency("rake")
38
36
  gem.add_development_dependency("coveralls")
39
37
 
@@ -1,9 +1,11 @@
1
1
  module GitFame
2
2
  class Author
3
3
  include GitFame::Helper
4
- attr_accessor :name, :raw_files, :raw_commits,
4
+ attr_accessor :name, :raw_files, :raw_commits,
5
5
  :raw_loc, :files_list, :file_type_counts
6
6
 
7
+ FIELDS = [:loc, :commits, :files]
8
+
7
9
  #
8
10
  # @args Hash
9
11
  #
@@ -12,7 +14,7 @@ module GitFame
12
14
  @raw_commits = 0
13
15
  @raw_files = 0
14
16
  @file_type_counts = Hash.new(0)
15
- args.keys.each do |name|
17
+ args.keys.each do |name|
16
18
  instance_variable_set "@" + name.to_s, args[name]
17
19
  end
18
20
  end
@@ -22,13 +24,15 @@ module GitFame
22
24
  # @return String Distribution (in %) between users
23
25
  #
24
26
  def distribution
25
- "%.1f / %.1f / %.1f" % [:loc, :commits, :files].
26
- map{ |w| (send("raw_#{w}") / @parent.send(w).to_f) * 100 }
27
+ "%s / %s / %s" % FIELDS.map do |field|
28
+ ("%.1f" % (percent_for_field(field) * 100)).rjust(4, " ")
29
+ end
27
30
  end
31
+ alias_method :"distribution (%)", :distribution
28
32
 
29
- [:commits, :files, :loc].each do |method|
33
+ FIELDS.each do |method|
30
34
  define_method(method) do
31
- number_with_delimiter(send("raw_#{method}"))
35
+ number_with_delimiter(raw(method))
32
36
  end
33
37
  end
34
38
 
@@ -38,5 +42,23 @@ module GitFame
38
42
  def method_missing(m, *args, &block)
39
43
  file_type_counts[m.to_s]
40
44
  end
45
+
46
+ def raw(method)
47
+ unless FIELDS.include?(method.to_sym)
48
+ raise "can't access raw '#{method}' on author"
49
+ end
50
+
51
+ send("raw_#{method}")
52
+ end
53
+
54
+ def inc(method, amount)
55
+ send("raw_#{method}=", raw(method) + amount)
56
+ end
57
+
58
+ private
59
+
60
+ def percent_for_field(field)
61
+ raw(field) / @parent.send(field).to_f
62
+ end
41
63
  end
42
64
  end
@@ -1,5 +1,9 @@
1
1
  require "csv"
2
2
  require_relative "./errors"
3
+ require_relative "./result"
4
+ require_relative "./file"
5
+ require "open3"
6
+
3
7
  if RUBY_VERSION.to_f < 2.1
4
8
  require "scrub_rb"
5
9
  end
@@ -7,6 +11,7 @@ end
7
11
  module GitFame
8
12
  class Base
9
13
  include GitFame::Helper
14
+ attr_accessor :file_extensions
10
15
 
11
16
  #
12
17
  # @args[:repository] String Absolute path to git repository
@@ -17,25 +22,31 @@ module GitFame
17
22
  # @args[:branch] String Branch to run from
18
23
  #
19
24
  def initialize(args)
20
- @sort = "loc"
21
- @progressbar = false
22
- @whitespace = false
23
- @bytype = false
24
- @extensions = ""
25
- @exclude = ""
26
- @include = ""
27
- @authors = {}
25
+ @default_settings = {
26
+ branch: "master",
27
+ sorting: "loc"
28
+ }
29
+ @progressbar = args.fetch(:progressbar, false)
28
30
  @file_authors = Hash.new { |h,k| h[k] = {} }
29
- args.keys.each do |name|
30
- instance_variable_set "@" + name.to_s, args[name]
31
+ # Create array out of comma separated list
32
+ @exclude = args.fetch(:exclude, "").split(",").
33
+ map{ |path| path.strip.sub(/\A\//, "") }
34
+ @extensions = args.fetch(:extensions, "").split(",")
35
+ # Default sorting option is by loc
36
+ @include = args.fetch(:include, "")
37
+ @sort = args.fetch(:sort, @default_settings.fetch(:sorting))
38
+ @repository = args.fetch(:repository)
39
+ @bytype = args.fetch(:bytype, false)
40
+ @branch = args.fetch(:branch, default_branch)
41
+
42
+ # User defined branch must exist
43
+ if not blank?(@branch) and not default_branch_exists?
44
+ raise GitFame::BranchNotFound, "Branch '#{@branch}' does not exist"
31
45
  end
32
- @exclude = convert_exclude_paths_to_array
33
- @extensions = convert_extensions_to_array
34
- @branch = (@branch.nil? or @branch.empty?) ? "master" : @branch
35
46
 
36
47
  # Fields that should be visible in the final table
37
48
  # Used by #csv_puts, #to_csv and #pretty_puts
38
- # Format: [ [:method_on_author, "custom column name"] ]
49
+ # Format: [ [ :method_on_author, "custom column name" ] ]
39
50
  @visible_fields = [
40
51
  :name,
41
52
  :loc,
@@ -43,17 +54,10 @@ module GitFame
43
54
  :files,
44
55
  [:distribution, "distribution (%)"]
45
56
  ]
46
- end
47
-
48
- #
49
- # @return Boolean Is the given @dir a git repository?
50
- # @dir Path (relative or absolute) to git repository
51
- #
52
- def self.git_repository?(dir)
53
- return false unless File.directory?(dir)
54
- Dir.chdir(dir) do
55
- system "git rev-parse --git-dir > /dev/null 2>&1"
56
- end
57
+ @cache = {}
58
+ @file_extensions = []
59
+ @wopt = args.fetch(:whitespace, false) ? "-w" : ""
60
+ @authors = {}
57
61
  end
58
62
 
59
63
  #
@@ -66,7 +70,7 @@ module GitFame
66
70
  puts "Total number of lines: #{number_with_delimiter(loc)}"
67
71
  puts "Total number of commits: #{number_with_delimiter(commits)}\n"
68
72
 
69
- table(authors, fields: fields)
73
+ table(authors, fields: printable_fields)
70
74
  end
71
75
 
72
76
  #
@@ -81,7 +85,7 @@ module GitFame
81
85
  #
82
86
  def to_csv
83
87
  CSV.generate do |csv|
84
- csv << printable_fields
88
+ csv << fields
85
89
  authors.each do |author|
86
90
  csv << fields.map do |f|
87
91
  author.send(f)
@@ -92,95 +96,195 @@ module GitFame
92
96
 
93
97
  #
94
98
  # @return Fixnum Total number of files
99
+ # TODO: Rename this
95
100
  #
96
101
  def files
97
- populate.instance_variable_get("@files").count
102
+ file_list.count
98
103
  end
99
104
 
100
105
  #
101
106
  # @return Array list of repo files processed
102
107
  #
103
108
  def file_list
104
- populate.instance_variable_get("@files")
109
+ populate { current_files }
105
110
  end
106
111
 
107
112
  #
108
113
  # @return Fixnum Total number of commits
109
114
  #
110
115
  def commits
111
- authors.inject(0){ |result, author| author.raw_commits + result }
116
+ authors.inject(0) { |result, author| author.raw(:commits) + result }
112
117
  end
113
118
 
114
119
  #
115
120
  # @return Fixnum Total number of lines
116
121
  #
117
122
  def loc
118
- populate.authors.
119
- inject(0){ |result, author| author.raw_loc + result }
123
+ authors.inject(0) { |result, author| author.raw(:loc) + result }
120
124
  end
121
125
 
122
126
  #
123
127
  # @return Array<Author> A list of authors
124
128
  #
125
129
  def authors
126
- @_authors ||= begin
127
- authors = populate.instance_variable_get("@authors").values
128
- if @sort
129
- authors.sort_by do |author|
130
- if @sort == "name"
131
- author.send(@sort)
132
- else
133
- -1 * author.send("raw_#{@sort}")
134
- end
130
+ cache(:authors) do
131
+ populate do
132
+ @authors.values.sort_by do |author|
133
+ @sort == "name" ? author.send(@sort) : -1 * author.raw(@sort)
135
134
  end
136
- else
137
- authors
138
135
  end
139
136
  end
140
137
  end
141
138
 
142
- #
143
- # @return Boolean Does the branch exist?
144
- #
145
- def branch_exists?
146
- Dir.chdir(@repository) do
147
- system "git show-ref #{@branch} > /dev/null 2>&1"
139
+ private
140
+
141
+ # Populates @authors and @file_extensions with data
142
+ # Block is called on every call to populate, but
143
+ # the data is only calculated once
144
+ def populate(&block)
145
+ cache(:populate) do
146
+ # Display progressbar with the number of files as countdown
147
+ progressbar = init_progressbar(current_files.count)
148
+
149
+ # Extract the blame history from all checked in files
150
+ current_files.each do |file|
151
+ progressbar.inc
152
+
153
+ # Skip if mimetype can't be decided
154
+ next unless type = Mimer.identify(File.join(@repository, file.path))
155
+ # Binary types isn't very usefull to run git-blame on
156
+ next if type.binary?
157
+
158
+ @file_extensions << file.extname
159
+
160
+ execute("git blame #{@wopt} --line-porcelain #{@branch} -- '#{file}'") do |result|
161
+ # Authors from git blame has to be parsed
162
+ result.to_s.scan(/^author (.+)$/).each do |raw_author, _|
163
+ # Create or find already existing user
164
+ author = fetch(raw_author)
165
+
166
+ # Get author by name and increase the number of loc by 1
167
+ author.inc(:loc, 1)
168
+
169
+ # Store the files and authors together
170
+ @file_authors[raw_author][file] ||= 1
171
+
172
+ @bytype && author.file_type_counts[file.extname] += 1
173
+ end
174
+ end
175
+ end
176
+
177
+ # Get repository summery and update each author accordingly
178
+ execute("git shortlog #{@branch} -se") do |result|
179
+ result.to_s.split("\n").map do |line|
180
+ _, commits, raw_author = line.match(%r{^\s*(\d+)\s+(.+?)\s+<.+?>}).to_a
181
+ author = fetch(raw_author)
182
+ # There might be duplicate authors using git shortlog
183
+ # (same name, different emails). Update already existing authors
184
+ if author.raw(:commits).zero?
185
+ update(raw_author, {
186
+ raw_commits: commits.to_i,
187
+ raw_files: @file_authors[raw_author].keys.count,
188
+ files_list: @file_authors[raw_author].keys
189
+ })
190
+ else
191
+ # Calculate the number of files edited by users
192
+ files = (author.files_list + @file_authors[raw_author].keys).uniq
193
+ update(raw_author, {
194
+ raw_commits: commits.to_i + author.raw(:commits),
195
+ raw_files: files.count,
196
+ files_list: files
197
+ })
198
+ end
199
+ end
200
+ end
201
+
202
+ progressbar.finish
148
203
  end
149
- end
150
204
 
151
- private
205
+ block.call
206
+ end
152
207
 
208
+ # Uses the more printable names in @visible_fields
153
209
  def printable_fields
154
- @_printable_fields ||= raw_fields.map do |field|
155
- field.is_a?(Array) ? field.last : field
210
+ cache(:printable_fields) do
211
+ raw_fields.map do |field|
212
+ field.is_a?(Array) ? field.last : field
213
+ end
156
214
  end
157
215
  end
158
216
 
217
+ # Check to see if a string is empty (nil or "")
218
+ def blank?(value)
219
+ value.nil? or value.empty?
220
+ end
221
+
222
+ # Includes fields from file extensions
159
223
  def raw_fields
160
224
  return @visible_fields unless @bytype
161
- @_raw_fields ||= (
162
- @visible_fields + populate.instance_variable_get("@file_extensions")
163
- ).uniq
225
+ cache(:raw_fields) do
226
+ populate do
227
+ (@visible_fields + file_extensions).uniq
228
+ end
229
+ end
164
230
  end
165
231
 
232
+ # Method fields used by #to_csv and #pretty_puts
166
233
  def fields
167
- @_fields ||= raw_fields.map do |field|
168
- field.is_a?(Array) ? field.first : field
234
+ cache(:fields) do
235
+ raw_fields.map do |field|
236
+ field.is_a?(Array) ? field.first : field
237
+ end
169
238
  end
170
239
  end
171
240
 
172
- #
173
- # @command String Command to be executed inside the @repository path
174
- #
175
- def execute(command)
176
- Dir.chdir(@repository) { `#{command}`.scrub }
241
+ # Command to be executed at @repository
242
+ # @silent = true wont raise an error on exit code =! 0
243
+ def execute(command, silent = false, &block)
244
+ result = Open3.popen2e(command, chdir: @repository) do |_, out, thread|
245
+ Result.new(out.read, thread.value.success?)
246
+ end
247
+
248
+ return block.call(result) if result.success? or silent
249
+ raise cmd_error_message(command, result.data)
250
+ rescue Errno::ENOENT
251
+ raise cmd_error_message(command, $!.message)
177
252
  end
178
253
 
179
- #
180
- # @author String Author
181
- # @args Hash Argument that should be set in @return
182
- # @return Author
183
- #
254
+ def cmd_error_message(command, message)
255
+ "Could not run '#{command}' => #{message}"
256
+ end
257
+
258
+ # Boolean Does the branch exist?
259
+ def default_branch_exists?
260
+ branch_exists?(@branch)
261
+ end
262
+
263
+ # Does @branch exist in the current git repo?
264
+ def branch_exists?(branch)
265
+ execute("git show-ref '#{branch}'", true) do |result|
266
+ result.success?
267
+ end
268
+ end
269
+
270
+ # In those cases the users havent defined a branch
271
+ # We try to define it for him/her by
272
+ # 1. check if { @default_settings.fetch(:branch) } exists
273
+ # 1. look at .git/HEAD (basically)
274
+ def default_branch
275
+ if branch_exists?(@default_settings.fetch(:branch))
276
+ return @default_settings.fetch(:branch)
277
+ end
278
+
279
+ execute("git rev-parse HEAD") do |result|
280
+ return result.data if result.success?
281
+ end
282
+
283
+ raise BranchNotFound.new("No branch found")
284
+ end
285
+
286
+ # Tries to create an author, unless it already exists in cache
287
+ # User is always updated with the passed @args
184
288
  def update(author, args)
185
289
  fetch(author).tap do |found|
186
290
  args.keys.each do |key|
@@ -189,115 +293,43 @@ module GitFame
189
293
  end
190
294
  end
191
295
 
192
- #
193
- # @return Author
194
- # @author String
195
- #
296
+ # Fetches user from cache
196
297
  def fetch(author)
197
- @authors[author] ||= Author.new({name: author, parent: self})
298
+ @authors[author] ||= Author.new({ name: author, parent: self })
198
299
  end
199
300
 
200
- #
201
- # @return GitFame
202
- #
203
- def populate
204
- @_populate ||= begin
205
- unless branch_exists?
206
- raise BranchNotFound.new("Does '#{@branch}' exist?")
207
- end
208
-
209
- command = "git ls-tree -r #{@branch} --name-only #{@include}"
210
- command += " | grep \"\\.\\(#{@extensions.join("\\|")}\\)$\"" unless @extensions.empty?
211
- @files = execute(command).split("\n")
212
- @file_extensions = []
213
- remove_excluded_files
214
- progressbar = SilentProgressbar.new(
215
- "Blame",
216
- @files.count,
217
- @progressbar
218
- )
219
- blame_opts = @whitespace ? "-w" : ""
220
- @files.each do |file|
221
- progressbar.inc
222
- if @bytype
223
- file_extension = File.extname(file).gsub(/^\./, "")
224
- file_extension = "unknown" if file_extension.empty?
225
- end
226
-
227
- unless type = Mimer.identify(File.join(@repository, file))
228
- next
229
- end
230
-
231
- if type.binary?
232
- next
301
+ # List all files in current git directory, excluding
302
+ # extensions in @extensions defined by the user
303
+ def current_files
304
+ cache(:current_files) do
305
+ execute("git ls-tree -r #{@branch} --name-only #{@include}") do |result|
306
+ files = remove_excluded_files(result.to_s.split("\n")).map do |path|
307
+ GitFame::FileUnit.new(path)
233
308
  end
234
309
 
235
- # only count extensions that aren't binary
236
- @file_extensions << file_extension
237
-
238
- output = execute(
239
- "git blame #{blame_opts} --line-porcelain #{@branch} -- '#{file}'"
240
- )
241
- output.scan(/^author (.+)$/).each do |author|
242
- fetch(author.first).raw_loc += 1
243
- @file_authors[author.first][file] ||= 1
244
- if @bytype
245
- fetch(author.first).
246
- file_type_counts[file_extension] += 1
247
- end
248
- end
249
- end
250
-
251
- execute("git shortlog #{@branch} -se").split("\n").map do |l|
252
- _, commits, u = l.match(%r{^\s*(\d+)\s+(.+?)\s+<.+?>}).to_a
253
- user = fetch(u)
254
- # Has this user been updated before?
255
- if user.raw_commits.zero?
256
- update(u, {
257
- raw_commits: commits.to_i,
258
- raw_files: @file_authors[u].keys.count,
259
- files_list: @file_authors[u].keys
260
- })
261
- else
262
- # Calculate the number of files edited by users
263
- files = (user.files_list + @file_authors[u].keys).uniq
264
- update(u, {
265
- raw_commits: commits.to_i + user.raw_commits,
266
- raw_files: files.count,
267
- files_list: files
268
- })
269
- end
310
+ return files if @extensions.empty?
311
+ files.select { |file| @extensions.include?(file.extname) }
270
312
  end
271
-
272
- progressbar.finish
273
-
274
313
  end
275
- return self
276
314
  end
277
315
 
278
- #
279
- # Converts @exclude argument to an array and removes leading slash
280
- #
281
- def convert_exclude_paths_to_array
282
- @exclude.split(",").map{|path| path.strip.sub(/\A\//, "") }
316
+ # The block is only called once for every unique key
317
+ # Used to ensure methods are only called once
318
+ def cache(key, &block)
319
+ @cache[key] ||= block.call
283
320
  end
284
321
 
285
- #
286
- # Converts @extensions argument to an array
287
- #
288
- def convert_extensions_to_array
289
- @extensions.split(",")
322
+ # Removes files excluded by the user
323
+ # Defined using --exclude
324
+ def remove_excluded_files(files)
325
+ return files if @exclude.empty?
326
+ files.reject do |file|
327
+ @exclude.any? { |exclude| file.match(exclude) }
328
+ end
290
329
  end
291
330
 
292
- #
293
- # Removes files matching paths in @exclude from @files instance variable
294
- #
295
- def remove_excluded_files
296
- return if @exclude.empty?
297
- @files = @files.map do |path|
298
- next if path =~ /\A(#{@exclude.join("|")})/
299
- path
300
- end.compact
331
+ def init_progressbar(files_count)
332
+ SilentProgressbar.new("GitBlame", files_count, @progressbar)
301
333
  end
302
334
  end
303
335
  end
@@ -0,0 +1,13 @@
1
+ module GitFame
2
+ class FileUnit < Struct.new(:path)
3
+ def extname
4
+ return @_extname if @_extname
5
+ @_extname = ::File.extname(path).sub(/^\./, "")
6
+ @_extname = @_extname.empty? ? "unknown" : @_extname
7
+ end
8
+
9
+ def to_s
10
+ path
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,6 @@
1
+ module GitFame
2
+ class Result < Struct.new(:data, :success)
3
+ def to_s; data; end
4
+ def success?; success; end
5
+ end
6
+ end
@@ -1,3 +1,3 @@
1
1
  module GitFame
2
- VERSION = "1.6.0"
2
+ VERSION = "1.7.1"
3
3
  end
@@ -1,11 +1,12 @@
1
1
  describe GitFame::Base do
2
- let(:subject) { GitFame::Base.new({repository: @repository}) }
2
+ let(:subject) { GitFame::Base.new({repository: repository}) }
3
3
  describe "#authors" do
4
4
  it "should have a list of authors" do
5
5
  subject.should have(3).authors
6
6
  end
7
7
 
8
8
  describe "author" do
9
+ require "pp"
9
10
  let(:author) { subject.authors.last }
10
11
  it "should have a bunch of commits" do
11
12
  author.raw_commits.should eq(23)
@@ -61,7 +62,7 @@ describe GitFame::Base do
61
62
  describe "sort" do
62
63
  it "should be able to sort #authors by name" do
63
64
  authors = GitFame::Base.new({
64
- repository: @repository,
65
+ repository: repository,
65
66
  sort: "name"
66
67
  }).authors
67
68
  authors.map(&:name).
@@ -70,7 +71,7 @@ describe GitFame::Base do
70
71
 
71
72
  it "should be able to sort #authors by commits" do
72
73
  authors = GitFame::Base.new({
73
- repository: @repository,
74
+ repository: repository,
74
75
  sort: "commits"
75
76
  }).authors
76
77
  authors.map(&:name).
@@ -79,7 +80,7 @@ describe GitFame::Base do
79
80
 
80
81
  it "should be able to sort #authors by files" do
81
82
  authors = GitFame::Base.new({
82
- repository: @repository,
83
+ repository: repository,
83
84
  sort: "files"
84
85
  }).authors
85
86
  authors.map(&:name).
@@ -90,7 +91,7 @@ describe GitFame::Base do
90
91
  describe "#command_line_arguments" do
91
92
  let(:subject) do
92
93
  GitFame::Base.new({
93
- repository: @repository,
94
+ repository: repository,
94
95
  exclude: "lib",
95
96
  bytype: true,
96
97
  extensions: "rb,rdoc"
@@ -98,11 +99,11 @@ describe GitFame::Base do
98
99
  end
99
100
 
100
101
  it "should exclude the lib folder" do
101
- subject.file_list.include?("lib/gash.rb").should be_false
102
+ subject.file_list.include?("lib/gash.rb").should be_falsey
102
103
  end
103
104
 
104
105
  it "should exclude non rb or rdoc files" do
105
- subject.file_list.include?("HISTORY").should be_false
106
+ subject.file_list.include?("HISTORY").should be_falsey
106
107
  end
107
108
 
108
109
  let(:author) { subject.authors.find { |author| author.name == "7rans" } }
@@ -131,37 +132,17 @@ describe GitFame::Base do
131
132
  end
132
133
 
133
134
  it "should be equal to" do
134
- subject.to_csv.should eq("name,loc,commits,files,distribution (%)\n" \
135
+ subject.to_csv.should eq("name,loc,commits,files,distribution\n" \
135
136
  "Magnus Holm,586,41,4,54.2 / 58.6 / 25.0\n" \
136
- "7rans,360,6,10,33.3 / 8.6 / 62.5\n" \
137
+ "7rans,360,6,10,33.3 / 8.6 / 62.5\n" \
137
138
  "Linus Oleander,136,23,7,12.6 / 32.9 / 43.8\n")
138
139
  end
139
140
  end
140
141
 
141
- describe ".git_repository?" do
142
- it "should know if a folder is a git repository [absolute path]" do
143
- GitFame::Base.git_repository?(@repository).should eq(true)
144
- end
145
-
146
- it "should know if a folder exists or not [absolute path]" do
147
- GitFame::Base.git_repository?("/f67c2bcbfcfa30fccb36f72dca22a817").
148
- should eq(false)
149
- end
150
-
151
- it "should know if a folder is a git repository [relative path]" do
152
- GitFame::Base.git_repository?("spec/fixtures/gash").should eq(true)
153
- end
154
-
155
- it "should know if a folder exists or not [relative path]" do
156
- GitFame::Base.git_repository?("f67c2bcbfcfa30fccb36f72dca22a817").
157
- should eq(false)
158
- end
159
- end
160
-
161
142
  describe "branches" do
162
143
  it "should handle existing branches" do
163
144
  authors = GitFame::Base.new({
164
- repository: @repository,
145
+ repository: repository,
165
146
  branch: "0.1.0"
166
147
  }).authors
167
148
 
@@ -172,8 +153,8 @@ describe GitFame::Base do
172
153
  it "should raise an error if branch doesn't exist" do
173
154
  expect {
174
155
  GitFame::Base.new({
175
- repository: @repository,
176
- branch: "f67c2bcbfcfa30fccb36f72dca22a817"
156
+ repository: repository,
157
+ branch: "-----"
177
158
  }).authors
178
159
  }.to raise_error(GitFame::BranchNotFound)
179
160
  end
@@ -1,16 +1,21 @@
1
1
  require "rspec"
2
2
  require "git_fame"
3
3
  require "coveralls"
4
+ require "rspec/collection_matchers"
5
+ require_relative "./support/startup"
4
6
 
5
7
  Coveralls.wear!
6
8
 
7
9
  RSpec.configure do |config|
10
+ config.include GitFame::Startup
8
11
  config.mock_with :rspec
9
12
  config.order = "random"
10
- config.before(:all) do
11
- @repository = File.join(File.dirname(File.dirname(__FILE__)), "spec/fixtures/gash")
12
- Dir.chdir(@repository) do
13
- `git checkout 7ab01bc5a720`
14
- end
13
+ config.expect_with(:rspec) { |c| c.syntax = [:should, :expect] }
14
+ config.fail_fast = false
15
+ config.before(:all) do
16
+ Dir.chdir(repository) { `git checkout 7ab01bc5a720` }
15
17
  end
18
+
19
+ # Remove this line to allow Kernel#puts
20
+ config.before { allow($stdout).to receive(:puts) }
16
21
  end
@@ -0,0 +1,7 @@
1
+ module GitFame
2
+ module Startup
3
+ def repository
4
+ File.join(File.dirname(File.dirname(__FILE__)), "fixtures/gash")
5
+ end
6
+ end
7
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: git_fame
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.0
4
+ version: 1.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Linus Oleander
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-05-16 00:00:00.000000000 Z
11
+ date: 2016-05-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: progressbar
@@ -66,20 +66,48 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: scrub_rb
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: rspec
71
85
  requirement: !ruby/object:Gem::Requirement
72
86
  requirements:
73
- - - '='
87
+ - - "~>"
74
88
  - !ruby/object:Gem::Version
75
- version: 2.10.0
89
+ version: '3.0'
76
90
  type: :development
77
91
  prerelease: false
78
92
  version_requirements: !ruby/object:Gem::Requirement
79
93
  requirements:
80
- - - '='
94
+ - - "~>"
81
95
  - !ruby/object:Gem::Version
82
- version: 2.10.0
96
+ version: '3.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec-collection_matchers
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
83
111
  - !ruby/object:Gem::Dependency
84
112
  name: rake
85
113
  requirement: !ruby/object:Gem::Requirement
@@ -130,11 +158,14 @@ files:
130
158
  - lib/git_fame/author.rb
131
159
  - lib/git_fame/base.rb
132
160
  - lib/git_fame/errors.rb
161
+ - lib/git_fame/file.rb
133
162
  - lib/git_fame/helper.rb
163
+ - lib/git_fame/result.rb
134
164
  - lib/git_fame/silent_progressbar.rb
135
165
  - lib/git_fame/version.rb
136
166
  - spec/git_fame_spec.rb
137
167
  - spec/spec_helper.rb
168
+ - spec/support/startup.rb
138
169
  homepage: https://github.com/oleander/git-fame-rb
139
170
  licenses: []
140
171
  metadata: {}
@@ -163,3 +194,4 @@ summary: 'Generates awesome stats from git-blame A Ruby wrapper for git-blame.
163
194
  test_files:
164
195
  - spec/git_fame_spec.rb
165
196
  - spec/spec_helper.rb
197
+ - spec/support/startup.rb