pointrb 0.0.1 → 0.1.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.
Files changed (69) hide show
  1. data/.gitignore +16 -0
  2. data/.rspec +1 -0
  3. data/.ruby-version +1 -0
  4. data/Gemfile +2 -1
  5. data/Gemfile.lock +40 -26
  6. data/README.md +1 -86
  7. data/Rakefile +5 -0
  8. data/TODO.md +35 -1
  9. data/bin/pointrb +35 -0
  10. data/cucumber.yml +3 -0
  11. data/features/create_layout.feature +96 -0
  12. data/features/create_new_project.feature +29 -0
  13. data/features/pointrb_setup.feature +22 -0
  14. data/features/step_definitions.rb +96 -0
  15. data/features/support/env.rb +26 -0
  16. data/features/support/helper.rb +62 -0
  17. data/features/test.feature +0 -0
  18. data/gemfiles/Gemfile.default +2 -1
  19. data/lib/bob_the_helper/command/command_result.rb +12 -0
  20. data/lib/bob_the_helper/command.rb +49 -0
  21. data/lib/bob_the_helper/environment.rb +27 -0
  22. data/lib/bob_the_helper/file_system/exceptions.rb +11 -0
  23. data/lib/bob_the_helper/file_system.rb +245 -0
  24. data/lib/bob_the_helper.rb +5 -0
  25. data/lib/pointrb/actions/check_if_pointrb_has_already_been_initialized.rb +15 -0
  26. data/lib/pointrb/actions/check_project_path.rb +15 -0
  27. data/lib/pointrb/actions/create_layout.rb +16 -0
  28. data/lib/pointrb/actions/create_project_wrapper.rb +15 -0
  29. data/lib/pointrb/actions/determine_layout_directory.rb +14 -0
  30. data/lib/pointrb/actions/error_handler_commandline.rb +39 -0
  31. data/lib/pointrb/actions/initialize_pointrb.rb +15 -0
  32. data/lib/pointrb/actions/retrieve_layout_files.rb +16 -0
  33. data/lib/pointrb/actions/retrieve_parsed_layout.rb +17 -0
  34. data/lib/pointrb/actions/set_project_name.rb +15 -0
  35. data/lib/pointrb/actions/show_pointrb_version.rb +14 -0
  36. data/lib/pointrb/api.rb +36 -0
  37. data/lib/pointrb/directory.rb +25 -0
  38. data/lib/pointrb/exceptions.rb +22 -0
  39. data/lib/pointrb/layout.rb +16 -0
  40. data/lib/pointrb/layout_constructor.rb +58 -0
  41. data/lib/pointrb/layout_file.rb +24 -0
  42. data/lib/pointrb/layout_manager.rb +32 -0
  43. data/lib/pointrb/layout_storage_manager.rb +40 -0
  44. data/lib/pointrb/layout_tree.rb +45 -0
  45. data/lib/pointrb/pointrb_file.rb +33 -0
  46. data/lib/pointrb/project.rb +11 -0
  47. data/lib/pointrb/version.rb +1 -1
  48. data/lib/pointrb.rb +32 -0
  49. data/pointrb.gemspec +3 -2
  50. data/script/terminal +1 -0
  51. data/spec/bob_the_helper/command/command_spec.rb +55 -0
  52. data/spec/bob_the_helper/environment/environment_spec.rb +15 -0
  53. data/spec/bob_the_helper/file_system/file_system_spec.rb +279 -0
  54. data/spec/directory/directory_spec.rb +30 -0
  55. data/spec/hooks.rb +5 -0
  56. data/spec/layout/layout_spec.rb +20 -0
  57. data/spec/layout_constructor/layout_constructor_spec.rb +122 -0
  58. data/spec/layout_file/layout_file_spec.rb +49 -0
  59. data/spec/layout_manager/layout_manager_spec.rb +47 -0
  60. data/spec/layout_storage_manager/layout_storage_manager_spec.rb +58 -0
  61. data/spec/layout_tree/layout_tree_spec.rb +70 -0
  62. data/spec/pointrb_file/pointrb_file_spec.rb +34 -0
  63. data/spec/project/project_spec.rb +19 -0
  64. data/spec/spec_helper.rb +9 -13
  65. data/spec/support/capture.rb +19 -0
  66. data/spec/support/env.rb +0 -0
  67. data/spec/support/helper.rb +8 -0
  68. data/spec/support/hooks.rb +5 -0
  69. metadata +104 -5
@@ -0,0 +1,62 @@
1
+ #encoding: utf-8
2
+ require 'bob_the_helper'
3
+
4
+
5
+ include BobTheHelper::FileSystem
6
+ include BobTheHelper::Command
7
+
8
+ def root_directory
9
+ File.expand_path('../../../', __FILE__)
10
+ end
11
+
12
+ def pointrb_config_directories
13
+ result = []
14
+ result << expand_path( File.join('~', '.config', 'pointrb' ) )
15
+ result << expand_path( File.join('~', '.config', 'pointrb', 'layouts' ) )
16
+
17
+ result
18
+ end
19
+
20
+ def run_this_command(command)
21
+ search_paths = [ File.join( root_directory, 'bin' ) , '/usr/bin', '/bin' ]
22
+
23
+ new_env_vars = {
24
+ 'HOME' => File.join(working_directory, ENV['HOME']),
25
+ 'PATH' => search_paths.join(':')
26
+ }
27
+
28
+ if @cmd_debug
29
+ runner = lambda do |cmd|
30
+ r = system(cmd)
31
+
32
+ status_klass = Class.new do
33
+ def initialize(status)
34
+ @status = status
35
+ end
36
+
37
+ def success?
38
+ @status
39
+ end
40
+ end
41
+
42
+ result = CommandResult.new
43
+ result.stderr = "Keep in mind, you're in debugging mode. Look for '@cmd_debug' in your feature files"
44
+ result.stdout = "Keep in mind, you're in debugging mode. Look for '@cmd_debug' in your feature files"
45
+ result.status = status_klass.new(r)
46
+
47
+ result
48
+ end
49
+ else
50
+ runner = lambda { |cmd| run_command(cmd) }
51
+ end
52
+
53
+ result = isolated_environment new_env_vars do
54
+
55
+ cmd_result = switch_to_working_directory do
56
+ runner.call(command)
57
+ end
58
+
59
+ cmd_result
60
+ end
61
+
62
+ end
File without changes
@@ -22,9 +22,10 @@ group :development do
22
22
  gem 'debugger'
23
23
  gem 'pry'
24
24
  gem 'pry-doc'
25
+ gem 'pry-debugger'
26
+ gem 'debugger-completion'
25
27
  gem 'awesome_print'
26
28
  gem 'travis-lint'
27
- gem 'activesupport'
28
29
  gem 'fuubar'
29
30
  gem 'churn'
30
31
  end
@@ -0,0 +1,12 @@
1
+ module BobTheHelper
2
+ module Command
3
+ class CommandResult
4
+ attr_accessor :stderr, :stdout, :status
5
+
6
+ def initialize
7
+ @stderr = ''
8
+ @stdout = ''
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,49 @@
1
+ require 'open3'
2
+
3
+ require 'bob_the_helper/environment'
4
+ require 'bob_the_helper/command/command_result'
5
+
6
+ module BobTheHelper
7
+ module Command
8
+ include Environment
9
+
10
+ # Execute command
11
+ #
12
+ # @param [String] cmd
13
+ # the command
14
+ #
15
+ # @param [Hash] options
16
+ # the options for command execution
17
+ #
18
+ # @option options [Hash] env ({])
19
+ # the environment variables for the command ('VAR' => 'CONTENT')
20
+ #
21
+ # @option options [String] stdin (nil)
22
+ # the string for stdin of the command
23
+ #
24
+ # @option options [TrueClass,FalseClass] binmode (false)
25
+ # should the stdin be read a binary or not
26
+ #
27
+ # @return [CommandResult]
28
+ # the result of the command execution
29
+ #
30
+ # @return [CommandResult]
31
+ # the result of the command execution
32
+ def run_command(cmd,options={})
33
+ opts = {
34
+ env: nil,
35
+ stdin: nil,
36
+ binmode: false,
37
+ }.merge options
38
+
39
+ env = opts[:env] || ENV.to_hash
40
+ stdin = opts[:stdin]
41
+ binmode = opts[:binmode]
42
+
43
+ result = CommandResult.new
44
+ result.stdout, result.stderr, result.status = Open3.capture3(env, cmd, stdin_data: stdin, chdir: working_directory, binmode: binmode)
45
+
46
+ result
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,27 @@
1
+ module BobTheHelper
2
+ module Environment
3
+
4
+ # Set environment variable for code block
5
+ #
6
+ # @param [Hash] variables
7
+ # the variables which should be set for that environment
8
+ #
9
+ # @yield
10
+ # the block which should be run which the change environment
11
+ def isolated_environment(variables, &block)
12
+ #backup
13
+ old_env = ENV.to_hash
14
+ #change env
15
+ ENV.update variables
16
+
17
+ block_result = block.call
18
+
19
+ #cleanup
20
+ ENV.clear
21
+ #install backuped information
22
+ ENV.update old_env
23
+
24
+ block_result
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,11 @@
1
+ module BobTheHelper
2
+ module FileSystem
3
+ module Exceptions
4
+ # Raise if path with '..' given
5
+ class InvalidPath < Exception; end
6
+
7
+ #Raised if library is not used correctly
8
+ class InvalidUsageOfLibrary < Exception; end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,245 @@
1
+ require 'fileutils'
2
+ require 'bob_the_helper/file_system/exceptions'
3
+
4
+ # helper for file system
5
+ module BobTheHelper
6
+ module FileSystem
7
+
8
+ # The root directory of the project
9
+ #
10
+ # @return [String]
11
+ # the root directory
12
+ def root_directory
13
+ #File.expand_path('../../../', __FILE__)
14
+ raise Exceptions::InvalidUsageOfLibrary , "Sorry, but you need to define the root directory yourself"
15
+ end
16
+
17
+ # The temporary directory for the project
18
+ #
19
+ # @return [String]
20
+ # the directory created for the tests
21
+ def working_directory
22
+ File.join(root_directory, 'tmp', 'test')
23
+ end
24
+
25
+ # Create temporary directory
26
+ def create_working_directory
27
+ FileUtils.mkdir_p(working_directory) unless File.exists? working_directory
28
+ end
29
+
30
+ # Delete temporary directory
31
+ def delete_working_directory
32
+ FileUtils.rm_rf(working_directory) if File.exists? working_directory
33
+ end
34
+
35
+ # Clean up test directory
36
+ def cleanup_working_directory
37
+ delete_working_directory
38
+ create_working_directory
39
+ end
40
+
41
+ # Switch the current working directory to
42
+ # the temporary one and execute code block
43
+ def switch_to_working_directory(&block)
44
+ Dir.chdir(working_directory, &block)
45
+ end
46
+
47
+ # Create directory(ies)
48
+ #
49
+ # @param [String,Array] dir
50
+ # the directories to be created, multiple arguments are possible as well
51
+ #
52
+ # @return [String,Array]
53
+ # returns a string if there was only one file given, and an array with
54
+ # muliple files
55
+ def create_directory(*dirs)
56
+ raise_if_forbidden_path_for_delete_operation(dirs)
57
+
58
+ directories = expand_path(dirs.flatten)
59
+ FileUtils.mkdir_p(directories)
60
+
61
+ if directories.size == 1
62
+ return directories.first
63
+ else
64
+ return directories
65
+ end
66
+ end
67
+
68
+ # Delete directory(ies)
69
+ #
70
+ # @param [String, Array] dir
71
+ # the directories to be deleted, multiple arguments are possible as well
72
+ #
73
+ # @return [String,Array]
74
+ # returns a string if there was only one file given, and an array with
75
+ # muliple files
76
+ def delete_directory(*dirs)
77
+ raise_if_forbidden_path_for_delete_operation(dirs)
78
+
79
+ directories = expand_path(dirs.flatten)
80
+ FileUtils.rm_r(directories)
81
+
82
+ if directories.size == 1
83
+ return directories.first
84
+ else
85
+ return directories
86
+ end
87
+ end
88
+
89
+ # Check existence of path(s)
90
+ #
91
+ # @param [String,Array] paths
92
+ # which path(s) should be checked, multiple arguments are possible as well
93
+ #
94
+ # @return [TrueClass,FalseClass]
95
+ # the result of all checks done
96
+ def path_exists?(*paths)
97
+ raise_if_forbidden_path_for_create_operation(paths)
98
+
99
+ paths_expanded = expand_path(paths.flatten)
100
+ paths_expanded.flatten.all? { |p| File.exists?(p) }
101
+ end
102
+
103
+ # Check absence of path(s)
104
+ #
105
+ # @param [String,Array] paths
106
+ # which path(s) should be checked, multiple arguments are possible as well
107
+ #
108
+ # @return [TrueClass,FalseClass]
109
+ # the result of all checks done
110
+ def path_does_not_exist?(*paths)
111
+ not path_exists?(paths)
112
+ end
113
+
114
+ # Create a single file
115
+ #
116
+ # @param [String] file_path
117
+ # the path for the new file (can include directories)
118
+ #
119
+ # @param [String] content
120
+ # the content written to the file
121
+ #
122
+ # @return [String]
123
+ # the path to the created file
124
+ def create_file(path, content='')
125
+ raise_if_forbidden_path_for_create_operation(path)
126
+
127
+ file = expand_path(path).first
128
+ directory = File.dirname(file)
129
+
130
+ FileUtils.mkdir_p(directory) unless directory == '.'
131
+ File.open(file, "wb") do |f|
132
+ f.write content
133
+ end
134
+
135
+ file
136
+ end
137
+
138
+ # Delete a single file
139
+ #
140
+ # @param [String] file_path
141
+ # the path for the new file (can include directories)
142
+ #
143
+ # @param [String] content
144
+ # the content written to the file
145
+ #
146
+ # @return [String]
147
+ # the path to the created file
148
+ def delete_file(*files)
149
+ raise_if_forbidden_path_for_delete_operation(files)
150
+
151
+ files_to_be_deleted = expand_path(files.flatten)
152
+ FileUtils.rm(files_to_be_deleted)
153
+
154
+ if files_to_be_deleted.size == 1
155
+ return files_to_be_deleted.first
156
+ else
157
+ return files_to_be_deleted
158
+ end
159
+ end
160
+
161
+ # Read the content of a file
162
+ #
163
+ # @param [String] file_path
164
+ # the path to the file
165
+ #
166
+ # @return [String,Binary]
167
+ # the content of the file
168
+ def read_file(path)
169
+ raise_if_forbidden_path_for_create_operation(path)
170
+
171
+ file_path = expand_path(path).first
172
+ return File.read(file_path)
173
+ end
174
+
175
+ # Expand path based on temporary directory
176
+ #
177
+ # @param [String, Array, Multiple Values] paths
178
+ # the paths to be expanded
179
+ #
180
+ # @return [Array, String]
181
+ # the expanded arrays
182
+ def expand_path(*paths)
183
+ raise_if_forbidden_path_for_create_operation(paths)
184
+
185
+ paths.flatten.map do |p|
186
+ case p
187
+ when /^~/
188
+ File.expand_path(p)
189
+ else
190
+ File.join(working_directory, p )
191
+ end
192
+ end
193
+ end
194
+
195
+ # Check if path is forbidden for delete operation
196
+ #
197
+ # @param [String, Array] paths
198
+ # paths which should be checked
199
+ #
200
+ # @return [TrueClass, FalseClass]
201
+ # true if path is forbidden, false if path is not forbidden
202
+ def raise_if_forbidden_path_for_create_operation(*paths)
203
+ flattend_paths = paths.flatten
204
+ strings = []
205
+ regex = %r[\.\.]
206
+
207
+ raise FileSystem::Exceptions::InvalidPath , "Sorry, but you cannot use paths matching \"#{strings.join(', ')}\" or \"#{regex.to_s}\" here!" if path_matches?(strings, regex, flattend_paths)
208
+ end
209
+
210
+ # Check if path is forbidden for delete operation
211
+ #
212
+ # @param [String, Array] paths
213
+ # paths which should be checked
214
+ #
215
+ # @return [TrueClass, FalseClass]
216
+ # true if path is forbidden, false if path is not forbidden
217
+ def raise_if_forbidden_path_for_delete_operation(*paths)
218
+ flattend_paths = paths.flatten
219
+ strings = %w[ / ]
220
+ regex = %r[\.\.]
221
+
222
+ raise FileSystem::Exceptions::InvalidPath , "Sorry, but you cannot use paths matching \"#{strings.join(', ')}\" or \"#{regex.to_s}\" here!" if path_matches?(strings, regex, flattend_paths)
223
+ end
224
+
225
+ # Check if path matches
226
+ #
227
+ # @param [Array, String] strings
228
+ # strings which are checked against paths
229
+ #
230
+ # @param [Array, String] regex
231
+ # regex which is checked against path
232
+ #
233
+ # @param [Array, String] paths
234
+ # the paths to be checked
235
+ #
236
+ # @result [TrueClass, FalseClass]
237
+ # true if path is valid, false if invalid
238
+ def path_matches?(strings, regex, *paths)
239
+ flattend_paths = paths.flatten
240
+ flattend_strings = strings.flatten
241
+
242
+ flattend_paths.any? { |f| f =~ regex or flattend_strings.include?(f) }
243
+ end
244
+ end
245
+ end
@@ -0,0 +1,5 @@
1
+ require 'bob_the_helper/environment'
2
+ require 'bob_the_helper/file_system'
3
+ require 'bob_the_helper/command'
4
+
5
+ module BobTheHelper; end
@@ -0,0 +1,15 @@
1
+ module PointRb
2
+ module Actions
3
+ class CheckIfPointRbHasAlreadyBeenInitialized
4
+ def initialize(app)
5
+ @app = app
6
+ end
7
+
8
+ def call(env)
9
+ raise Exceptions::PointRbWasAlreadInitialized , "This system has already been setup." if File.exists? env.layout_directory
10
+
11
+ @app.call(env)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module PointRb
2
+ module Actions
3
+ class CheckProjectPath
4
+ def initialize(app)
5
+ @app = app
6
+ end
7
+
8
+ def call(env)
9
+ raise PointRb::Exceptions::ProjectPathExists, "Directory '#{env.project.name}' exists." if File.exists? env.project.path
10
+
11
+ @app.call(env)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ module PointRb
2
+ module Actions
3
+ class CreateLayout
4
+ def initialize(app)
5
+ @app = app
6
+ end
7
+
8
+ def call(env)
9
+ env.layout.create
10
+ puts "[Information] Layout '#{env.layout.name}' for project '#{env.project.name}' created."
11
+
12
+ @app.call(env)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,15 @@
1
+ module PointRb
2
+ module Actions
3
+ class CreateProjectWrapper
4
+ def initialize(app)
5
+ @app = app
6
+ end
7
+
8
+ def call(env)
9
+ env.project = PointRb::Project.new(env.project_name)
10
+
11
+ @app.call(env)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,14 @@
1
+ module PointRb
2
+ module Actions
3
+ class DetermineLayoutDirectory
4
+ def initialize(app)
5
+ @app = app
6
+ end
7
+
8
+ def call(env)
9
+ env.layout_directory = File.join(ENV['HOME'], '.config', 'pointrb', 'layouts')
10
+ @app.call(env)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,39 @@
1
+ module PointRb
2
+ module Actions
3
+ class ErrorHandlerCommandline
4
+ def initialize(app)
5
+ @app = app
6
+ end
7
+
8
+ def call(env)
9
+ begin
10
+ @app.call(env)
11
+ rescue Exceptions::SyntaxErrorInLayout => e
12
+ error_msg e.message, 1
13
+ rescue Exceptions::ProjectPathExists => e
14
+ error_msg e.message, 2
15
+ rescue Exceptions::PointRbWasAlreadInitialized => e
16
+ error_msg e.message, 3
17
+ rescue Exceptions::LayoutNotFound => e
18
+ error_msg e.message, 4
19
+ rescue Exception => e
20
+
21
+ if env.command_line_options[:verbose]
22
+ message = e.message
23
+ else
24
+ message = 'An unknown error occured. If you would like to see a more verbose output, then please use the --verbose option.'
25
+ end
26
+
27
+ error_msg message, -1
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def error_msg(msg, return_code)
34
+ $stderr.puts "[Error] #{msg} Exit!"
35
+ exit return_code
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,15 @@
1
+ module PointRb
2
+ module Actions
3
+ class InitializePointRb
4
+ def initialize(app)
5
+ @app = app
6
+ end
7
+
8
+ def call(env)
9
+ FileUtils.mkdir_p env.layout_directory
10
+
11
+ @app.call(env)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ module PointRb
2
+ module Actions
3
+ class RetrieveLayoutFiles
4
+ def initialize(app)
5
+ @app = app
6
+ end
7
+
8
+ def call(env)
9
+ layout_storage_manager = PointRb::LayoutStorageManager.new(env.layout_directory)
10
+ env.layout_files = layout_storage_manager.retrieve_all
11
+
12
+ @app.call(env)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,17 @@
1
+ module PointRb
2
+ module Actions
3
+ class RetrieveParsedLayout
4
+ def initialize(app)
5
+ @app = app
6
+ end
7
+
8
+ def call(env)
9
+ layout_manager = PointRb::LayoutManager.new(env.layout_files, env.project)
10
+ layout_name = env.command_line_options[:layout].to_sym
11
+
12
+ env.layout = layout_manager.retrieve(layout_name)
13
+ @app.call(env)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ module PointRb
2
+ module Actions
3
+ class CreateProjectWrapper
4
+ def initialize(app)
5
+ @app = app
6
+ end
7
+
8
+ def call(env)
9
+ env.project = PointRb::Project.new(env.project_name)
10
+
11
+ @app.call(env)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,14 @@
1
+ module PointRb
2
+ module Actions
3
+ class ShowPointRbVersion
4
+ def initialize(app)
5
+ @app = app
6
+ end
7
+
8
+ def call(env)
9
+ puts "Version: #{PointRb::VERSION}"
10
+ @app.call(env)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,36 @@
1
+ module PointRb
2
+ class Api
3
+ def self.create_layout(env)
4
+ stack = Middleware::Builder.new do
5
+ use Actions::ErrorHandlerCommandline
6
+ use Actions::CreateProjectWrapper
7
+ use Actions::CheckProjectPath
8
+ use Actions::DetermineLayoutDirectory
9
+ use Actions::RetrieveLayoutFiles
10
+ use Actions::RetrieveParsedLayout
11
+ use Actions::CreateLayout
12
+ end
13
+
14
+ stack.call(env)
15
+ end
16
+
17
+ def self.initialize_pointrb(env)
18
+ stack = Middleware::Builder.new do
19
+ use Actions::ErrorHandlerCommandline
20
+ use Actions::DetermineLayoutDirectory
21
+ use Actions::CheckIfPointRbHasAlreadyBeenInitialized
22
+ use Actions::InitializePointRb
23
+ end
24
+
25
+ stack.call(env)
26
+ end
27
+
28
+ def self.show_version
29
+ stack = Middleware::Builder.new do
30
+ use Actions::ShowPointRbVersion
31
+ end
32
+
33
+ stack.call
34
+ end
35
+ end
36
+ end