method_log 0.1.1 → 0.2.0

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
- SHA1:
3
- metadata.gz: c433833678edcb6c769cc4af052d1f76789d0b1a
4
- data.tar.gz: 5ca47df97661e48f31f5b109964bcf8fa4ba81cd
2
+ SHA256:
3
+ metadata.gz: 125db342c6c8ad4ba938d3fac7cee3fc7dfe7330a53b4c882d051570d851791b
4
+ data.tar.gz: 817b5da57430c8703b8d7b00adba2de76714d03cd588ff36bdec79837615f978
5
5
  SHA512:
6
- metadata.gz: b649b279915c749afd19cae699e2b1d2d93573994f52caf0c296a786b03560e4694bc73b58746ff4dada2dd379437fcea22995d300bd5dd65f4ac005591be4ba
7
- data.tar.gz: 1136f3efdf3218496c00cd17e44365cdadd81add70fcbeccef303d6e40028c286e0a51f4e53a12b1d08899d0648dbc14a0f6303f1a8d7c3ed33cef577374906b
6
+ metadata.gz: edc71468238c1f9dc27f6698a8726a4c9768d6706091788b68f0dc2dd1e257a59e3b76a9f82713bde8403b3416cea7ba226450436c5921019699f1ec65995163
7
+ data.tar.gz: 82777e60269dd12aabed2842386603a89f627f5f87666c20f06680d7eade642d49afc4b491537817a3c93c4b5358c0a2eff1eae4e96037efd986f2a23fee7605
data/.travis.yml CHANGED
@@ -1,6 +1,9 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.1.0
3
+ - 2.6.3
4
+ - 2.5.5
5
+ - 2.4.6
6
+ - 2.3.8
7
+ - 2.2.10
8
+ - 2.1.10
4
9
  - 2.0.0
5
- - 1.9.3
6
-
data/README.md CHANGED
@@ -4,7 +4,7 @@ Trace the history of an individual method in a git repository (experimental).
4
4
 
5
5
  ### Requirements
6
6
 
7
- * Ruby >= v1.9.3 (due to requirements of the `rugged` gem)
7
+ * Ruby >= v2.0.0 (due to requirements of the `parser` gem); although parsing of source code for Ruby >= v1.8 is possible
8
8
  * The [rugged](https://github.com/libgit2/rugged) Ruby gem (listed as dependency in gemspec)
9
9
  * The [libgit2](https://github.com/libgit2/libgit2) C library (included as part of rugged gem)
10
10
  * The [parser](https://github.com/whitequark/parser) Ruby gem (listed as dependency in gemspec)
@@ -15,21 +15,17 @@ Trace the history of an individual method in a git repository (experimental).
15
15
 
16
16
  ### Run
17
17
 
18
- $ method_log <options> <method-signature>
19
-
20
- # options:
21
- --patch, -p: Generate patch.
22
- --ruby-version, -r <s>: Parser Ruby version (18, 19, 20, 21) (default: current)
23
- --max-count, -n <i>: Limit the number of commits to output.
24
- --stop-at-latest-introduction-of-method, -s: Stop at lastest introduction of method.
25
- --help, -h: Show usage.
26
-
27
- # method-signature
28
- Uses the Ruby Index format e.g. Foo#bar, Bar::Baz#foo, Baz.foo.
29
-
30
- ### Todo
31
-
32
- * Support for Rspec tests
18
+ #### Display the commit history for a single method
19
+
20
+ $ method_log [options] <method-signature>
21
+
22
+ #### Build a parallel git repository of method definitions
23
+
24
+ $ build_methods_repo [options] <source-repo-path> <target-repo-path>
25
+
26
+ ### To Do
27
+
28
+ * Parsing support for RSpec tests
33
29
  * Default to looking for commits in current git branch
34
30
  * Check what happens with merge commits
35
31
  * Maybe add as new git command or extension to existing command e.g. `git log`
@@ -0,0 +1,80 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'method_log'
4
+ require 'optimist'
5
+
6
+ options = Optimist::options do
7
+ version MethodLog::VERSION
8
+ banner <<-EOS
9
+ Build a parallel git repository of method definitions.
10
+
11
+ Usage:
12
+ build_methods_repo [options] <source-repo-path> <target-repo-path>
13
+
14
+ source-repo-path: the path to the source repository from which to read
15
+ target-repo-path: the path to the target repository to which to write
16
+
17
+ [options] are:
18
+ EOS
19
+ opt :ruby_version, 'Parser Ruby version (e.g. 2.5)', default: 'current'
20
+ opt :excluded_directories, 'Directories in source repository to exclude from analysis', type: :strings, default: []
21
+ end
22
+
23
+ Optimist.die 'No source path specified' if ARGV[0].nil?
24
+ source_path = ARGV[0]
25
+ Optimist.die 'Source repository does not exist' unless Dir.exist?(source_path)
26
+
27
+ Optimist.die 'No target path specified' if ARGV[1].nil?
28
+ target_path = ARGV[1]
29
+ Optimist.die 'Target repository already exists' if Dir.exist?(target_path)
30
+
31
+ case ruby_version = options[:ruby_version]
32
+ when 'current'
33
+ require 'parser/current'
34
+ when /^(\d)\.(\d)$/
35
+ begin
36
+ require "parser/ruby#{$1}#{$2}"
37
+ Parser::CurrentRuby = Parser.const_get("Ruby#{$1}#{$2}")
38
+ rescue LoadError
39
+ Optimist.die "Ruby version not supported: #{ruby_version}"
40
+ end
41
+ else
42
+ Optimist.die "Ruby version not supported: #{ruby_version}"
43
+ end
44
+
45
+ require 'method_log/repository'
46
+ require 'method_log/method_finder'
47
+ require 'method_log/source_file'
48
+
49
+ def unindent(code)
50
+ lines = code.split($/)
51
+ indent = lines.reject { |l| l.strip.length == 0 }.map { |l| l[/^ */].length }.min
52
+ lines.map { |l| l.sub(Regexp.new(' ' * indent), '') }.join($/)
53
+ end
54
+
55
+ new_repository_path = File.expand_path(target_path)
56
+ Rugged::Repository.init_at(new_repository_path, :bare)
57
+ new_repository = MethodLog::Repository.new(new_repository_path)
58
+
59
+ repository_path = File.expand_path(source_path)
60
+ repository = MethodLog::Repository.new(repository_path)
61
+ repository.commits(sorting: Rugged::SORT_TOPO | Rugged::SORT_REVERSE).each do |commit|
62
+ puts commit.to_s
63
+ new_commit = new_repository.build_commit
64
+ commit.source_files.each do |source_file|
65
+ next if options[:excluded_directories].any? { |d| source_file.path.start_with?(d) }
66
+ begin
67
+ method_finder = MethodLog::MethodFinder.new(source_file)
68
+ method_finder.methods.each do |method_signature, method_definition|
69
+ _, namespace, name = method_signature.match(/^(.*)([#.].*)$/).to_a
70
+ path = namespace.split('::').push(name).join(File::SEPARATOR) + '.rb'
71
+ method_source = unindent(method_definition.source) + $/
72
+ method_source_file = MethodLog::SourceFile.new(path: path, source: method_source)
73
+ new_commit.add(method_source_file)
74
+ end
75
+ rescue Parser::SyntaxError => e
76
+ p e
77
+ end
78
+ end
79
+ new_commit.apply(user: commit.author, message: commit.message)
80
+ end
data/bin/method_log CHANGED
@@ -1,40 +1,51 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'method_log'
4
- require 'trollop'
4
+ require 'optimist'
5
5
 
6
- options = Trollop::options do
7
- opt :patch, 'Generate patch.', short: 'p'
8
- opt :ruby_version, 'Parser Ruby version (18, 19, 20, 21)', default: 'current'
6
+ options = Optimist::options do
7
+ version MethodLog::VERSION
8
+ banner <<-EOS
9
+ Display the commit history for a single method.
10
+
11
+ Usage:
12
+ method_log [options] <method-signature>
13
+
14
+ where <method-signature> is in the Ruby Index format e.g. Foo#bar, Bar::Baz#foo, Baz.foo.
15
+
16
+ and [options] are:
17
+ EOS
18
+ opt :patch, 'Generate patch.'
19
+ opt :ruby_version, 'Parser Ruby version (e.g. 2.5)', default: 'current'
9
20
  opt :max_count, 'Limit the number of commits to output.', type: :integer, short: 'n'
10
21
  opt :stop_at_latest_introduction_of_method, 'Stop at lastest introduction of method.', default: true
22
+ opt :repository_path, 'Path to repository', default: Dir.pwd
11
23
  end
12
24
 
25
+ Optimist.die 'No method signature specified' if ARGV.empty?
26
+ method_signature = ARGV[0]
27
+
13
28
  case ruby_version = options[:ruby_version]
14
29
  when 'current'
15
30
  require 'parser/current'
16
- when '18', '19', '20', '21'
17
- require 'parser/ruby18'
18
- require 'parser/ruby19'
19
- require 'parser/ruby20'
20
- require 'parser/ruby21'
21
- Parser::CurrentRuby = Parser.const_get("Ruby#{ruby_version}")
31
+ when /^(\d)\.(\d)$/
32
+ begin
33
+ require "parser/ruby#{$1}#{$2}"
34
+ Parser::CurrentRuby = Parser.const_get("Ruby#{$1}#{$2}")
35
+ rescue LoadError
36
+ Optimist.die "Ruby version not supported: #{ruby_version}"
37
+ end
22
38
  else
23
- raise "Ruby version not supported: #{ruby_version}"
39
+ Optimist.die "Ruby version not supported: #{ruby_version}"
24
40
  end
25
41
 
26
- require 'method_log'
27
42
  require 'method_log/repository'
28
43
  require 'method_log/api'
29
44
 
30
- repository = MethodLog::Repository.new(Dir.pwd)
45
+ repository = MethodLog::Repository.new(options[:repository_path])
31
46
  api = MethodLog::API.new(repository)
32
- api.diffs(ARGV[0], options).each do |method_commit, method_diff|
33
- puts "commit #{method_commit.sha}"
34
- puts "Author: #{method_commit.author[:name]} <#{method_commit.author[:email]}>"
35
- puts "Date: #{method_commit.author[:time].strftime('%a %b %-e %T %Y %z')}"
36
- puts
37
- puts method_commit.message
47
+ api.diffs(method_signature, options).each do |method_commit, method_diff|
48
+ puts method_commit.to_s
38
49
  puts
39
50
  if options[:patch]
40
51
  puts method_diff.to_s(:color)
@@ -39,6 +39,16 @@ module MethodLog
39
39
  method_definition && method_definition.source_file
40
40
  end
41
41
 
42
+ def to_s
43
+ [
44
+ "commit #{sha}",
45
+ "Author: #{author[:name]} <#{author[:email]}>",
46
+ "Date: #{author[:time].strftime('%a %b %-e %T %Y %z')}",
47
+ '',
48
+ message
49
+ ].join($/)
50
+ end
51
+
42
52
  protected
43
53
 
44
54
  attr_reader :commit
@@ -7,6 +7,8 @@ require 'method_log/scope'
7
7
 
8
8
  module MethodLog
9
9
  class MethodFinder < Parser::AST::Processor
10
+ attr_reader :methods
11
+
10
12
  def initialize(source_file)
11
13
  @source_file = source_file
12
14
  @scope = Scope::Root.new
@@ -25,9 +25,10 @@ module MethodLog
25
25
  end
26
26
 
27
27
  def commits(options = {})
28
+ options[:sorting] ||= Rugged::SORT_TOPO
28
29
  Enumerator.new do |yielder|
29
30
  if @repository.ref('refs/heads/master')
30
- @repository.walk(@repository.last_commit).with_index do |commit, index|
31
+ @repository.walk(@repository.last_commit, options[:sorting]).with_index do |commit, index|
31
32
  break if options[:max_count] && index >= options[:max_count] - 1
32
33
  yielder << build_commit(commit.oid)
33
34
  end
@@ -35,4 +36,4 @@ module MethodLog
35
36
  end
36
37
  end
37
38
  end
38
- end
39
+ end
@@ -1,3 +1,3 @@
1
1
  module MethodLog
2
- VERSION = '0.1.1'
2
+ VERSION = '0.2.0'
3
3
  end
data/method_log.gemspec CHANGED
@@ -18,13 +18,13 @@ Gem::Specification.new do |s|
18
18
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
19
  s.require_paths = ['lib']
20
20
 
21
- s.required_ruby_version = '>= 1.9.3'
21
+ s.required_ruby_version = '>= 2.0.0'
22
22
 
23
23
  s.add_dependency 'rugged'
24
- s.add_dependency 'parser'
24
+ s.add_dependency 'parser', '~> 2.5'
25
25
  s.add_dependency 'diffy'
26
- s.add_dependency 'trollop'
26
+ s.add_dependency 'optimist'
27
27
 
28
28
  s.add_development_dependency 'rake'
29
- s.add_development_dependency 'rspec'
29
+ s.add_development_dependency 'rspec', '~> 3.0'
30
30
  end
data/spec/api_spec.rb CHANGED
@@ -140,4 +140,4 @@ module MethodLog
140
140
  [method_commits, method_diffs]
141
141
  end
142
142
  end
143
- end
143
+ end
data/spec/commit_spec.rb CHANGED
@@ -66,8 +66,8 @@ module MethodLog
66
66
  repository = Repository.new(repository_path)
67
67
  commit = repository.commits.to_a.last
68
68
 
69
- expect(commit.contains?(source_file)).to be_true
70
- expect(commit.contains?(another_source_file)).to be_false
69
+ expect(commit.contains?(source_file)).to be true
70
+ expect(commit.contains?(another_source_file)).to be false
71
71
  end
72
72
 
73
73
  it 'makes author available' do
@@ -9,8 +9,8 @@ module MethodLog
9
9
  let(:diff) { MethodDiff.new(first_commit, second_commit) }
10
10
 
11
11
  it 'generates text diff of the method source for two commits' do
12
- first_commit.stub(:method_source).and_return(%{line 1\nline 2\n})
13
- second_commit.stub(:method_source).and_return(%{line 2\nline 3\n})
12
+ allow(first_commit).to receive(:method_source).and_return(%{line 1\nline 2\n})
13
+ allow(second_commit).to receive(:method_source).and_return(%{line 2\nline 3\n})
14
14
  expect(diff.to_s).to eq(%{-line 1\n line 2\n+line 3\n})
15
15
  end
16
16
  end
@@ -218,7 +218,7 @@ module MethodLog
218
218
  })
219
219
 
220
220
  method_finder = MethodFinder.new(foo)
221
- method_definition = method_finder.find('Foo::(ivar :@foo).bar')
221
+ method_definition = method_finder.find('Foo::s(:ivar, :@foo).bar')
222
222
 
223
223
  expect(method_definition).to eq(MethodDefinition.new(foo, 4..6))
224
224
  end
@@ -39,7 +39,7 @@ module MethodLog
39
39
  end
40
40
 
41
41
  it 'looks up source in repository using SHA if no source set' do
42
- repository.stub(:lookup).with(sha).and_return(blob)
42
+ allow(repository).to receive(:lookup).with(sha).and_return(blob)
43
43
  file = source(path: 'path/to/source.rb', repository: repository, sha: sha)
44
44
  expect(file.source).to eq('source')
45
45
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: method_log
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Mead
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-10 00:00:00.000000000 Z
11
+ date: 2019-06-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rugged
@@ -28,16 +28,16 @@ dependencies:
28
28
  name: parser
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: '2.5'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: '2.5'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: diffy
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: trollop
56
+ name: optimist
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -84,20 +84,21 @@ dependencies:
84
84
  name: rspec
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ">="
87
+ - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '0'
89
+ version: '3.0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ">="
94
+ - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '0'
96
+ version: '3.0'
97
97
  description:
98
98
  email:
99
99
  - james@floehopper.org
100
100
  executables:
101
+ - build_methods_repo
101
102
  - method_log
102
103
  extensions: []
103
104
  extra_rdoc_files: []
@@ -108,6 +109,7 @@ files:
108
109
  - LICENSE
109
110
  - README.md
110
111
  - Rakefile
112
+ - bin/build_methods_repo
111
113
  - bin/method_log
112
114
  - lib/method_log.rb
113
115
  - lib/method_log/api.rb
@@ -154,15 +156,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
154
156
  requirements:
155
157
  - - ">="
156
158
  - !ruby/object:Gem::Version
157
- version: 1.9.3
159
+ version: 2.0.0
158
160
  required_rubygems_version: !ruby/object:Gem::Requirement
159
161
  requirements:
160
162
  - - ">="
161
163
  - !ruby/object:Gem::Version
162
164
  version: '0'
163
165
  requirements: []
164
- rubyforge_project:
165
- rubygems_version: 2.2.0
166
+ rubygems_version: 3.0.3
166
167
  signing_key:
167
168
  specification_version: 4
168
169
  summary: Trace the history of an individual method in a git repository.