transpec 1.2.1 → 1.2.2

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: f1cbae52577334b666b5a02f1c926f8a8ca1af16
4
- data.tar.gz: 181c31e4d34c5b5f4e966d0627fb30fa9d875142
3
+ metadata.gz: 59870e21327ecc3a1a3a436db95ed2f6ba446a66
4
+ data.tar.gz: dbb7b187b7a2d0224727c8bad33ff25e26cb9fe5
5
5
  SHA512:
6
- metadata.gz: 1d41de85a3be6bb7e6d271c170c169358a46a8501e52023b13a1fc74df4633c5be597798359312e805666156e85119b6911d712981ca35fd1a3c8105c616f468
7
- data.tar.gz: c0970c8ed8a6daefe39fc0bf136d54d58872255d0dfdaef1ebf4aff500fd1511e369af3c0c06f81c52153ca5cbcc29a12a884380a59256fff8f9274e4c533cf4
6
+ metadata.gz: 407da45de0345dd8d3e3e857b4e02038aa9c8d379d9dc49c49ae30cb100ba0ade7d82a3cf348001b59c9c0d15debea59203ec0a034fd59039e34895aca80a5d9
7
+ data.tar.gz: 8584f6ffac8f1157e9e78ca6f1d158cc67f603f669480f400c16c8e9f8ea8425f508d65a78a5d3ef8b88072c4df67012cdad477faebd69b31091b2975e6665e2
data/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## Development
4
4
 
5
+ ## v1.2.2
6
+
7
+ * Fix error `singleton can't be dumped (TypeError)` at the end of dynamic analysis ([#17](https://github.com/yujinakayama/transpec/issues/17))
8
+ * Do not copy pseudo files (device, socket, etc.) in dynamic analysis ([#17](https://github.com/yujinakayama/transpec/issues/17))
9
+ * Fix error `undefined method receive_messages_available?` while conversion ([#17](https://github.com/yujinakayama/transpec/issues/17))
10
+
5
11
  ## v1.2.1
6
12
 
7
13
  * Apply `-p/--no-parentheses-matcher-arg` to the conversion of `have(n).items` (`obj.should have(n).items` is now converted to `expect(obj.size).to eq n` with `-p/--no-parentheses-matcher-arg`)
data/README.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  # Transpec
4
4
 
5
- **Transpec** automatically converts your specs into latest [RSpec](http://rspec.info/) syntax with static and dynamic code analysis.
5
+ **Transpec** automatically converts your specs into the latest [RSpec](http://rspec.info/) syntax with static and dynamic code analysis.
6
6
 
7
- This aims to facilitate smooth transition to RSpec 3, and is now ready for RSpec 2.99 and 3.0 beta!
7
+ This aims to facilitate smooth transition to RSpec 3, and it's now ready for RSpec 2.99 and 3.0 beta!
8
8
 
9
9
  See the following pages for the new RSpec syntax and the plan for RSpec 3:
10
10
 
@@ -154,6 +154,12 @@ $ git commit -eF .git/COMMIT_EDITMSG
154
154
 
155
155
  And you are done!
156
156
 
157
+ ## Upgrade Process to RSpec 3 beta
158
+
159
+ If you are going to use Transpec in the upgrade process to RSpec 3 beta, read the article by [Myron Marston](https://github.com/myronmarston):
160
+
161
+ * [Myron Marston » RSpec 2.99 and 3.0 betas have been released!](http://myronmars.to/n/dev-blog/2013/11/rspec-2-99-and-3-0-betas-have-been-released)
162
+
157
163
  ## Options
158
164
 
159
165
  ### `-f/--force`
data/README.md.erb CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  # Transpec
4
4
 
5
- **Transpec** automatically converts your specs into latest [RSpec](http://rspec.info/) syntax with static and dynamic code analysis.
5
+ **Transpec** automatically converts your specs into the latest [RSpec](http://rspec.info/) syntax with static and dynamic code analysis.
6
6
 
7
- This aims to facilitate smooth transition to RSpec 3, and is now ready for RSpec 2.99 and 3.0 beta!
7
+ This aims to facilitate smooth transition to RSpec 3, and it's now ready for RSpec 2.99 and 3.0 beta!
8
8
 
9
9
  See the following pages for the new RSpec syntax and the plan for RSpec 3:
10
10
 
@@ -127,6 +127,12 @@ $ git commit -eF .git/COMMIT_EDITMSG
127
127
 
128
128
  And you are done!
129
129
 
130
+ ## Upgrade Process to RSpec 3 beta
131
+
132
+ If you are going to use Transpec in the upgrade process to RSpec 3 beta, read the article by [Myron Marston](https://github.com/myronmarston):
133
+
134
+ * [Myron Marston » RSpec 2.99 and 3.0 betas have been released!](http://myronmars.to/n/dev-blog/2013/11/rspec-2-99-and-3-0-betas-have-been-released)
135
+
130
136
  ## Options
131
137
 
132
138
  ### `-f/--force`
data/lib/transpec.rb CHANGED
@@ -16,7 +16,7 @@ module Transpec
16
16
  if rspec_dependency
17
17
  rspec_requirement = rspec_dependency.requirement
18
18
  gem_version = rspec_requirement.requirements.first.find { |r| r.is_a?(Gem::Version) }
19
- RSpecVersion.new(gem_version.to_s)
19
+ RSpecVersion.new(gem_version)
20
20
  else
21
21
  # Using development version of RSpec with Bundler.
22
22
  current_rspec_version
@@ -13,7 +13,7 @@ module Transpec
13
13
  conversion_summary = @report.summary(bullet: '*', separate_by_blank_line: true)
14
14
 
15
15
  <<-END.gsub(/^\s+\|/, '').chomp
16
- |Convert specs to latest RSpec syntax with Transpec
16
+ |Convert specs to the latest RSpec syntax with Transpec
17
17
  |
18
18
  |This conversion is done by Transpec #{Transpec::Version} with the following command:
19
19
  | transpec #{@cli_args.join(' ')}
@@ -5,8 +5,9 @@ require 'transpec/dynamic_analyzer/runtime_data'
5
5
  require 'transpec/file_finder'
6
6
  require 'transpec/project'
7
7
  require 'tmpdir'
8
+ require 'find'
9
+ require 'pathname'
8
10
  require 'fileutils'
9
- require 'ostruct'
10
11
  require 'shellwords'
11
12
  require 'English'
12
13
 
@@ -15,10 +16,10 @@ module Transpec
15
16
  EVAL_TARGET_TYPES = [:object, :context]
16
17
  ANALYSIS_METHOD = 'transpec_analysis'
17
18
  HELPER_FILE = 'transpec_analysis_helper.rb'
18
- RESULT_FILE = 'transpec_analysis_result.dump'
19
+ RESULT_FILE = 'transpec_analysis_result.json'
19
20
  HELPER_SOURCE = <<-END
20
- require 'ostruct'
21
21
  require 'pathname'
22
+ require 'json'
22
23
 
23
24
  module TranspecAnalysis
24
25
  @base_path = Dir.pwd
@@ -38,9 +39,14 @@ module Transpec
38
39
  end
39
40
 
40
41
  at_exit do
42
+ # Use JSON rather than Marshal so that:
43
+ # * Unknown third-party class information won't be serialized.
44
+ # (Such objects are stored as a string.)
45
+ # * Singleton method information won't be serialized.
46
+ # (With Marshal.load, `singleton can't be dumped (TypeError)` will be raised.)
41
47
  path = File.join(@base_path, '#{RESULT_FILE}')
42
48
  File.open(path, 'w') do |file|
43
- Marshal.dump(data, file)
49
+ JSON.dump(data, file)
44
50
  end
45
51
  end
46
52
  end
@@ -52,12 +58,12 @@ module Transpec
52
58
  when :context then context
53
59
  end
54
60
 
55
- eval_data = OpenStruct.new
61
+ eval_data = {}
56
62
 
57
63
  begin
58
- eval_data.result = target.instance_eval(code)
64
+ eval_data[:result] = target.instance_eval(code)
59
65
  rescue Exception => error
60
- eval_data.error = error
66
+ eval_data[:error] = error
61
67
  end
62
68
 
63
69
  [key, eval_data]
@@ -112,8 +118,7 @@ module Transpec
112
118
  run_rspec(paths)
113
119
 
114
120
  File.open(RESULT_FILE) do |file|
115
- hash = Marshal.load(file)
116
- RuntimeData.new(hash)
121
+ RuntimeData.load(file)
117
122
  end
118
123
  end
119
124
  end
@@ -124,7 +129,7 @@ module Transpec
124
129
  @in_copied_project = true
125
130
 
126
131
  Dir.mktmpdir do |tmpdir|
127
- FileUtils.cp_r(@project.path, tmpdir)
132
+ copy_recursively(@project.path, tmpdir)
128
133
  @copied_project_path = File.join(tmpdir, @project.basename)
129
134
  Dir.chdir(@copied_project_path) do
130
135
  yield
@@ -156,5 +161,45 @@ module Transpec
156
161
  end
157
162
  end
158
163
  end
164
+
165
+ def copy_recursively(source_root, destination_root)
166
+ source_root = File.expand_path(source_root)
167
+ source_root_pathname = Pathname.new(source_root)
168
+
169
+ destination_root = File.expand_path(destination_root)
170
+ if File.directory?(destination_root)
171
+ destination_root = File.join(destination_root, File.basename(source_root))
172
+ end
173
+
174
+ Find.find(source_root) do |source_path|
175
+ relative_path = Pathname.new(source_path).relative_path_from(source_root_pathname).to_s
176
+ destination_path = File.join(destination_root, relative_path)
177
+ copy(source_path, destination_path)
178
+ end
179
+ end
180
+
181
+ private
182
+
183
+ def copy(source, destination)
184
+ if File.symlink?(source)
185
+ File.symlink(File.readlink(source), destination)
186
+ elsif File.directory?(source)
187
+ FileUtils.mkdir_p(destination)
188
+ elsif File.file?(source)
189
+ FileUtils.copy_file(source, destination)
190
+ end
191
+
192
+ copy_permission(source, destination) if File.exist?(destination)
193
+ end
194
+
195
+ def copy_permission(source, destination)
196
+ source_mode = File.lstat(source).mode
197
+ begin
198
+ File.lchmod(source_mode, destination)
199
+ rescue NotImplementedError, Errno::ENOSYS
200
+ # Should not change mode of symlink's destination.
201
+ File.chmod(source_mode, destination) unless File.symlink?(destination)
202
+ end
203
+ end
159
204
  end
160
205
  end
@@ -1,18 +1,26 @@
1
1
  # coding: utf-8
2
2
 
3
+ require 'json'
4
+ require 'ostruct'
3
5
  require 'pathname'
4
6
 
5
7
  module Transpec
6
8
  class DynamicAnalyzer
7
9
  class RuntimeData
8
- attr_reader :hash
10
+ attr_reader :data
9
11
 
10
- def initialize(hash = {})
11
- @hash = hash
12
+ def self.load(string_or_io)
13
+ options = { object_class: CompatibleOpenStruct, symbolize_names: true }
14
+ data = JSON.load(string_or_io, nil, options)
15
+ new(data)
16
+ end
17
+
18
+ def initialize(data = CompatibleOpenStruct.new)
19
+ @data = data
12
20
  end
13
21
 
14
22
  def [](node)
15
- @hash[node_id(node)]
23
+ @data[node_id(node)]
16
24
  end
17
25
 
18
26
  def node_id(node)
@@ -22,6 +30,21 @@ module Transpec
22
30
  relative_path = Pathname.new(absolute_path).relative_path_from(Pathname.pwd).to_s
23
31
  [relative_path, source_range.begin_pos, source_range.end_pos].join('_')
24
32
  end
33
+
34
+ class CompatibleOpenStruct < OpenStruct
35
+ # OpenStruct#[] is available from Ruby 2.0.
36
+ unless method_defined?(:[])
37
+ def [](key)
38
+ __send__(key)
39
+ end
40
+ end
41
+
42
+ unless method_defined?(:[]=)
43
+ def []=(key, value)
44
+ __send__("#{key}=", value)
45
+ end
46
+ end
47
+ end
25
48
  end
26
49
  end
27
50
  end
@@ -3,7 +3,11 @@
3
3
  require 'transpec'
4
4
 
5
5
  module Transpec
6
- class RSpecVersion < Gem::Version
6
+ # Gem::Version caches its instances with class variable @@all,
7
+ # so we should not inherit it.
8
+ class RSpecVersion
9
+ include Comparable
10
+
7
11
  # http://www.ruby-doc.org/stdlib-2.0.0/libdoc/rubygems/rdoc/Gem/Version.html
8
12
  #
9
13
  # If any part contains letters (currently only a-z are supported) then that version is
@@ -11,15 +15,33 @@ module Transpec
11
15
  # Prerelease parts are sorted alphabetically using the normal Ruby string sorting rules.
12
16
  # If a prerelease part contains both letters and numbers, it will be broken into multiple parts
13
17
  # to provide expected sort behavior (1.0.a10 becomes 1.0.a.10, and is greater than 1.0.a9).
14
- VERSION_2_99 = new('2.99.aaaaaaaaaa')
15
- VERSION_3_0 = new('3.0.aaaaaaaaaa')
18
+ GEM_VERSION_2_99 = Gem::Version.new('2.99.aaaaaaaaaa')
19
+ GEM_VERSION_3_0 = Gem::Version.new('3.0.aaaaaaaaaa')
20
+
21
+ attr_reader :gem_version
22
+
23
+ def initialize(version)
24
+ @gem_version = if version.is_a?(Gem::Version)
25
+ version
26
+ else
27
+ Gem::Version.new(version)
28
+ end
29
+ end
16
30
 
17
31
  def be_truthy_available?
18
- self >= VERSION_2_99
32
+ @gem_version >= GEM_VERSION_2_99
19
33
  end
20
34
 
21
35
  def receive_messages_available?
22
- self >= VERSION_3_0
36
+ @gem_version >= GEM_VERSION_3_0
37
+ end
38
+
39
+ def <=>(other)
40
+ @gem_version <=> other.gem_version
41
+ end
42
+
43
+ def to_s
44
+ @gem_version.to_s
23
45
  end
24
46
  end
25
47
  end
@@ -98,8 +98,9 @@ module Transpec
98
98
 
99
99
  def query_method
100
100
  node_data = runtime_node_data(@expectation.subject_node)
101
- if node_data
102
- (QUERY_METHOD_PRIORITIES & node_data[:available_query_methods].result).first
101
+ if node_data && node_data[:available_query_methods].result.is_a?(Array)
102
+ available_query_methods = node_data[:available_query_methods].result.map(&:to_sym)
103
+ (QUERY_METHOD_PRIORITIES & available_query_methods).first
103
104
  else
104
105
  default_query_method
105
106
  end
@@ -5,7 +5,7 @@ module Transpec
5
5
  module Version
6
6
  MAJOR = 1
7
7
  MINOR = 2
8
- PATCH = 1
8
+ PATCH = 2
9
9
 
10
10
  def self.to_s
11
11
  [MAJOR, MINOR, PATCH].join('.')
@@ -48,7 +48,8 @@ module CacheHelper
48
48
  def cache_dir
49
49
  @cache_dir ||= begin
50
50
  project_root = File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
51
- cache_dir = File.join(project_root, 'tmp', 'spec_cache')
51
+ ruby_version = "#{RUBY_ENGINE}#{RUBY_VERSION}"
52
+ cache_dir = File.join(project_root, 'tmp', 'spec_cache', ruby_version)
52
53
 
53
54
  unless Dir.exist?(cache_dir)
54
55
  require 'fileutils'
@@ -27,7 +27,7 @@ module Transpec
27
27
  let(:lines) { commit_message.to_s.lines.to_a }
28
28
 
29
29
  it 'has concise summary at first line' do
30
- lines[0].chomp.should == 'Convert specs to latest RSpec syntax with Transpec'
30
+ lines[0].chomp.should == 'Convert specs to the latest RSpec syntax with Transpec'
31
31
  end
32
32
 
33
33
  it 'has blank line at second line' do
@@ -167,14 +167,71 @@ module Transpec
167
167
 
168
168
  subject(:element) { runtime_data[target_node] }
169
169
 
170
- it 'is a hash' do
171
- should be_a(Hash)
170
+ it 'is an OpenStruct' do
171
+ should be_a(OpenStruct)
172
172
  end
173
173
 
174
174
  it 'has result of requested analysis' do
175
- element[:available_query_methods].result.should =~ [:size, :count, :length]
175
+ element[:available_query_methods].result.should =~ %w(size count length)
176
176
  end
177
177
  end
178
178
  end
179
+
180
+ describe '#copy_recursively' do
181
+ it 'copies files recursively' do
182
+ [
183
+ 'src/file1',
184
+ 'src/file2',
185
+ 'src/dir1/file',
186
+ 'src/dir2/file'
187
+ ].each do |path|
188
+ create_file(path, '')
189
+ end
190
+
191
+ dynamic_analyzer.copy_recursively('src', 'dst')
192
+
193
+ [
194
+ 'dst/file1',
195
+ 'dst/file2',
196
+ 'dst/dir1/file',
197
+ 'dst/dir2/file'
198
+ ].each do |path|
199
+ File.exist?(path).should be_true
200
+ end
201
+ end
202
+
203
+ it 'copies only directories, files and symlinks' do
204
+ create_file('src/file', '')
205
+ File.symlink('file', 'src/symlink')
206
+ Dir.mkdir('src/dir')
207
+ system('mkfifo', 'src/fifo')
208
+
209
+ dynamic_analyzer.copy_recursively('src', 'dst')
210
+
211
+ File.file?('dst/file').should be_true
212
+ File.symlink?('dst/symlink').should be_true
213
+ File.directory?('dst/dir').should be_true
214
+ File.exist?('dst/fifo').should be_false
215
+ end
216
+
217
+ def permission(path)
218
+ format('%o', File.lstat(path).mode)[-4..-1]
219
+ end
220
+
221
+ it 'preserves permission' do
222
+ create_file('src/file', '')
223
+ File.chmod(0755, 'src/file')
224
+
225
+ File.symlink('file', 'src/symlink')
226
+
227
+ Dir.mkdir('src/dir')
228
+ File.chmod(0600, 'src/dir')
229
+
230
+ dynamic_analyzer.copy_recursively('src', 'dst')
231
+
232
+ permission('dst/file').should == '0755'
233
+ permission('dst/dir').should == '0600'
234
+ end
235
+ end
179
236
  end
180
237
  end
@@ -64,6 +64,13 @@ class TranspecTest
64
64
  next if ['.', '..', 'tmp'].include?(entry)
65
65
  FileUtils.cp_r(entry, project_dir)
66
66
  end
67
+
68
+ spec_cache_dir = File.join('tmp', 'spec_cache')
69
+
70
+ if Dir.exist?(spec_cache_dir)
71
+ Dir.mkdir(File.join(project_dir, 'tmp'))
72
+ FileUtils.cp_r(spec_cache_dir, File.join(project_dir, spec_cache_dir))
73
+ end
67
74
  end
68
75
 
69
76
  bundle_install
data/tasks/readme.rake CHANGED
@@ -5,13 +5,6 @@ task :readme do
5
5
  require 'erb'
6
6
  require 'transpec/cli'
7
7
 
8
- gem_specification = Gem::Specification.load('transpec.gemspec')
9
- rspec_dependency = gem_specification.dependencies.find { |d| d.name == 'rspec' }
10
- rspec_requirement = rspec_dependency.requirement
11
- # rubocop:disable UselessAssignment
12
- rspec_version = rspec_requirement.requirements.first.find { |r| r.is_a?(Gem::Version) }
13
- # rubocop:enable UselessAssignment
14
-
15
8
  erb = ERB.new(File.read('README.md.erb'), nil, '-')
16
9
  content = erb.result(binding)
17
10
  File.write('README.md', content)
data/transpec.gemspec CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
  spec.authors = ['Yuji Nakayama']
11
11
  spec.email = ['nkymyj@gmail.com']
12
12
  spec.summary = 'A RSpec syntax converter'
13
- spec.description = 'Transpec converts your specs into latest RSpec syntax ' +
13
+ spec.description = 'Transpec converts your specs into the latest RSpec syntax ' +
14
14
  'with static and dynamic code analysis.'
15
15
  spec.homepage = 'https://github.com/yujinakayama/transpec'
16
16
  spec.license = 'MIT'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: transpec
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yuji Nakayama
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-11-09 00:00:00.000000000 Z
11
+ date: 2013-11-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parser
@@ -164,8 +164,8 @@ dependencies:
164
164
  - - ~>
165
165
  - !ruby/object:Gem::Version
166
166
  version: '0.3'
167
- description: Transpec converts your specs into latest RSpec syntax with static and
168
- dynamic code analysis.
167
+ description: Transpec converts your specs into the latest RSpec syntax with static
168
+ and dynamic code analysis.
169
169
  email:
170
170
  - nkymyj@gmail.com
171
171
  executables: