pointrb 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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