method_log 0.0.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.
Files changed (37) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/Gemfile +5 -0
  4. data/LICENSE +19 -0
  5. data/README.md +34 -0
  6. data/Rakefile +7 -0
  7. data/bin/method_log +13 -0
  8. data/lib/method_log/api.rb +20 -0
  9. data/lib/method_log/commit.rb +50 -0
  10. data/lib/method_log/method_commit.rb +25 -0
  11. data/lib/method_log/method_definition.rb +28 -0
  12. data/lib/method_log/method_finder.rb +51 -0
  13. data/lib/method_log/repository.rb +28 -0
  14. data/lib/method_log/source_file.rb +23 -0
  15. data/lib/method_log/version.rb +3 -0
  16. data/lib/method_log.rb +2 -0
  17. data/method_log.gemspec +25 -0
  18. data/samples/repository.git/HEAD +1 -0
  19. data/samples/repository.git/config +5 -0
  20. data/samples/repository.git/description +1 -0
  21. data/samples/repository.git/hooks/README.sample +5 -0
  22. data/samples/repository.git/info/exclude +2 -0
  23. data/samples/repository.git/objects/45/0ab23bfa0bd482244c42c7e18fad84526258fc +0 -0
  24. data/samples/repository.git/objects/4c/5ba880d306780e033a5c35d3805b5f6f76aa41 +1 -0
  25. data/samples/repository.git/objects/b0/3eef6ca386d8463c28dd26f52333aba9af05dc +5 -0
  26. data/samples/repository.git/objects/e0/ec752ebc5a724d5c2880dce3126948555b9709 +0 -0
  27. data/samples/repository.git/objects/ef/ebdb1a26d03939042f2f9c09f2aa49d87d1169 +2 -0
  28. data/samples/repository.git/objects/f6/6529c35058f591594fdc9affad66ebd6a16d0f +1 -0
  29. data/samples/repository.git/refs/heads/master +1 -0
  30. data/spec/api_spec.rb +62 -0
  31. data/spec/commit_spec.rb +45 -0
  32. data/spec/method_commit_spec.rb +24 -0
  33. data/spec/method_definition_spec.rb +39 -0
  34. data/spec/method_finder_spec.rb +53 -0
  35. data/spec/source_file_spec.rb +35 -0
  36. data/spec/spec_helper.rb +1 -0
  37. metadata +129 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6a64a5c77324253051cdea911808a4d26fbcf07a
4
+ data.tar.gz: 8cf7ac058dea844d6ffbcfff7e87ce7d64bd91bf
5
+ SHA512:
6
+ metadata.gz: c1a4955bc308e0e733e3f156f44ba796a2ce639660f4988a87949ef7ab6ef85b0dd1975f540c96386cac17ff72ef912700da0d2f3477d863ff5eb6b3b2f428ea
7
+ data.tar.gz: 7176a109612715acd7b7e57f35800bb2c4c533ccf82b56ccd40dd305f67b0cc9a0f1d96cafa7233bcf24c1f9ae7e168031dd730c5b9e29e4e4b1367a6d85aa7e
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ ruby '2.1.0'
4
+
5
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (C) 2014 by James Mead
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,34 @@
1
+ ## Method Log
2
+
3
+ Trace the history of an individual method in a git repository.
4
+
5
+ ### Install
6
+
7
+ gem install method_log
8
+
9
+ ### Run
10
+
11
+ method_log <method-signature> # e.g. Foo::Bar#baz
12
+
13
+ ### Todo
14
+
15
+ * Support earlier versions of Ruby
16
+ * Support class methods
17
+ * Support namespaced classes e.g. `class Foo::Bar`
18
+ * Support for Rspec tests
19
+ * Display diffs in method implementation between commits
20
+ * Only display diffs when method implementation has changed
21
+ * Default to looking for git repo in current working directory
22
+ * Default to looking for commits in current git branch
23
+ * Maybe add as new git command or extension to existing command e.g. `git log`
24
+ * Optimise search for method definitions:
25
+ * First look in file where method was last defined
26
+ * Simple text search for files containing method name to narrow files that need to be parsed
27
+
28
+ ### Credits
29
+
30
+ Written by [James Mead](http://jamesmead.org) and the other members of [Go Free Range](http://gofreerange.com).
31
+
32
+ ### License
33
+
34
+ Released under the [MIT License](https://github.com/freerange/method_log/blob/master/LICENSE).
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require 'bundler/setup'
2
+ require 'bundler/gem_tasks'
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
data/bin/method_log ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'method_log'
5
+ require 'method_log/repository'
6
+ require 'method_log/api'
7
+
8
+ repository = MethodLog::Repository.new(path: ARGV[0])
9
+ api = MethodLog::API.new(repository: repository)
10
+ method_commits = api.history(ARGV[1])
11
+ method_commits.each do |method_commit|
12
+ puts method_commit
13
+ end
@@ -0,0 +1,20 @@
1
+ require 'method_log/method_finder'
2
+ require 'method_log/method_commit'
3
+
4
+ module MethodLog
5
+ class API
6
+ def initialize(repository:)
7
+ @repository = repository
8
+ end
9
+
10
+ def history(method_identifier)
11
+ @repository.commits.map do |commit|
12
+ method_definitions = commit.source_files.inject([]) do |definitions, source_file|
13
+ method_finder = MethodFinder.new(source_file: source_file)
14
+ definitions += Array(method_finder.find(method_identifier))
15
+ end
16
+ MethodCommit.new(commit: commit, method_definition: method_definitions.first)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,50 @@
1
+ require 'rugged'
2
+
3
+ require 'method_log/source_file'
4
+
5
+ module MethodLog
6
+ class Commit
7
+ attr_reader :sha
8
+
9
+ def initialize(repository: repository, sha: sha)
10
+ @repository = repository
11
+ @sha = sha
12
+ @index = Rugged::Index.new
13
+ end
14
+
15
+ def add(source_file)
16
+ oid = @repository.write(source_file.source, :blob)
17
+ @index.add(path: source_file.path, oid: oid, mode: 0100644)
18
+ end
19
+
20
+ def apply
21
+ tree = @index.write_tree(@repository)
22
+ parents = @repository.empty? ? [] : [@repository.head.target].compact
23
+ user = { email: 'test@example.com', name: 'test', time: Time.now }
24
+ @sha = Rugged::Commit.create(@repository, tree: tree, parents: parents, update_ref: 'HEAD', author: user, committer: user, message: 'commit-message')
25
+ end
26
+
27
+ def source_files
28
+ commit = @repository.lookup(sha)
29
+ source_files = []
30
+ commit.tree.walk_blobs do |root, blob_hash|
31
+ path = root.empty? ? blob_hash[:name] : File.join(root, blob_hash[:name])
32
+ source = @repository.lookup(blob_hash[:oid]).text
33
+ source_files << SourceFile.new(path: path, source: source)
34
+ end
35
+ source_files
36
+ end
37
+
38
+ def ==(other)
39
+ sha == other.sha
40
+ end
41
+
42
+ def hash
43
+ sha.hash
44
+ end
45
+
46
+ def to_s
47
+ sha
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,25 @@
1
+ module MethodLog
2
+ class MethodCommit
3
+ def initialize(commit:, method_definition:)
4
+ @commit = commit
5
+ @method_definition = method_definition
6
+ end
7
+
8
+ def ==(other)
9
+ (commit == other.commit) && (method_definition == other.method_definition)
10
+ end
11
+
12
+ def hash
13
+ [commit, method_definition].hash
14
+ end
15
+
16
+ def to_s
17
+ "#{commit}: #{method_definition}"
18
+ end
19
+
20
+ protected
21
+
22
+ attr_reader :commit
23
+ attr_reader :method_definition
24
+ end
25
+ end
@@ -0,0 +1,28 @@
1
+ module MethodLog
2
+ class MethodDefinition
3
+ def initialize(source_file:, lines:)
4
+ @source_file = source_file
5
+ @lines = lines
6
+ end
7
+
8
+ def ==(other)
9
+ (source_file == other.source_file) && (lines == other.lines)
10
+ end
11
+
12
+ def hash
13
+ [source_file, lines].hash
14
+ end
15
+
16
+ def to_s
17
+ [
18
+ "#{source_file.path}:#{lines}",
19
+ source_file.snippet(lines)
20
+ ].join($/)
21
+ end
22
+
23
+ protected
24
+
25
+ attr_reader :source_file
26
+ attr_reader :lines
27
+ end
28
+ end
@@ -0,0 +1,51 @@
1
+ require 'ripper'
2
+
3
+ require 'method_log/method_definition'
4
+
5
+ module MethodLog
6
+ class MethodFinder < Ripper
7
+ def initialize(source_file:)
8
+ super(source_file.source)
9
+ @source_file = source_file
10
+ @namespaces = []
11
+ @methods = {}
12
+ @at_scope_start = false
13
+ parse
14
+ end
15
+
16
+ def find(method_identifier)
17
+ @methods[method_identifier]
18
+ end
19
+
20
+ def on_kw(name)
21
+ case name
22
+ when 'def'
23
+ @line_number = lineno
24
+ when 'class', 'module'
25
+ @at_scope_start = true
26
+ end
27
+ end
28
+
29
+ def on_const(name)
30
+ if @at_scope_start
31
+ @namespaces << name
32
+ @at_scope_start = false
33
+ end
34
+ end
35
+
36
+ def on_def(name, *args)
37
+ identifier = "#{@namespaces.join('::')}##{name}"
38
+ lines = (@line_number - 1)..(lineno - 1)
39
+ definition = MethodDefinition.new(source_file: @source_file, lines: lines)
40
+ @methods[identifier] = definition
41
+ end
42
+
43
+ def on_class(*args)
44
+ @namespaces.pop
45
+ end
46
+
47
+ def on_module(*args)
48
+ @namespaces.pop
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,28 @@
1
+ require 'rugged'
2
+
3
+ require 'method_log/commit'
4
+
5
+ module MethodLog
6
+ class Repository
7
+ attr_reader :commits
8
+
9
+ def initialize(path:)
10
+ @repository = Rugged::Repository.new(path)
11
+ @commits = []
12
+ if @repository.ref('refs/heads/master')
13
+ @repository.walk(@repository.last_commit) do |commit|
14
+ @commits << build_commit(sha: commit.oid)
15
+ end
16
+ end
17
+ end
18
+
19
+ def build_commit(sha: nil)
20
+ Commit.new(repository: @repository, sha: sha)
21
+ end
22
+
23
+ def add(commit)
24
+ commit.apply
25
+ @commits << commit
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,23 @@
1
+ module MethodLog
2
+ class SourceFile
3
+ attr_reader :path
4
+ attr_reader :source
5
+
6
+ def initialize(path:, source:)
7
+ @path = path
8
+ @source = source
9
+ end
10
+
11
+ def ==(other)
12
+ (path == other.path) && (source == other.source)
13
+ end
14
+
15
+ def hash
16
+ [path, source].hash
17
+ end
18
+
19
+ def snippet(range)
20
+ lines = source.split($/)[range].join($/)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,3 @@
1
+ module MethodLog
2
+ VERSION = '0.0.1'
3
+ end
data/lib/method_log.rb ADDED
@@ -0,0 +1,2 @@
1
+ module MethodLog
2
+ end
@@ -0,0 +1,25 @@
1
+ lib = File.expand_path('../lib/', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+
4
+ require 'method_log/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = 'method_log'
8
+ s.version = MethodLog::VERSION
9
+ s.platform = Gem::Platform::RUBY
10
+ s.authors = ['James Mead']
11
+ s.email = ['james@floehopper.org']
12
+ s.homepage = 'http://jamesmead.org'
13
+ s.summary = 'Trace the history of an individual method in a git repository.'
14
+ s.license = 'MIT'
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- spec/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ['lib']
20
+
21
+ s.add_dependency 'rugged'
22
+
23
+ s.add_development_dependency 'rake'
24
+ s.add_development_dependency 'rspec'
25
+ end
@@ -0,0 +1 @@
1
+ ref: refs/heads/master
@@ -0,0 +1,5 @@
1
+ [core]
2
+ bare = true
3
+ repositoryformatversion = 0
4
+ filemode = true
5
+ ignorecase = true
@@ -0,0 +1 @@
1
+ Unnamed repository; edit this file 'description' to name the repository.
@@ -0,0 +1,5 @@
1
+ #!/bin/sh
2
+ #
3
+ # Place appropriately named executable hook scripts into this directory
4
+ # to intercept various actions that git takes. See `git help hooks` for
5
+ # more information.
@@ -0,0 +1,2 @@
1
+ # File patterns to ignore; see `git help ignore` for more information.
2
+ # Lines that start with '#' are comments.
@@ -0,0 +1 @@
1
+ x�� �0�N iB���;��b��o�0 �U�bݖ ��aܯ ���%�#���-�a�H�jyb����2oC�S�&T�
@@ -0,0 +1,5 @@
1
+ x��A
2
+ 1 E]�)���&L`��DKe��[� �o���s���)l|U#��gC��G+��L
3
+ �^
4
+ I�l����
5
+ ��a��o�χ�s�'��#�`ƦaǑ�ɯ�U�]����4�
@@ -0,0 +1,2 @@
1
+ x��A
2
+ �0E]�ً��$qE��d2Q���F��F���_�ǃ/s��f�Ү���y� 0�);pN�IG*��y�Ȱ��f�E���B�(g�"r����,��m^Mӭ���}s]z���͈q�!zB��=C_���(?�Pu���1�B{
@@ -0,0 +1 @@
1
+ x+)JMU06a040031QH���+Jbx�ToOT�o�F�B����9#��
@@ -0,0 +1 @@
1
+ efebdb1a26d03939042f2f9c09f2aa49d87d1169
data/spec/api_spec.rb ADDED
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+
3
+ require 'method_log/api'
4
+ require 'method_log/source_file'
5
+ require 'method_log/repository'
6
+ require 'method_log/commit'
7
+ require 'method_log/method_definition'
8
+ require 'method_log/method_commit'
9
+
10
+ describe MethodLog::API do
11
+ let(:repository_path) { File.expand_path('../repository.git', __FILE__) }
12
+
13
+ before do
14
+ FileUtils.mkdir_p(repository_path)
15
+ Rugged::Repository.init_at(repository_path, :bare)
16
+ end
17
+
18
+ after do
19
+ FileUtils.rm_rf(repository_path)
20
+ end
21
+
22
+ it 'finds class instance method in repository with two commits with single source file' do
23
+ foo_1 = MethodLog::SourceFile.new(path: 'foo.rb', source: %{
24
+ class Foo
25
+ def bar
26
+ # implementation
27
+ end
28
+ end
29
+ }.strip)
30
+
31
+ foo_2 = MethodLog::SourceFile.new(path: 'foo.rb', source: %{
32
+ # move method definition down one line
33
+ class Foo
34
+ def bar
35
+ # implementation
36
+ end
37
+ end
38
+ }.strip)
39
+
40
+ repository = MethodLog::Repository.new(path: repository_path)
41
+
42
+ commit_1 = repository.build_commit
43
+ commit_1.add(foo_1)
44
+ repository.add(commit_1)
45
+
46
+ commit_2 = repository.build_commit
47
+ commit_2.add(foo_2)
48
+ repository.add(commit_2)
49
+
50
+ repository = MethodLog::Repository.new(path: repository_path)
51
+ api = MethodLog::API.new(repository: repository)
52
+ method_commits = api.history('Foo#bar')
53
+
54
+ method_definition_1 = MethodLog::MethodDefinition.new(source_file: foo_1, lines: 1..3)
55
+ method_definition_2 = MethodLog::MethodDefinition.new(source_file: foo_2, lines: 2..4)
56
+
57
+ method_commit_1 = MethodLog::MethodCommit.new(commit: commit_1, method_definition: method_definition_1)
58
+ method_commit_2 = MethodLog::MethodCommit.new(commit: commit_2, method_definition: method_definition_2)
59
+
60
+ expect(method_commits).to eq([method_commit_2, method_commit_1])
61
+ end
62
+ end
@@ -0,0 +1,45 @@
1
+ require 'method_log/repository'
2
+ require 'method_log/commit'
3
+ require 'method_log/source_file'
4
+
5
+ describe MethodLog::Commit do
6
+ let(:sha) { 'b54d38bbd989f4b54c38fd77767d89d1' }
7
+ let(:commit) { MethodLog::Commit.new(sha: sha) }
8
+ let(:commit_with_same_sha) { MethodLog::Commit.new(sha: sha) }
9
+
10
+ it 'is equal to another commit with same SHA' do
11
+ expect(commit).to eq(commit_with_same_sha)
12
+ end
13
+
14
+ it 'has same hash as another commit with same SHA' do
15
+ expect(commit.hash).to eq(commit_with_same_sha.hash)
16
+ end
17
+
18
+ context 'using a real git repository' do
19
+ let(:repository_path) { File.expand_path('../repository.git', __FILE__) }
20
+
21
+ before do
22
+ FileUtils.mkdir_p(repository_path)
23
+ Rugged::Repository.init_at(repository_path, :bare)
24
+ end
25
+
26
+ after do
27
+ FileUtils.rm_rf(repository_path)
28
+ end
29
+
30
+ it 'stores source files added to a commit in the repository against a real commit' do
31
+ source_one = MethodLog::SourceFile.new(path: 'path/to/source_one.rb', source: 'source-one')
32
+ source_two = MethodLog::SourceFile.new(path: 'path/to/source_two.rb', source: 'source-two')
33
+
34
+ repository = MethodLog::Repository.new(path: repository_path)
35
+ commit = repository.build_commit
36
+ commit.add(source_one)
37
+ commit.add(source_two)
38
+ commit.apply
39
+
40
+ repository = MethodLog::Repository.new(path: repository_path)
41
+ commit = repository.commits.first
42
+ expect(commit.source_files).to eq([source_one, source_two])
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,24 @@
1
+ require 'method_log/method_commit'
2
+ require 'method_log/commit'
3
+ require 'method_log/source_file'
4
+ require 'method_log/method_definition'
5
+
6
+ describe MethodLog::MethodCommit do
7
+ let(:commit) { MethodLog::Commit.new }
8
+ let(:source_file) { MethodLog::SourceFile.new(path: '/path/to/source.rb', source: 'source') }
9
+ let(:method_definition) { MethodLog::MethodDefinition.new(source_file: source_file, lines: 5..7) }
10
+ let(:method_commit) {
11
+ MethodLog::MethodCommit.new(commit: commit, method_definition: method_definition)
12
+ }
13
+ let(:method_commit_with_same_commit_and_method_definition) {
14
+ MethodLog::MethodCommit.new(commit: commit, method_definition: method_definition)
15
+ }
16
+
17
+ it 'is equal to another method commit with same commit and method definition' do
18
+ expect(method_commit).to eq(method_commit_with_same_commit_and_method_definition)
19
+ end
20
+
21
+ it 'has same hash as another method commit with same commit and method definition' do
22
+ expect(method_commit.hash).to eq(method_commit_with_same_commit_and_method_definition.hash)
23
+ end
24
+ end
@@ -0,0 +1,39 @@
1
+ require 'method_log/method_definition'
2
+ require 'method_log/source_file'
3
+
4
+ describe MethodLog::MethodDefinition do
5
+ let(:source_file) do
6
+ MethodLog::SourceFile.new(path: 'path/to/source.rb', source: %{
7
+ class Foo
8
+ def bar
9
+ # implementation
10
+ end
11
+ end
12
+ }.strip)
13
+ end
14
+
15
+ it 'is equal to another method definition with same source file and line numbers' do
16
+ definition_one = MethodLog::MethodDefinition.new(source_file: source_file, lines: 1..3)
17
+ definition_two = MethodLog::MethodDefinition.new(source_file: source_file, lines: 1..3)
18
+
19
+ expect(definition_one).to eq(definition_two)
20
+ end
21
+
22
+ it 'has same hash as another method definition with same path and line numbers' do
23
+ definition_one = MethodLog::MethodDefinition.new(source_file: source_file, lines: 1..3)
24
+ definition_two = MethodLog::MethodDefinition.new(source_file: source_file, lines: 1..3)
25
+
26
+ expect(definition_one.hash).to eq(definition_two.hash)
27
+ end
28
+
29
+ it 'describes method definition' do
30
+ definition = MethodLog::MethodDefinition.new(source_file: source_file, lines: 1..3)
31
+
32
+ expect(definition.to_s).to eq(%{
33
+ path/to/source.rb:1..3
34
+ def bar
35
+ # implementation
36
+ end
37
+ }.strip)
38
+ end
39
+ end
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+
3
+ require 'method_log/source_file'
4
+ require 'method_log/method_finder'
5
+
6
+ describe MethodLog::MethodFinder do
7
+ it 'finds definition of instance method on class' do
8
+ foo = MethodLog::SourceFile.new(path: 'foo.rb', source: %{
9
+ class Foo
10
+ def bar
11
+ # implementation
12
+ end
13
+ end
14
+ }.strip)
15
+
16
+ method_finder = MethodLog::MethodFinder.new(source_file: foo)
17
+ method_definition = method_finder.find('Foo#bar')
18
+
19
+ expect(method_definition).to eq(MethodLog::MethodDefinition.new(source_file: foo, lines: 1..3))
20
+ end
21
+
22
+ it 'finds definition of instance method on module' do
23
+ foo = MethodLog::SourceFile.new(path: 'foo.rb', source: %{
24
+ module Foo
25
+ def bar
26
+ # implementation
27
+ end
28
+ end
29
+ }.strip)
30
+
31
+ method_finder = MethodLog::MethodFinder.new(source_file: foo)
32
+ method_definition = method_finder.find('Foo#bar')
33
+
34
+ expect(method_definition).to eq(MethodLog::MethodDefinition.new(source_file: foo, lines: 1..3))
35
+ end
36
+
37
+ it 'finds definition of instance method on class within module' do
38
+ foo = MethodLog::SourceFile.new(path: 'foo.rb', source: %{
39
+ module Foo
40
+ class Bar
41
+ def baz
42
+ # implementation
43
+ end
44
+ end
45
+ end
46
+ }.strip)
47
+
48
+ method_finder = MethodLog::MethodFinder.new(source_file: foo)
49
+ method_definition = method_finder.find('Foo::Bar#baz')
50
+
51
+ expect(method_definition).to eq(MethodLog::MethodDefinition.new(source_file: foo, lines: 2..4))
52
+ end
53
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ require 'method_log/source_file'
4
+
5
+ describe MethodLog::SourceFile do
6
+ it 'is equal to another source file with same path and source' do
7
+ file_one = MethodLog::SourceFile.new(path: 'path/to/source.rb', source: 'source-one')
8
+ file_two = MethodLog::SourceFile.new(path: 'path/to/source.rb', source: 'source-one')
9
+
10
+ expect(file_one).to eq(file_two)
11
+ end
12
+
13
+ it 'has same hash as another source file with same path and source' do
14
+ file_one = MethodLog::SourceFile.new(path: 'path/to/source.rb', source: 'source-one')
15
+ file_two = MethodLog::SourceFile.new(path: 'path/to/source.rb', source: 'source-one')
16
+
17
+ expect(file_one.hash).to eq(file_two.hash)
18
+ end
19
+
20
+ it 'describes source file' do
21
+ file = MethodLog::SourceFile.new(path: 'path/to/source.rb', source: %{
22
+ class Foo
23
+ def bar
24
+ # implementation
25
+ end
26
+ end
27
+ }.strip)
28
+
29
+ expect(file.snippet(1..3).strip).to eq(%{
30
+ def bar
31
+ # implementation
32
+ end
33
+ }.strip)
34
+ end
35
+ end
@@ -0,0 +1 @@
1
+ $LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__))
metadata ADDED
@@ -0,0 +1,129 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: method_log
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - James Mead
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-02-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rugged
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description:
56
+ email:
57
+ - james@floehopper.org
58
+ executables:
59
+ - method_log
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - ".gitignore"
64
+ - Gemfile
65
+ - LICENSE
66
+ - README.md
67
+ - Rakefile
68
+ - bin/method_log
69
+ - lib/method_log.rb
70
+ - lib/method_log/api.rb
71
+ - lib/method_log/commit.rb
72
+ - lib/method_log/method_commit.rb
73
+ - lib/method_log/method_definition.rb
74
+ - lib/method_log/method_finder.rb
75
+ - lib/method_log/repository.rb
76
+ - lib/method_log/source_file.rb
77
+ - lib/method_log/version.rb
78
+ - method_log.gemspec
79
+ - samples/repository.git/HEAD
80
+ - samples/repository.git/config
81
+ - samples/repository.git/description
82
+ - samples/repository.git/hooks/README.sample
83
+ - samples/repository.git/info/exclude
84
+ - samples/repository.git/objects/45/0ab23bfa0bd482244c42c7e18fad84526258fc
85
+ - samples/repository.git/objects/4c/5ba880d306780e033a5c35d3805b5f6f76aa41
86
+ - samples/repository.git/objects/b0/3eef6ca386d8463c28dd26f52333aba9af05dc
87
+ - samples/repository.git/objects/e0/ec752ebc5a724d5c2880dce3126948555b9709
88
+ - samples/repository.git/objects/ef/ebdb1a26d03939042f2f9c09f2aa49d87d1169
89
+ - samples/repository.git/objects/f6/6529c35058f591594fdc9affad66ebd6a16d0f
90
+ - samples/repository.git/refs/heads/master
91
+ - spec/api_spec.rb
92
+ - spec/commit_spec.rb
93
+ - spec/method_commit_spec.rb
94
+ - spec/method_definition_spec.rb
95
+ - spec/method_finder_spec.rb
96
+ - spec/source_file_spec.rb
97
+ - spec/spec_helper.rb
98
+ homepage: http://jamesmead.org
99
+ licenses:
100
+ - MIT
101
+ metadata: {}
102
+ post_install_message:
103
+ rdoc_options: []
104
+ require_paths:
105
+ - lib
106
+ required_ruby_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ required_rubygems_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ requirements: []
117
+ rubyforge_project:
118
+ rubygems_version: 2.2.0
119
+ signing_key:
120
+ specification_version: 4
121
+ summary: Trace the history of an individual method in a git repository.
122
+ test_files:
123
+ - spec/api_spec.rb
124
+ - spec/commit_spec.rb
125
+ - spec/method_commit_spec.rb
126
+ - spec/method_definition_spec.rb
127
+ - spec/method_finder_spec.rb
128
+ - spec/source_file_spec.rb
129
+ - spec/spec_helper.rb