ruby_diff 0.1 → 0.1.5

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.
data/.gitignore CHANGED
@@ -2,5 +2,7 @@
2
2
  *~
3
3
  # Ignore rubygems pkg dir
4
4
  /pkg
5
+ # Ignore rubygems docs dir
6
+ /doc
5
7
  # Ignore MacOSX .DS_Store
6
- .DS_Store
8
+ .DS_Store
data/History.txt CHANGED
@@ -1,2 +1,9 @@
1
- === 0.0.1 / 2008-06-03
2
- Initial verison of RubyDiff
1
+ === 0.1.5 / --
2
+ Making everything a little better:
3
+ - Merged changes from kballard to fix the git feeder
4
+ - Added support for git working directory (use --git-wd)
5
+ - Added support for multiple inputs
6
+ - Metamethods such as 'attr_reader' are now processed
7
+
8
+ === 0.1 / 2008-06-03
9
+ Initial verison of RubyDiff
data/Manifest.txt CHANGED
@@ -8,12 +8,16 @@ lib/ruby_diff.rb
8
8
  lib/ruby_diff/code_comparison.rb
9
9
  lib/ruby_diff/file_feeder.rb
10
10
  lib/ruby_diff/git_feeder.rb
11
+ lib/ruby_diff/git_support.rb
12
+ lib/ruby_diff/git_working_dir_feeder.rb
11
13
  lib/ruby_diff/patterns.rb
12
14
  lib/ruby_diff/structure_processor.rb
13
15
  ruby_diff.gemspec
16
+ test/code_comparison_test.rb
14
17
  test/file_feeder_test.rb
15
18
  test/git_feeder_test.rb
16
19
  test/git_sample/README
17
20
  test/git_sample/book.rb
18
21
  test/git_sample/lib/chapter.rb
22
+ test/git_working_dir_feeder_test.rb
19
23
  test/structure_processor_test.rb
data/README.txt CHANGED
@@ -27,9 +27,13 @@ changes to instance methods. The API is likely to change drastically.
27
27
  == Usage
28
28
  This is likely to change a bunch, but for the moment:
29
29
  ruby_diff old_file new_file
30
+
30
31
  Or for git repositories, etc.
31
- ruby_diff --git HEAD --file ./
32
-
32
+ ruby_diff --git HEAD --git-wd
33
+
34
+ Compare three different release tags.
35
+ ruby_diff --git v0.1 --git v0.2 --git v0.3
36
+
33
37
  See help for more information.
34
38
 
35
39
  == Contact
data/Rakefile CHANGED
@@ -24,7 +24,7 @@ namespace :git do
24
24
  task :changed do |t|
25
25
  _divider
26
26
  puts "Changes since last commit:"
27
- puts `./bin/ruby_diff --git HEAD --file ./`
27
+ puts `./bin/ruby_diff --git HEAD --git-wd ./`
28
28
  _divider
29
29
  end
30
30
 
data/bin/ruby_diff CHANGED
@@ -1,13 +1,26 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'rubygems'
3
- require 'ruby_diff'
4
- require 'optparse'
3
+ require 'optparse'
4
+ require 'enumerator'
5
+
6
+ # If we're loading ruby_diff directly for development,
7
+ # don't require it through rubygems. Is there a better
8
+ # way to do this?
9
+
10
+ if $0 == __FILE__
11
+ # loaded directly (dev)
12
+ require File.dirname(__FILE__)+"/../lib/ruby_diff"
13
+ else
14
+ # loaded via ruby_gems
15
+ require 'ruby_diff'
16
+ end
5
17
 
6
18
  @options = {}
7
19
 
8
20
  feeder_mapping = {
9
21
  :file => FileFeeder,
10
- :git => GitFeeder
22
+ :git => GitFeeder,
23
+ :git_wd => GitWorkingDirFeeder,
11
24
  }
12
25
 
13
26
  feeders = []
@@ -21,25 +34,35 @@ opts.separator "Specific options:"
21
34
  opts.define_head <<-HEAD
22
35
 
23
36
  Examples:
24
- Changes between git HEAD and current file system:
25
- ruby_diff --git HEAD --file ./
37
+ Changes between git HEAD and current working directory:
38
+ ruby_diff --git HEAD --git-wd ./
39
+
40
+ Changes between two sets of files:
41
+ ruby_diff --file old_dir --file new_dir
26
42
 
27
- Changes between HEAD and previous revision:
28
- ruby_diff --git HEAD~1 --git HEAD
29
43
  HEAD
30
44
 
31
- opts.on('--sexp', "Show the s expressions for each input"){
45
+ opts.on('--sexp', "Show the s expressions for each input (mostly for debugging)"){
32
46
  @options[:sexp] = true
33
47
  }
34
48
 
49
+ opts.on('--verbose', "Shows more information while processing files"){
50
+ @options[:verbose] = true
51
+ }
52
+
35
53
  opts.on('--git PATH', "Use a git repository as a code source"){|path|
36
54
  feeders << feeder_mapping[:git].new(path)
37
55
  }
56
+
57
+ opts.on('--git-wd PATH', "Use the git working directory as a code source"){|path|
58
+ feeders << feeder_mapping[:git_wd].new(path)
59
+ }
60
+
38
61
  opts.on('--file PATH', "Use a file system path as a code source"){|path|
39
62
  feeders << feeder_mapping[:file].new(path)
40
63
  }
41
64
 
42
- opts.on_tail('-v', '--version') { puts "ruby_diff v:0" ; exit }
65
+ opts.on_tail('-v', '--version') { puts "ruby_diff #{RubyDiff::VERSION}" ; exit }
43
66
  opts.on_tail('-h', '--help') { puts opts; exit }
44
67
 
45
68
  opts.parse!(ARGV)
@@ -49,36 +72,42 @@ ARGV.each do |path|
49
72
  feeders << feeder_mapping[:file].new(path)
50
73
  end
51
74
 
52
- if feeders.length > 2
75
+ if feeders.length < 2
53
76
  puts opts
54
- puts "Too many code sources (#{feeders.length})"
55
- exit 1
56
- elsif feeders.length < 2
57
- puts opts
58
- puts "Must supply least 2 code sources (#{feeders.length})"
77
+ puts "Must supply at least 2 code sources (found #{feeders.length})"
59
78
  exit 1
60
79
  end
61
80
 
62
81
  processors = feeders.map do |feeder|
63
82
  puts "#{feeder.class}: #{feeder.path}" if @options[:sexp]
64
- processor = StructureProcessor.new
65
- feeder.each do |code|
66
- sexp = ParseTree.new.parse_tree_for_string(code)
67
- if @options[:sexp]
68
- pp sexp
69
- puts "--"
70
- end
83
+ processor = StructureProcessor.new(feeder.path)
84
+ puts "\n#{feeder.path}" if @options[:verbose]
85
+
86
+ feeder.each do |code, path|
87
+ puts path if @options[:verbose]
88
+ begin
89
+ sexp = ParseTree.new.parse_tree_for_string(code,path)
90
+ if @options[:sexp]
91
+ pp sexp
92
+ puts "--"
93
+ end
71
94
 
72
- processor.process(*sexp)
95
+ processor.process(*sexp) unless sexp.empty?
96
+ rescue Exception => ex
97
+ STDERR << "Could not parse input (#{path}):\n#{ex}"
98
+ end
73
99
  end
74
100
 
75
101
  processor
76
102
  end
77
103
 
78
-
79
- old_processor, new_processor = *processors
80
104
 
81
- changes = old_processor.diff(new_processor).sort_by{|c| c.signature}
82
- changes.each do |change|
83
- puts change.to_s
105
+ processors.each_cons(2) do |old_processor, new_processor|
106
+ if processors.length > 2 or @options[:verbose]
107
+ puts "# #{old_processor.name} to #{new_processor.name}"
108
+ end
109
+ changes = old_processor.diff(new_processor).sort_by{|c| c.signature}
110
+ changes.each do |change|
111
+ puts change.to_s
112
+ end
84
113
  end
data/lib/ruby_diff.rb CHANGED
@@ -11,10 +11,10 @@ require 'set'
11
11
  require 'pp'
12
12
 
13
13
  module RubyDiff
14
- VERSION = "0.1"
14
+ VERSION = "0.1.5"
15
15
  end
16
16
 
17
17
  # RubyDiff
18
- %w(code_comparison structure_processor file_feeder git_feeder).each do |name|
18
+ %w(code_comparison structure_processor file_feeder git_support git_feeder git_working_dir_feeder).each do |name|
19
19
  require File.expand_path(File.dirname(__FILE__) + "/ruby_diff/#{name}")
20
20
  end
@@ -1,3 +1,5 @@
1
+ # A CodeChange represents a difference between two sets of ruby
2
+ # code. It may contain child changes.
1
3
  class CodeChange
2
4
  attr_reader :signature
3
5
  attr_reader :operation
@@ -23,12 +25,15 @@ class CodeChange
23
25
  end
24
26
  end
25
27
 
28
+ # Compares two sets of parsed CodeObjects. A CodeComparison
29
+ # Expects sets of CodeObjects hashed by their signature.
26
30
  class CodeComparison
27
31
  def initialize(old_signatures, new_signatures)
28
32
  @old = old_signatures
29
33
  @new = new_signatures
30
34
  end
31
35
 
36
+ # Returns the set of changes.
32
37
  def changes
33
38
  changes = []
34
39
  seen = Set.new
@@ -1,3 +1,9 @@
1
+ # A Feeder reads in files for RubyDiff's processor to
2
+ # run over. FileFeeder reads them from the file system.
3
+ #
4
+ # Example Usage:
5
+ # ruby_diff --file old_version.rb --file new_version.rb
6
+ # ruby_diff --file old_dir/ --file new_dir
1
7
  class FileFeeder
2
8
  attr_accessor :files
3
9
  attr_accessor :path
@@ -21,7 +27,7 @@ class FileFeeder
21
27
 
22
28
  def each
23
29
  @files.each do |file|
24
- yield(open(file, 'r'){|io| io.read})
30
+ yield(open(file, 'r'){|io| io.read}, file)
25
31
  end
26
32
  end
27
33
 
@@ -1,9 +1,17 @@
1
- GitFile = Struct.new :access, :type, :hash, :name
1
+ # A Feeder reads in files for RubyDiff's processor to
2
+ # run over. GitFeeder reads them from a git repository.
3
+ #
4
+ # Example Usage:
5
+ # ruby_diff --git v0.1:lib --git v0.1:lib
6
+ # ruby_diff --git HEAD^2 --git HEAD^1 --git HEAD
2
7
  class GitFeeder
8
+ GitFile = Struct.new :access, :type, :hash, :name
9
+
3
10
  attr_accessor :files
4
11
  attr_accessor :path
5
12
 
6
13
  include Enumerable
14
+ include GitSupport
7
15
 
8
16
  # Expects something in the form of REV:PATH
9
17
  # --git REV:[PATH]
@@ -27,7 +35,7 @@ class GitFeeder
27
35
  @files = []
28
36
 
29
37
  FileUtils.cd(@working_dir) do
30
- git_list = git "git-ls-tree -r #{rev}"
38
+ git_list = git "ls-tree -r #{rev}"
31
39
  git_list.each_line do |line|
32
40
  file = GitFile.new(*line.chomp.split(/\s+/,4))
33
41
 
@@ -42,36 +50,10 @@ class GitFeeder
42
50
  def each
43
51
  FileUtils.cd(@working_dir) do
44
52
  @files.each do |file|
45
- code = git "git-show #{file.hash}"
46
- yield(code)
53
+ code = git "show #{file.hash}"
54
+ yield(code, file.name)
47
55
  end
48
56
  end
49
57
  end
50
-
51
- def init_git(path, search_path='')
52
- if File.exist?(File.join(path, ".git"))
53
- # If this is the git repository
54
- @working_dir = path
55
- @search_path = search_path
56
-
57
- else
58
- next_search = File.join( File.split(path).last, search_path )
59
- next_path = File.dirname(path)
60
-
61
- if next_path == path # We have reached the root, and can go no further
62
- raise "Could not find a git working directory"
63
- else
64
- init_git(next_path, next_search)
65
- end
66
- end
67
- end
68
-
69
- def git command
70
- output = `#{command} 2>&1`.chomp
71
- unless $?.success?
72
- raise RuntimeError, output
73
- end
74
- output
75
- end
76
58
 
77
59
  end
@@ -0,0 +1,33 @@
1
+ # Common feeder support for working with git repositories.
2
+ module GitSupport
3
+
4
+ # Finds root of a git repository. If the repository is the parent of the
5
+ # supplied path, then the remainder is made into the search path.
6
+ def init_git(path, search_path='')
7
+ path = File.expand_path(path)
8
+ if File.exist?(File.join(path, ".git"))
9
+ # If this is the git repository
10
+ @working_dir = path
11
+ @search_path = search_path
12
+
13
+ else
14
+ next_search = File.join( File.basename(path), search_path )
15
+ next_path = File.dirname(path)
16
+
17
+ if next_path == path # We have reached the root, and can go no further
18
+ raise "Could not find a git working directory"
19
+ else
20
+ init_git(next_path, next_search)
21
+ end
22
+ end
23
+ end
24
+
25
+ # issues a command to git
26
+ def git command
27
+ output = `git #{command} 2>&1`.chomp
28
+ unless $?.success?
29
+ raise RuntimeError, output
30
+ end
31
+ output
32
+ end
33
+ end
@@ -0,0 +1,53 @@
1
+ # A Feeder reads in files for RubyDiff's processor to
2
+ # run over. GitWorkingDirFeeder reads them from a git repository. Usually
3
+ # used in conjunction with the GitFeeder.
4
+ #
5
+ # Example Usage:
6
+ # ruby_diff --git v0.1:lib --git-wd lib
7
+ class GitWorkingDirFeeder
8
+ attr_accessor :files
9
+ attr_accessor :path
10
+
11
+ include Enumerable
12
+ include GitSupport
13
+
14
+ # Expects something in the form of PATH
15
+ # --file [PATH]
16
+ def initialize(path)
17
+ @path = path
18
+
19
+ path = File.expand_path(path) if path
20
+ init_git(path || '.')
21
+ @file_pattern = if @search_path == ''
22
+ "**.rb"
23
+ elsif @search_path =~ /\.rb#{File::SEPARATOR}$/
24
+ # So appending each piece into the search path during init_git
25
+ # causes the search path to always end with a /
26
+ @search_path[0...-1]
27
+ else
28
+ File.join(@search_path,"**.rb")
29
+ end
30
+
31
+ @files = []
32
+
33
+ FileUtils.cd(@working_dir) do
34
+ git_list = git "ls-files"
35
+ git_list.each_line do |line|
36
+ file = line.chomp
37
+ if File.fnmatch(@file_pattern, file)
38
+ @files << file
39
+ end
40
+ end
41
+ end
42
+
43
+ end
44
+
45
+ def each
46
+ FileUtils.cd(@working_dir) do
47
+ @files.each do |file|
48
+ yield(open(file, 'r'){|io| io.read}, file)
49
+ end
50
+ end
51
+ end
52
+
53
+ end
@@ -4,7 +4,7 @@ class CodeObject
4
4
  attr_reader :children
5
5
  attr_reader :sexp
6
6
 
7
- def initialize(name, parent, sexp)
7
+ def initialize(name, parent=nil, sexp=Sexp.new)
8
8
  @name = name
9
9
  @parent = parent
10
10
  @sexp = sexp.deep_clone
@@ -56,14 +56,58 @@ class MethodCode < CodeObject
56
56
  end
57
57
  end
58
58
 
59
+ # Meta method support
60
+ class MetaCode < CodeObject
61
+ def initialize(name, parent, label, sexp=s() )
62
+ super(name, parent, sexp)
63
+ @label = label
64
+ end
65
+
66
+ def signature
67
+ parent_signature = self.parent ? self.parent.signature : ""
68
+ "#{parent_signature} {#{@label} #{self.name}}"
69
+ end
70
+ end
71
+
72
+ class AccessorHandler
73
+ def initialize(label)
74
+ @label = label
75
+ end
76
+
77
+ def meta_codes(args_sexp, scope)
78
+ meta_codes = []
79
+ args_sexp.sexp_body.each do |arg|
80
+ if name = name_for_arg(arg)
81
+ meta_codes << MetaCode.new(name, scope, @label)
82
+ end
83
+ end
84
+ meta_codes
85
+ end
86
+
87
+ def name_for_arg(name_sexp)
88
+ identifier = name_sexp.to_a
89
+ case identifier.first
90
+ when :lit then identifier.last
91
+ when :str then identifier.last.to_sym
92
+ else nil
93
+ end
94
+ end
95
+ end
96
+
97
+ # StructureProcessor is a SexpProcessor which will generate a logical
98
+ # model of the ruby code. It can be fooled by metaprogramming and method
99
+ # redefinition, but in most cases should be fairly accurate.
59
100
  class StructureProcessor < SexpProcessor
101
+ attr_reader :name
60
102
  attr_accessor :code_objects
61
103
  attr_accessor :root_objects
62
104
 
63
105
  attr_accessor :scope_stack
106
+ attr_reader :meta_methods
64
107
 
65
- def initialize
66
- super
108
+ def initialize(name='')
109
+ super()
110
+ @name = name
67
111
  self.strict = false
68
112
  self.auto_shift_type = true
69
113
 
@@ -71,6 +115,11 @@ class StructureProcessor < SexpProcessor
71
115
  @code_objects = {}
72
116
  @root_objects = {}
73
117
  @scope_stack = []
118
+ @meta_methods = {
119
+ :attr_accessor => AccessorHandler.new("accessor"),
120
+ :attr_writer => AccessorHandler.new("writer"),
121
+ :attr_reader => AccessorHandler.new("reader")
122
+ }
74
123
  end
75
124
 
76
125
  def process_class(exp)
@@ -120,6 +169,18 @@ class StructureProcessor < SexpProcessor
120
169
  s(:sclass, exp_scope, body)
121
170
  end
122
171
 
172
+ def process_fcall(exp)
173
+ name = exp.shift
174
+ args = process exp.shift
175
+
176
+ if meta_handler = @meta_methods[name]
177
+ meta_codes = meta_handler.meta_codes(args, self.scope)
178
+ meta_codes.each{|m| record(m)}
179
+ end
180
+
181
+ return s(:fcall, name, args)
182
+ end
183
+
123
184
  def diff(other_processor)
124
185
  method_diff = CodeComparison.new(self.root_objects, other_processor.root_objects).changes
125
186
  end
@@ -141,4 +202,5 @@ class StructureProcessor < SexpProcessor
141
202
  def scope
142
203
  self.scope_stack.last
143
204
  end
205
+
144
206
  end
@@ -0,0 +1,65 @@
1
+ require 'test/unit'
2
+ require 'test/unit/testcase'
3
+ require "ruby_diff"
4
+
5
+ class CodeComparisonTestCase < Test::Unit::TestCase
6
+ def setup
7
+ @old_objects = []
8
+ @new_objects = []
9
+ @changes = nil
10
+ end
11
+
12
+ def test_empty_set
13
+ assert_changes
14
+ end
15
+
16
+ def test_removed
17
+ @old_objects << DummyCodeObject.new('m')
18
+ assert_changes 'm' => :removed
19
+ end
20
+
21
+ def test_added
22
+ @new_objects << DummyCodeObject.new('m')
23
+ assert_changes 'm' => :added
24
+ end
25
+
26
+ def test_changed
27
+ @old_objects << DummyCodeObject.new('m',nil,s(:a))
28
+ @new_objects << DummyCodeObject.new('m',nil,s(:b))
29
+ assert_changes 'm' => :changed
30
+ end
31
+
32
+ def test_no_change
33
+ @old_objects << DummyCodeObject.new('m',nil,s(:a))
34
+ @new_objects << DummyCodeObject.new('m',nil,s(:a))
35
+ assert_changes
36
+ assert @changes.empty?
37
+ end
38
+
39
+ private
40
+ class DummyCodeObject < CodeObject
41
+ def signature
42
+ name
43
+ end
44
+ end
45
+
46
+ def assert_changes(sig_hash={})
47
+ c = CodeComparison.new(
48
+ code_objects_by_sig(@old_objects),
49
+ code_objects_by_sig(@new_objects)
50
+ )
51
+
52
+ change_hash = {}
53
+ @changes = c.changes
54
+ @changes.each{|change| change_hash[change.signature] = change.operation}
55
+ sig_hash.each do |sig, operation|
56
+ assert_equal operation, change_hash[sig], "#{sig} should have been #{operation}"
57
+ end
58
+ end
59
+
60
+ def code_objects_by_sig(code_objects)
61
+ h = {}
62
+ code_objects.each{|o| h[o.signature] = o}
63
+ h
64
+ end
65
+ end
@@ -2,9 +2,8 @@ require 'test/unit'
2
2
  require 'test/unit/testcase'
3
3
  require "ruby_diff"
4
4
 
5
- DIR = File.join(File.dirname(__FILE__), "git_sample")
6
-
7
5
  class FileFeederTestCase < Test::Unit::TestCase
6
+ DIR = File.join(File.dirname(__FILE__), "git_sample")
8
7
 
9
8
  def test_find_all_files
10
9
  assert File.exist?(DIR)
@@ -26,7 +25,7 @@ class FileFeederTestCase < Test::Unit::TestCase
26
25
  def test_files_are_suitable_for_processing
27
26
  feeder = FileFeeder.new DIR
28
27
  assert_nothing_raised do
29
- sexps = feeder.map{|code| ParseTree.new.parse_tree_for_string(code)}
28
+ sexps = feeder.map{|code,name| ParseTree.new.parse_tree_for_string(code)}
30
29
 
31
30
  sexps.each do |sexp|
32
31
  assert sexp.length > 0, "Parsed code should not be empty"
@@ -2,9 +2,8 @@ require 'test/unit'
2
2
  require 'test/unit/testcase'
3
3
  require "ruby_diff"
4
4
 
5
- GIT_REPO = File.join(File.dirname(__FILE__), "git_sample")
6
-
7
5
  class GitFeederTestCase < Test::Unit::TestCase
6
+ GIT_REPO = File.join(File.dirname(__FILE__), "git_sample")
8
7
 
9
8
  def test_find_all_files
10
9
  assert File.exist?(GIT_REPO)
@@ -26,7 +25,7 @@ class GitFeederTestCase < Test::Unit::TestCase
26
25
  def test_files_are_suitable_for_processing
27
26
  feeder = GitFeeder.new "HEAD:#{GIT_REPO}"
28
27
  assert_nothing_raised do
29
- sexps = feeder.map{|code| ParseTree.new.parse_tree_for_string(code)}
28
+ sexps = feeder.map{|code,name| ParseTree.new.parse_tree_for_string(code)}
30
29
 
31
30
  sexps.each do |sexp|
32
31
  assert sexp.length > 0, "Parsed code should not be empty"
@@ -0,0 +1,36 @@
1
+ require 'test/unit'
2
+ require 'test/unit/testcase'
3
+ require "ruby_diff"
4
+
5
+ class GitWorkingDirFeederTestCase < Test::Unit::TestCase
6
+ DIR = File.join(File.dirname(__FILE__), "git_sample")
7
+
8
+ def test_find_all_files
9
+ assert File.exist?(DIR)
10
+ feeder = GitWorkingDirFeeder.new DIR
11
+ assert_equal 2, feeder.files.length
12
+ end
13
+
14
+ def test_find_single_file
15
+ assert File.exist?(DIR)
16
+ feeder = GitWorkingDirFeeder.new(File.join(DIR,'lib','chapter.rb'))
17
+ assert_equal 1, feeder.files.length
18
+ end
19
+
20
+ def test_find_files_in_sub_dir
21
+ feeder = GitWorkingDirFeeder.new(File.join(DIR,'lib'))
22
+ assert_equal 1, feeder.files.length
23
+ end
24
+
25
+ def test_files_are_suitable_for_processing
26
+ feeder = GitWorkingDirFeeder.new DIR
27
+ assert_nothing_raised do
28
+ sexps = feeder.map{|code,name| ParseTree.new.parse_tree_for_string(code)}
29
+
30
+ sexps.each do |sexp|
31
+ assert sexp.length > 0, "Parsed code should not be empty"
32
+ end
33
+ end
34
+ end
35
+
36
+ end
@@ -63,6 +63,22 @@ class StructureProcessorTestCase < Test::Unit::TestCase
63
63
  CODE
64
64
  end
65
65
 
66
+ def test_reader_attribute
67
+ assert_signatures <<-CODE, ["A {reader b}"], [MetaCode]
68
+ class A
69
+ attr_reader :b
70
+ end
71
+ CODE
72
+ end
73
+
74
+ def test_multiple_writer_attributes
75
+ assert_signatures <<-CODE, ["A {writer b}", "A {writer c}"], [MetaCode]
76
+ class A
77
+ attr_writer :b, 'c'
78
+ end
79
+ CODE
80
+ end
81
+
66
82
  def assert_signatures(code, signatures, types=[MethodCode])
67
83
  sexp = ParseTree.new.parse_tree_for_string(code)
68
84
  processor = StructureProcessor.new()
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
3
3
  specification_version: 1
4
4
  name: ruby_diff
5
5
  version: !ruby/object:Gem::Version
6
- version: "0.1"
7
- date: 2008-06-04 00:00:00 -07:00
6
+ version: 0.1.5
7
+ date: 2008-06-09 00:00:00 -07:00
8
8
  summary: a higher level diff application for analyzing changes to ruby code
9
9
  require_paths:
10
10
  - lib
@@ -40,19 +40,25 @@ files:
40
40
  - lib/ruby_diff/code_comparison.rb
41
41
  - lib/ruby_diff/file_feeder.rb
42
42
  - lib/ruby_diff/git_feeder.rb
43
+ - lib/ruby_diff/git_support.rb
44
+ - lib/ruby_diff/git_working_dir_feeder.rb
43
45
  - lib/ruby_diff/patterns.rb
44
46
  - lib/ruby_diff/structure_processor.rb
45
47
  - ruby_diff.gemspec
48
+ - test/code_comparison_test.rb
46
49
  - test/file_feeder_test.rb
47
50
  - test/git_feeder_test.rb
48
51
  - test/git_sample/README
49
52
  - test/git_sample/book.rb
50
53
  - test/git_sample/lib/chapter.rb
54
+ - test/git_working_dir_feeder_test.rb
51
55
  - test/structure_processor_test.rb
52
56
  test_files:
53
57
  - test/git_feeder_test.rb
54
58
  - test/file_feeder_test.rb
59
+ - test/code_comparison_test.rb
55
60
  - test/structure_processor_test.rb
61
+ - test/git_working_dir_feeder_test.rb
56
62
  rdoc_options:
57
63
  - --main
58
64
  - README.txt