skippy 0.4.0.a → 0.5.0.a

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Skippy::Helpers
2
4
  module File
3
5
 
@@ -7,6 +9,7 @@ module Skippy::Helpers
7
9
  # @return [Array<Pathname>]
8
10
  def directories(pathname)
9
11
  return [] unless pathname.exist?
12
+
10
13
  pathname.children.select(&:directory?)
11
14
  end
12
15
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'git'
2
4
  require 'naturally'
3
5
  require 'pathname'
@@ -32,8 +34,7 @@ class Skippy::GitLibraryInstaller < Skippy::LibraryInstaller
32
34
  git.checkout(previous_commit) if previous_commit
33
35
  raise
34
36
  end
35
- library = Skippy::Library.new(target, source: source)
36
- library
37
+ Skippy::Library.new(target, source: source)
37
38
  end
38
39
 
39
40
  private
@@ -55,18 +56,19 @@ class Skippy::GitLibraryInstaller < Skippy::LibraryInstaller
55
56
  git = Git.open(target)
56
57
  previous_commit = git.object('HEAD^').class
57
58
  git.reset_hard
58
- git.pull
59
+ git.fetch
59
60
  [git, previous_commit]
60
61
  end
61
62
 
62
63
  # @param [Git::Base]
63
64
  # @param [String] branch
64
65
  def checkout_branch(git, branch)
65
- branches = git.braches.map(&:name)
66
+ branches = git.branches.map(&:name)
66
67
  info "Branches: #{branches.inspect}"
67
68
  unless branches.include?(branch)
68
69
  raise Skippy::BranchNotFound, "Found no branch named: '#{branch}'"
69
70
  end
71
+
70
72
  git.checkout(branch)
71
73
  nil
72
74
  end
@@ -77,6 +79,7 @@ class Skippy::GitLibraryInstaller < Skippy::LibraryInstaller
77
79
  tags = Naturally.sort_by(git.tags, :name)
78
80
  tag = latest_version?(version) ? tags.last : resolve_tag(tags, version)
79
81
  raise Skippy::TagNotFound, "Found no version: '#{version}'" if tag.nil?
82
+
80
83
  git.checkout(tag)
81
84
  # Verify the library version with the tagged version.
82
85
  target = path.join(source.lib_path)
@@ -97,6 +100,7 @@ class Skippy::GitLibraryInstaller < Skippy::LibraryInstaller
97
100
  requirement = Gem::Requirement.new(version)
98
101
  tags.reverse.find { |tag|
99
102
  next false unless Gem::Version.correct?(tag.name)
103
+
100
104
  tag_version = Gem::Version.new(tag.name)
101
105
  requirement.satisfied_by?(tag_version)
102
106
  }
@@ -104,7 +108,7 @@ class Skippy::GitLibraryInstaller < Skippy::LibraryInstaller
104
108
 
105
109
  # @param [String] version
106
110
  def edge_version?(version)
107
- version && version.casecmp('edge').zero?
111
+ version&.casecmp('edge')&.zero?
108
112
  end
109
113
 
110
114
  # @param [String] version
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'pathname'
2
4
 
3
5
  require 'skippy/installer'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'skippy/lib_source'
2
4
  require 'skippy/library'
3
5
  require 'skippy/project'
@@ -28,7 +30,7 @@ class Skippy::LibraryInstaller
28
30
  # @param [Symbol] type
29
31
  # @param [String] message
30
32
  def status(type, message)
31
- @messager.call(type, message) if @messager
33
+ @messager&.call(type, message)
32
34
  end
33
35
 
34
36
  # @param [String] message
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'pathname'
2
4
 
3
5
  require 'skippy/library'
@@ -13,6 +15,7 @@ class Skippy::LibModule
13
15
  def initialize(library, path)
14
16
  @path = Pathname.new(path)
15
17
  raise ModuleNotFoundError, @path.to_s unless @path.file?
18
+
16
19
  @library = library
17
20
  end
18
21
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'digest'
2
4
  require 'net/http'
3
5
  require 'pathname'
@@ -40,6 +42,7 @@ class Skippy::LibrarySource
40
42
  # @return [String, nil]
41
43
  def requirement
42
44
  return nil if @options[:requirement].nil?
45
+
43
46
  # Normalize the version requirement pattern.
44
47
  parts = Gem::Requirement.parse(@options[:requirement])
45
48
  # .parse will from '1.2.3' return ['=', '1.2.3']. Don't need that.
@@ -117,7 +120,10 @@ class Skippy::LibrarySource
117
120
  # @param [String] source
118
121
  # @return [String]
119
122
  def resolve_from_git_uri(source)
120
- uri = URI.parse(source)
123
+ # This can be a local Windows path, normalize path separators to allow the
124
+ # path to be parsed.
125
+ normalized = source.tr('\\', '/')
126
+ uri = URI.parse(normalized)
121
127
  # When logged in, BitBucket will display a URI with the user's username.
122
128
  uri.user = ''
123
129
  uri.to_s
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'json'
2
4
  require 'pathname'
3
5
 
@@ -12,7 +14,7 @@ class Skippy::Library
12
14
 
13
15
  include Skippy::Helpers::File
14
16
 
15
- CONFIG_FILENAME = 'skippy.json'.freeze
17
+ CONFIG_FILENAME = 'skippy.json'
16
18
 
17
19
  attr_reader :path, :source, :requirement
18
20
 
@@ -28,8 +30,10 @@ class Skippy::Library
28
30
  @path = Pathname.new(path)
29
31
  raise LibraryNotFoundError, @path.to_s unless @path.directory?
30
32
  raise LibraryNotFoundError, config_file.to_s unless config_file.exist?
33
+
31
34
  @config = Skippy::Config.load(config_file)
32
35
  raise LibraryNotFoundError, 'Not a Skippy Library' unless @config[:library]
36
+
33
37
  @source = source
34
38
  end
35
39
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'git'
2
4
  require 'json'
3
5
  require 'naturally'
@@ -29,13 +31,14 @@ class Skippy::LibraryManager
29
31
  # @param [Skippy::Project] project
30
32
  def initialize(project)
31
33
  raise TypeError, 'expected a Project' unless project.is_a?(Skippy::Project)
34
+
32
35
  @project = project
33
36
  @libraries = SortedSet.new(discover_libraries)
34
37
  end
35
38
 
36
39
  # @yield [Skippy::Library]
37
- def each
38
- @libraries.each { |library| yield library }
40
+ def each(&block)
41
+ @libraries.each(&block)
39
42
  self
40
43
  end
41
44
 
@@ -56,8 +59,10 @@ class Skippy::LibraryManager
56
59
  if library_name.nil? || module_name.nil?
57
60
  raise ArgumentError, 'expected a module path'
58
61
  end
62
+
59
63
  library = find_library(library_name)
60
64
  return nil if library.nil?
65
+
61
66
  library.modules.find { |mod| mod.basename.casecmp(module_name).zero? }
62
67
  end
63
68
 
@@ -77,11 +82,12 @@ class Skippy::LibraryManager
77
82
  # @return [Skippy::Library]
78
83
  def install(source, options = {})
79
84
  raise Skippy::Project::ProjectNotSavedError unless project.exist?
85
+
80
86
  lib_source = Skippy::LibrarySource.new(project, source, options)
81
87
 
82
88
  installer = get_installer(lib_source)
83
89
  if block_given?
84
- installer.on_status { |type, message|
90
+ installer.on_status { |type, message| # rubocop:disable Style/ExplicitBlockArgument
85
91
  yield type, message
86
92
  }
87
93
  end
@@ -99,8 +105,10 @@ class Skippy::LibraryManager
99
105
  # @return [Skippy::Library]
100
106
  def uninstall(lib)
101
107
  raise Skippy::Project::ProjectNotSavedError unless project.exist?
108
+
102
109
  library = lib.is_a?(Skippy::Library) ? lib : find_library(lib)
103
110
  raise Skippy::LibraryNotFound, 'Library not found' if library.nil?
111
+
104
112
  # Uninstall modules first - using the module manager.
105
113
  vendor_path = project.modules.vendor_path
106
114
  vendor_module_path = vendor_path.join(library.name)
@@ -113,9 +121,11 @@ class Skippy::LibraryManager
113
121
  vendor_path.rmdir
114
122
  end
115
123
  raise 'Unable to remove vendor modules' if vendor_module_path.exist?
124
+
116
125
  # Now the library itself is safe to remove.
117
126
  library.path.rmtree if library.path.exist?
118
127
  raise 'Unable to remove library' if library.path.exist?
128
+
119
129
  @libraries.delete(library)
120
130
  library
121
131
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'fileutils'
2
4
  require 'json'
3
5
  require 'pathname'
@@ -17,13 +19,14 @@ class Skippy::ModuleManager
17
19
  # @param [Skippy::Project] project
18
20
  def initialize(project)
19
21
  raise TypeError, 'expected a Project' unless project.is_a?(Skippy::Project)
22
+
20
23
  @project = project
21
24
  @modules = SortedSet.new(discover_modules)
22
25
  end
23
26
 
24
27
  # @yield [Skippy::LibModule]
25
- def each
26
- @modules.each { |lib_module| yield lib_module }
28
+ def each(&block)
29
+ @modules.each(&block)
27
30
  self
28
31
  end
29
32
 
@@ -40,7 +43,7 @@ class Skippy::ModuleManager
40
43
  # @param [Skippy::LibModule, String] lib_module
41
44
  def installed?(lib_module)
42
45
  module_name = lib_module.name
43
- modules = project && project.config.get(:modules, [])
46
+ modules = project&.config&.get(:modules, [])
44
47
  modules.any? { |mod| mod.casecmp(module_name).zero? }
45
48
  end
46
49
 
@@ -48,6 +51,7 @@ class Skippy::ModuleManager
48
51
  # @return [Skippy::LibModule]
49
52
  def use(module_name)
50
53
  raise Skippy::Project::ProjectNotSavedError unless project.exist?
54
+
51
55
  lib_module = project.libraries.find_module_or_fail(module_name)
52
56
 
53
57
  source = lib_module.path
@@ -63,6 +67,7 @@ class Skippy::ModuleManager
63
67
  # @return [Array<Skippy::LibModule>]
64
68
  def update(library)
65
69
  raise Skippy::Project::ProjectNotSavedError unless project.exist?
70
+
66
71
  installed = select { |mod| mod.library.name.casecmp(library.name).zero? }
67
72
  installed.each { |mod| use(mod.name) }
68
73
  installed
@@ -72,6 +77,7 @@ class Skippy::ModuleManager
72
77
  # @return [Skippy::LibModule]
73
78
  def remove(module_name)
74
79
  raise Skippy::Project::ProjectNotSavedError unless project.exist?
80
+
75
81
  lib_module = project.libraries.find_module_or_fail(module_name)
76
82
 
77
83
  target = vendor_path.join(lib_module.library.name, lib_module.path.basename)
@@ -103,9 +109,11 @@ class Skippy::ModuleManager
103
109
  project.libraries.each { |library|
104
110
  library_vendor_path = vendor_path.join(library.name)
105
111
  next unless library_vendor_path.directory?
112
+
106
113
  library_vendor_path.each_child { |module_file|
107
114
  next unless module_file.file?
108
115
  next unless module_file.extname.casecmp('.rb').zero?
116
+
109
117
  modules << Skippy::LibModule.new(library, module_file)
110
118
  }
111
119
  }
@@ -122,6 +130,7 @@ class Skippy::ModuleManager
122
130
  basename = source.basename('.*')
123
131
  source_support_folder = source.parent.join(basename)
124
132
  return unless source_support_folder.directory?
133
+
125
134
  target_support_folder = target.parent.join(basename)
126
135
  copy_directory(lib_module, source_support_folder, target_support_folder)
127
136
  end
@@ -133,6 +142,7 @@ class Skippy::ModuleManager
133
142
  Dir.glob("#{source_path}/**/*") { |filename|
134
143
  source = Pathname.new(filename)
135
144
  next unless source.file?
145
+
136
146
  relative_path = source.relative_path_from(source_path)
137
147
  target = target_path.join(relative_path)
138
148
  copy_file(lib_module, source, target)
@@ -150,7 +160,7 @@ class Skippy::ModuleManager
150
160
  transform_module(content)
151
161
  File.write(target, content)
152
162
  else
153
- File.copy(source, target)
163
+ FileUtils.copy(source, target)
154
164
  end
155
165
  end
156
166
 
@@ -164,7 +174,7 @@ class Skippy::ModuleManager
164
174
  content
165
175
  end
166
176
 
167
- LIB_REQUIRE_PATTERN = %r{(\brequire ["'])(modules)(/[^"']*["'])}
177
+ LIB_REQUIRE_PATTERN = %r{(\brequire ["'])(modules)(/[^"']*["'])}.freeze
168
178
 
169
179
  # Transform the require statements to the target destination.
170
180
  #
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'skippy/error'
2
4
 
3
5
  class Skippy::Namespace
@@ -6,6 +8,7 @@ class Skippy::Namespace
6
8
  unless valid?(namespace)
7
9
  raise Skippy::Error, "'#{namespace}' is not a valid Ruby namespace"
8
10
  end
11
+
9
12
  @namespace = namespace
10
13
  end
11
14
 
@@ -24,6 +27,7 @@ class Skippy::Namespace
24
27
  def short_name
25
28
  items = to_a
26
29
  return to_s unless items.size > 1
30
+
27
31
  initials = items.first.scan(/[[:upper:]]/)
28
32
  prefix = initials.size > 1 ? initials.join : items.first[0, 2]
29
33
  "#{prefix}_#{items.last}"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Skippy::OSCommon
2
4
 
3
5
  # @param [String] command
@@ -23,4 +25,11 @@ class Skippy::OSCommon
23
25
  raise NotImplementedError
24
26
  end
25
27
 
28
+ # @param [String] path
29
+ # @return [Integer, nil]
30
+ def sketchup_version_from_path(path)
31
+ match = File.basename(path).match(/[0-9.]+/)
32
+ match ? match[0].to_i : nil
33
+ end
34
+
26
35
  end
data/lib/skippy/os/mac.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'skippy/os/common'
2
4
  require 'skippy/sketchup/app'
3
5
 
@@ -18,12 +20,14 @@ class Skippy::OSMac < Skippy::OSCommon
18
20
  Dir.glob(pattern) { |path|
19
21
  app = File.join(path, 'SketchUp.app')
20
22
  debug_lib = File.join(app, 'Contents/Frameworks/SURubyDebugger.dylib')
21
- version = File.basename(path).match(/[0-9.]+$/)[0].to_i
23
+ version = sketchup_version_from_path(path)
24
+ next unless version
25
+
22
26
  apps << Skippy::SketchUpApp.from_hash(
23
27
  executable: app,
24
28
  version: version,
25
29
  can_debug: File.exist?(debug_lib),
26
- is64bit: version > 2015,
30
+ is64bit: version > 2015
27
31
  )
28
32
  }
29
33
  apps.sort_by(&:version)
data/lib/skippy/os/win.rb CHANGED
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'skippy/os/common'
2
4
  require 'skippy/sketchup/app'
3
5
 
4
6
  class Skippy::OSWin < Skippy::OSCommon
5
7
 
6
- # Note: This is not a good indication to 32bit bs 64bit. It's a naive
8
+ # NOTE: This is not a good indication to 32bit bs 64bit. It's a naive
7
9
  # assumption that will fail when SketchUp is installed to a
8
10
  # non-standard location.
9
11
  SYSTEM_32BIT = ENV['ProgramFiles(x86)'].nil? && ENV['ProgramW6432'].nil?
@@ -28,12 +30,14 @@ class Skippy::OSWin < Skippy::OSCommon
28
30
  Dir.glob(pattern) { |path|
29
31
  exe = File.join(path, 'SketchUp.exe')
30
32
  debug_dll = File.join(path, 'SURubyDebugger.dll')
31
- version = File.basename(path).match(/[0-9.]+$/)[0].to_i
33
+ version = sketchup_version_from_path(path)
34
+ next unless version
35
+
32
36
  apps << Skippy::SketchUpApp.from_hash(
33
37
  executable: exe,
34
38
  version: version,
35
39
  can_debug: File.exist?(debug_dll),
36
- is64bit: SYSTEM_64BIT && path.start_with?("#{PROGRAM_FILES_64BIT}/"),
40
+ is64bit: SYSTEM_64BIT && path.start_with?("#{PROGRAM_FILES_64BIT}/")
37
41
  )
38
42
  }
39
43
  }
data/lib/skippy/os.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Skippy
2
4
 
3
5
  if RUBY_PLATFORM =~ /darwin/
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'json'
2
4
  require 'pathname'
3
5
 
@@ -15,7 +17,7 @@ class Skippy::Project
15
17
 
16
18
  include Skippy::Helpers::File
17
19
 
18
- PROJECT_FILENAME = 'skippy.json'.freeze
20
+ PROJECT_FILENAME = 'skippy.json'
19
21
 
20
22
  attr_reader :config
21
23
  attr_reader :libraries
@@ -36,6 +38,7 @@ class Skippy::Project
36
38
  def self.current_or_fail
37
39
  project = current
38
40
  raise ProjectNotFoundError, project.filename unless project.exist?
41
+
39
42
  project
40
43
  end
41
44
 
@@ -66,11 +69,9 @@ class Skippy::Project
66
69
 
67
70
  # @yield [filename]
68
71
  # @yieldparam [String] filename the path to custom Skippy command
69
- def command_files
72
+ def command_files(&block)
70
73
  files_pattern = File.join(path, 'skippy', '**', '*.rb')
71
- Dir.glob(files_pattern) { |filename|
72
- yield filename
73
- }
74
+ Dir.glob(files_pattern, &block)
74
75
  end
75
76
 
76
77
  # Checks if a project exist on disk. If not it's just transient.
@@ -108,8 +109,8 @@ class Skippy::Project
108
109
  end
109
110
 
110
111
  # @return [String]
111
- def to_json
112
- JSON.pretty_generate(@config)
112
+ def to_json(*args)
113
+ JSON.pretty_generate(@config, *args)
113
114
  end
114
115
 
115
116
  private
@@ -141,6 +142,7 @@ class Skippy::Project
141
142
  project_file = pathname.join(PROJECT_FILENAME)
142
143
  return pathname if project_file.exist?
143
144
  break if pathname.root?
145
+
144
146
  pathname = pathname.parent
145
147
  end
146
148
  nil
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Skippy
2
4
 
3
5
  SketchUpApp = Struct.new(:executable, :version, :can_debug, :is64bit) do
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Skippy
2
4
 
3
- VERSION = '0.4.0.a'.freeze
5
+ VERSION = '0.5.0.a'
4
6
 
5
7
  end
data/lib/skippy.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'skippy/version'
2
4
 
3
5
  module Skippy
data/skippy.gemspec CHANGED
@@ -15,7 +15,7 @@ Gem::Specification.new do |spec|
15
15
  spec.homepage = 'https://github.com/thomthom/skippy'
16
16
  spec.license = 'MIT'
17
17
 
18
- spec.required_ruby_version = '>= 2.0'
18
+ spec.required_ruby_version = '>= 2.3'
19
19
 
20
20
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
21
21
  f.match(%r{^(test|spec|features)/})
@@ -26,13 +26,10 @@ Gem::Specification.new do |spec|
26
26
 
27
27
  spec.add_dependency 'git', '~> 1.3'
28
28
  spec.add_dependency 'naturally', '~> 2.1'
29
- spec.add_dependency 'thor', '~> 0.19'
29
+ spec.add_dependency 'thor', '>= 0.19', '< 2.0'
30
30
 
31
- spec.add_development_dependency 'bundler', '~> 1.13'
32
- spec.add_development_dependency 'rake', '~> 10.0'
31
+ spec.add_development_dependency 'bundler', '>= 1.15.0', '< 3.0'
32
+ spec.add_development_dependency 'rake', '~> 12.3.3'
33
33
  spec.add_development_dependency 'minitest', '~> 5.0'
34
- # TODO(thomthom): Need to lock to 2.3 because 2.4 fails with the custom
35
- # aruba build.
36
- spec.add_development_dependency 'cucumber', '~> 2.3.0'
37
- spec.add_development_dependency 'aruba', '~> 0.14.1'
34
+ spec.add_development_dependency 'aruba', '~> 1.0'
38
35
  end