git_fame 1.6.0 → 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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