hanami 2.0.0.alpha8 → 2.0.0.beta1

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 (224) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +442 -241
  3. data/FEATURES.md +30 -9
  4. data/README.md +1 -3
  5. data/hanami.gemspec +21 -11
  6. data/lib/hanami/app.rb +141 -0
  7. data/lib/hanami/assets/application_configuration.rb +10 -4
  8. data/lib/hanami/configuration/actions/content_security_policy.rb +5 -5
  9. data/lib/hanami/configuration/actions/cookies.rb +2 -2
  10. data/lib/hanami/configuration/actions.rb +10 -4
  11. data/lib/hanami/configuration/logger.rb +4 -4
  12. data/lib/hanami/configuration/router.rb +2 -6
  13. data/lib/hanami/configuration/sessions.rb +1 -1
  14. data/lib/hanami/configuration/views.rb +9 -4
  15. data/lib/hanami/configuration.rb +118 -46
  16. data/lib/hanami/constants.rb +24 -2
  17. data/lib/hanami/errors.rb +1 -1
  18. data/lib/hanami/{application → extensions}/action/slice_configured_action.rb +9 -9
  19. data/lib/hanami/extensions/action.rb +79 -0
  20. data/lib/hanami/extensions/view/context.rb +106 -0
  21. data/lib/hanami/{application → extensions}/view/slice_configured_context.rb +10 -10
  22. data/lib/hanami/{application → extensions}/view/slice_configured_view.rb +12 -6
  23. data/lib/hanami/extensions/view.rb +33 -0
  24. data/lib/hanami/extensions.rb +10 -0
  25. data/lib/hanami/providers/inflector.rb +13 -0
  26. data/lib/hanami/providers/logger.rb +13 -0
  27. data/lib/hanami/providers/rack.rb +27 -0
  28. data/lib/hanami/providers/routes.rb +33 -0
  29. data/lib/hanami/providers/settings.rb +23 -0
  30. data/lib/hanami/rake_tasks.rb +61 -0
  31. data/lib/hanami/routes.rb +51 -0
  32. data/lib/hanami/server.rb +1 -1
  33. data/lib/hanami/settings/dotenv_store.rb +58 -0
  34. data/lib/hanami/settings.rb +90 -0
  35. data/lib/hanami/setup.rb +4 -2
  36. data/lib/hanami/{application → slice}/router.rb +18 -13
  37. data/lib/hanami/slice/routes_helper.rb +37 -0
  38. data/lib/hanami/{application → slice}/routing/middleware/stack.rb +43 -5
  39. data/lib/hanami/slice/routing/resolver.rb +97 -0
  40. data/lib/hanami/{application → slice}/view_name_inferrer.rb +3 -3
  41. data/lib/hanami/slice.rb +246 -73
  42. data/lib/hanami/slice_configurable.rb +4 -17
  43. data/lib/hanami/slice_name.rb +6 -6
  44. data/lib/hanami/slice_registrar.rb +119 -0
  45. data/lib/hanami/version.rb +1 -1
  46. data/lib/hanami/web/rack_logger.rb +1 -1
  47. data/lib/hanami.rb +34 -26
  48. data/spec/integration/application_middleware_stack_spec.rb +84 -0
  49. data/spec/integration/assets/cdn_spec.rb +48 -0
  50. data/spec/integration/assets/fingerprint_spec.rb +42 -0
  51. data/spec/integration/assets/helpers_spec.rb +50 -0
  52. data/spec/integration/assets/serve_spec.rb +70 -0
  53. data/spec/integration/assets/subresource_integrity_spec.rb +54 -0
  54. data/spec/integration/body_parsers_spec.rb +50 -0
  55. data/spec/integration/cli/assets/precompile_spec.rb +147 -0
  56. data/spec/integration/cli/assets_spec.rb +14 -0
  57. data/spec/integration/cli/console_spec.rb +105 -0
  58. data/spec/integration/cli/db/apply_spec.rb +74 -0
  59. data/spec/integration/cli/db/console_spec.rb +40 -0
  60. data/spec/integration/cli/db/create_spec.rb +50 -0
  61. data/spec/integration/cli/db/drop_spec.rb +54 -0
  62. data/spec/integration/cli/db/migrate_spec.rb +108 -0
  63. data/spec/integration/cli/db/prepare_spec.rb +36 -0
  64. data/spec/integration/cli/db/rollback_spec.rb +96 -0
  65. data/spec/integration/cli/db/version_spec.rb +38 -0
  66. data/spec/integration/cli/db_spec.rb +21 -0
  67. data/spec/integration/cli/destroy/action_spec.rb +143 -0
  68. data/spec/integration/cli/destroy/app_spec.rb +118 -0
  69. data/spec/integration/cli/destroy/mailer_spec.rb +74 -0
  70. data/spec/integration/cli/destroy/migration_spec.rb +70 -0
  71. data/spec/integration/cli/destroy/model_spec.rb +113 -0
  72. data/spec/integration/cli/destroy_spec.rb +18 -0
  73. data/spec/integration/cli/generate/action_spec.rb +469 -0
  74. data/spec/integration/cli/generate/app_spec.rb +215 -0
  75. data/spec/integration/cli/generate/mailer_spec.rb +189 -0
  76. data/spec/integration/cli/generate/migration_spec.rb +72 -0
  77. data/spec/integration/cli/generate/model_spec.rb +290 -0
  78. data/spec/integration/cli/generate/secret_spec.rb +56 -0
  79. data/spec/integration/cli/generate_spec.rb +19 -0
  80. data/spec/integration/cli/new/database_spec.rb +235 -0
  81. data/spec/integration/cli/new/hanami_head_spec.rb +27 -0
  82. data/spec/integration/cli/new/template_spec.rb +118 -0
  83. data/spec/integration/cli/new/test_spec.rb +274 -0
  84. data/spec/integration/cli/new_spec.rb +970 -0
  85. data/spec/integration/cli/plugins_spec.rb +39 -0
  86. data/spec/integration/cli/routes_spec.rb +49 -0
  87. data/spec/integration/cli/server_spec.rb +626 -0
  88. data/spec/integration/cli/version_spec.rb +85 -0
  89. data/spec/integration/early_hints_spec.rb +35 -0
  90. data/spec/integration/handle_exceptions_spec.rb +244 -0
  91. data/spec/integration/head_spec.rb +89 -0
  92. data/spec/integration/http_headers_spec.rb +29 -0
  93. data/spec/integration/mailer_spec.rb +32 -0
  94. data/spec/integration/middleware_spec.rb +81 -0
  95. data/spec/integration/mount_applications_spec.rb +88 -0
  96. data/spec/integration/project_initializers_spec.rb +40 -0
  97. data/spec/integration/rackup_spec.rb +35 -0
  98. data/spec/integration/rake/with_minitest_spec.rb +67 -0
  99. data/spec/integration/rake/with_rspec_spec.rb +69 -0
  100. data/spec/integration/routing_helpers_spec.rb +61 -0
  101. data/spec/integration/security/content_security_policy_spec.rb +46 -0
  102. data/spec/integration/security/csrf_protection_spec.rb +42 -0
  103. data/spec/integration/security/force_ssl_spec.rb +29 -0
  104. data/spec/integration/security/x_content_type_options_spec.rb +46 -0
  105. data/spec/integration/security/x_frame_options_spec.rb +46 -0
  106. data/spec/integration/security/x_xss_protection_spec.rb +46 -0
  107. data/spec/integration/send_file_spec.rb +51 -0
  108. data/spec/integration/sessions_spec.rb +247 -0
  109. data/spec/integration/static_middleware_spec.rb +21 -0
  110. data/spec/integration/streaming_spec.rb +41 -0
  111. data/spec/integration/unsafe_send_file_spec.rb +52 -0
  112. data/spec/isolation/hanami/application/already_configured_spec.rb +19 -0
  113. data/spec/isolation/hanami/application/inherit_anonymous_class_spec.rb +10 -0
  114. data/spec/isolation/hanami/application/inherit_concrete_class_spec.rb +14 -0
  115. data/spec/isolation/hanami/application/not_configured_spec.rb +9 -0
  116. data/spec/isolation/hanami/application/routes/configured_spec.rb +44 -0
  117. data/spec/isolation/hanami/application/routes/not_configured_spec.rb +16 -0
  118. data/spec/isolation/hanami/boot/success_spec.rb +50 -0
  119. data/spec/new_integration/action/configuration_spec.rb +26 -0
  120. data/spec/new_integration/action/cookies_spec.rb +58 -0
  121. data/spec/new_integration/action/csrf_protection_spec.rb +54 -0
  122. data/spec/new_integration/action/routes_spec.rb +73 -0
  123. data/spec/new_integration/action/sessions_spec.rb +50 -0
  124. data/spec/new_integration/action/view_integration_spec.rb +165 -0
  125. data/spec/new_integration/action/view_rendering/automatic_rendering_spec.rb +247 -0
  126. data/spec/new_integration/action/view_rendering/paired_view_inference_spec.rb +115 -0
  127. data/spec/new_integration/action/view_rendering_spec.rb +107 -0
  128. data/spec/new_integration/code_loading/loading_from_app_spec.rb +152 -0
  129. data/spec/new_integration/code_loading/loading_from_slice_spec.rb +165 -0
  130. data/spec/new_integration/container/application_routes_helper_spec.rb +48 -0
  131. data/spec/new_integration/container/auto_injection_spec.rb +53 -0
  132. data/spec/new_integration/container/auto_registration_spec.rb +86 -0
  133. data/spec/new_integration/container/autoloader_spec.rb +80 -0
  134. data/spec/new_integration/container/imports_spec.rb +253 -0
  135. data/spec/new_integration/container/prepare_container_spec.rb +123 -0
  136. data/spec/new_integration/container/shutdown_spec.rb +91 -0
  137. data/spec/new_integration/container/standard_bootable_components_spec.rb +124 -0
  138. data/spec/new_integration/rack_app/middleware_spec.rb +215 -0
  139. data/spec/new_integration/rack_app/non_booted_rack_app_spec.rb +105 -0
  140. data/spec/new_integration/rack_app/rack_app_spec.rb +524 -0
  141. data/spec/new_integration/settings_spec.rb +115 -0
  142. data/spec/new_integration/slices/external_slice_spec.rb +92 -0
  143. data/spec/new_integration/slices/slice_configuration_spec.rb +40 -0
  144. data/spec/new_integration/slices/slice_routing_spec.rb +226 -0
  145. data/spec/new_integration/slices/slice_settings_spec.rb +141 -0
  146. data/spec/new_integration/slices_spec.rb +101 -0
  147. data/spec/new_integration/view/configuration_spec.rb +49 -0
  148. data/spec/new_integration/view/context/assets_spec.rb +67 -0
  149. data/spec/new_integration/view/context/inflector_spec.rb +48 -0
  150. data/spec/new_integration/view/context/request_spec.rb +61 -0
  151. data/spec/new_integration/view/context/routes_spec.rb +86 -0
  152. data/spec/new_integration/view/context/settings_spec.rb +50 -0
  153. data/spec/new_integration/view/inflector_spec.rb +57 -0
  154. data/spec/new_integration/view/part_namespace_spec.rb +96 -0
  155. data/spec/new_integration/view/path_spec.rb +56 -0
  156. data/spec/new_integration/view/template_spec.rb +68 -0
  157. data/spec/new_integration/view/views_spec.rb +103 -0
  158. data/spec/spec_helper.rb +16 -0
  159. data/spec/support/app_integration.rb +91 -0
  160. data/spec/support/coverage.rb +1 -0
  161. data/spec/support/fixtures/hanami-plugin/Gemfile +8 -0
  162. data/spec/support/fixtures/hanami-plugin/README.md +35 -0
  163. data/spec/support/fixtures/hanami-plugin/Rakefile +4 -0
  164. data/spec/support/fixtures/hanami-plugin/bin/console +15 -0
  165. data/spec/support/fixtures/hanami-plugin/bin/setup +8 -0
  166. data/spec/support/fixtures/hanami-plugin/hanami-plugin.gemspec +28 -0
  167. data/spec/support/fixtures/hanami-plugin/lib/hanami/plugin/cli.rb +19 -0
  168. data/spec/support/fixtures/hanami-plugin/lib/hanami/plugin/version.rb +7 -0
  169. data/spec/support/fixtures/hanami-plugin/lib/hanami/plugin.rb +8 -0
  170. data/spec/support/rspec.rb +27 -0
  171. data/spec/support/shared_examples/cli/generate/app.rb +494 -0
  172. data/spec/support/shared_examples/cli/generate/migration.rb +32 -0
  173. data/spec/support/shared_examples/cli/generate/model.rb +81 -0
  174. data/spec/support/shared_examples/cli/new.rb +97 -0
  175. data/spec/unit/hanami/configuration/actions/content_security_policy_spec.rb +102 -0
  176. data/spec/unit/hanami/configuration/actions/cookies_spec.rb +46 -0
  177. data/spec/unit/hanami/configuration/actions/csrf_protection_spec.rb +57 -0
  178. data/spec/unit/hanami/configuration/actions/default_values_spec.rb +52 -0
  179. data/spec/unit/hanami/configuration/actions/sessions_spec.rb +50 -0
  180. data/spec/unit/hanami/configuration/actions_spec.rb +78 -0
  181. data/spec/unit/hanami/configuration/base_url_spec.rb +25 -0
  182. data/spec/unit/hanami/configuration/inflector_spec.rb +35 -0
  183. data/spec/unit/hanami/configuration/logger_spec.rb +203 -0
  184. data/spec/unit/hanami/configuration/views_spec.rb +120 -0
  185. data/spec/unit/hanami/configuration_spec.rb +43 -0
  186. data/spec/unit/hanami/env_spec.rb +54 -0
  187. data/spec/unit/hanami/routes_spec.rb +25 -0
  188. data/spec/unit/hanami/settings/dotenv_store_spec.rb +119 -0
  189. data/spec/unit/hanami/settings_spec.rb +56 -0
  190. data/spec/unit/hanami/slice_configurable_spec.rb +104 -0
  191. data/spec/unit/hanami/slice_name_spec.rb +47 -0
  192. data/spec/unit/hanami/slice_spec.rb +17 -0
  193. data/spec/unit/hanami/version_spec.rb +7 -0
  194. data/spec/unit/hanami/web/rack_logger_spec.rb +78 -0
  195. metadata +353 -57
  196. data/lib/hanami/application/action.rb +0 -72
  197. data/lib/hanami/application/container/providers/inflector.rb +0 -7
  198. data/lib/hanami/application/container/providers/logger.rb +0 -7
  199. data/lib/hanami/application/container/providers/rack_logger.rb +0 -15
  200. data/lib/hanami/application/container/providers/rack_monitor.rb +0 -12
  201. data/lib/hanami/application/container/providers/routes_helper.rb +0 -9
  202. data/lib/hanami/application/container/providers/settings.rb +0 -7
  203. data/lib/hanami/application/routes.rb +0 -55
  204. data/lib/hanami/application/routes_helper.rb +0 -34
  205. data/lib/hanami/application/routing/resolver/node.rb +0 -50
  206. data/lib/hanami/application/routing/resolver/trie.rb +0 -59
  207. data/lib/hanami/application/routing/resolver.rb +0 -87
  208. data/lib/hanami/application/routing/router.rb +0 -36
  209. data/lib/hanami/application/settings/dotenv_store.rb +0 -60
  210. data/lib/hanami/application/settings.rb +0 -93
  211. data/lib/hanami/application/slice_registrar.rb +0 -106
  212. data/lib/hanami/application/view/context.rb +0 -95
  213. data/lib/hanami/application/view.rb +0 -24
  214. data/lib/hanami/application.rb +0 -273
  215. data/lib/hanami/cli/application/cli.rb +0 -40
  216. data/lib/hanami/cli/application/command.rb +0 -47
  217. data/lib/hanami/cli/application/commands/console.rb +0 -81
  218. data/lib/hanami/cli/application/commands.rb +0 -16
  219. data/lib/hanami/cli/base_command.rb +0 -48
  220. data/lib/hanami/cli/commands/command.rb +0 -171
  221. data/lib/hanami/cli/commands/server.rb +0 -88
  222. data/lib/hanami/cli/commands.rb +0 -65
  223. data/lib/hanami/configuration/middleware.rb +0 -20
  224. data/lib/hanami/configuration/source_dirs.rb +0 -42
@@ -0,0 +1,970 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe "hanami new", type: :integration do
4
+ it "generates vanilla project" do
5
+ project = "bookshelf"
6
+ output = <<-OUT
7
+ create .hanamirc
8
+ create .env.development
9
+ create .env.test
10
+ create README.md
11
+ create Gemfile
12
+ create config.ru
13
+ create config/boot.rb
14
+ create config/environment.rb
15
+ create lib/#{project}.rb
16
+ create public/.gitkeep
17
+ create config/initializers/.gitkeep
18
+ create lib/#{project}/entities/.gitkeep
19
+ create lib/#{project}/repositories/.gitkeep
20
+ create lib/#{project}/mailers/.gitkeep
21
+ create lib/#{project}/mailers/templates/.gitkeep
22
+ create spec/#{project}/entities/.gitkeep
23
+ create spec/#{project}/repositories/.gitkeep
24
+ create spec/#{project}/mailers/.gitkeep
25
+ create spec/support/.gitkeep
26
+ create db/migrations/.gitkeep
27
+ create Rakefile
28
+ create .rspec
29
+ create spec/spec_helper.rb
30
+ create spec/features_helper.rb
31
+ create spec/support/capybara.rb
32
+ create db/schema.sql
33
+ create .gitignore
34
+ run git init . from "."
35
+ create apps/web/app.rb
36
+ create apps/web/config/routes.rb
37
+ create apps/web/views/app_layout.rb
38
+ create apps/web/templates/app.html.erb
39
+ create apps/web/assets/favicon.ico
40
+ create apps/web/controllers/.gitkeep
41
+ create apps/web/assets/images/.gitkeep
42
+ create apps/web/assets/javascripts/.gitkeep
43
+ create apps/web/assets/stylesheets/.gitkeep
44
+ create spec/web/features/.gitkeep
45
+ create spec/web/controllers/.gitkeep
46
+ create spec/web/views/app_layout_spec.rb
47
+ insert config/environment.rb
48
+ insert config/environment.rb
49
+ append .env.development
50
+ append .env.test
51
+ OUT
52
+
53
+ run_cmd "hanami new #{project}", output
54
+
55
+ within_project_directory(project) do
56
+ # Assert it's an initialized Git repository
57
+ run_cmd "git status", default_git_branch
58
+
59
+ #
60
+ # .hanamirc
61
+ #
62
+ expect(".hanamirc").to have_file_content <<~END
63
+ project=#{project}
64
+ test=rspec
65
+ template=erb
66
+ END
67
+
68
+ #
69
+ # .env.development
70
+ #
71
+ expect(".env.development").to have_file_content(%r{# Define ENV variables for development environment})
72
+ expect(".env.development").to have_file_content(%r{DATABASE_URL="sqlite://db/#{project}_development.sqlite"})
73
+ expect(".env.development").to have_file_content(%r{SERVE_STATIC_ASSETS="true"})
74
+ expect(".env.development").to have_file_content(%r{WEB_SESSIONS_SECRET="[\w]{64}"})
75
+
76
+ #
77
+ # .env.test
78
+ #
79
+ expect(".env.test").to have_file_content(%r{# Define ENV variables for test environment})
80
+ expect(".env.test").to have_file_content(%r{DATABASE_URL="sqlite://db/#{project}_test.sqlite"})
81
+ expect(".env.test").to have_file_content(%r{SERVE_STATIC_ASSETS="true"})
82
+ expect(".env.test").to have_file_content(%r{WEB_SESSIONS_SECRET="[\w]{64}"})
83
+
84
+ #
85
+ # README.md
86
+ #
87
+ expect("README.md").to have_file_content <<~END
88
+ # Bookshelf
89
+
90
+ Welcome to your new Hanami project!
91
+
92
+ ## Setup
93
+
94
+ How to run tests:
95
+
96
+ ```
97
+ % bundle exec rake
98
+ ```
99
+
100
+ How to run the development console:
101
+
102
+ ```
103
+ % bundle exec hanami console
104
+ ```
105
+
106
+ How to run the development server:
107
+
108
+ ```
109
+ % bundle exec hanami server
110
+ ```
111
+
112
+ How to prepare (create and migrate) DB for `development` and `test` environments:
113
+
114
+ ```
115
+ % bundle exec hanami db prepare
116
+
117
+ % HANAMI_ENV=test bundle exec hanami db prepare
118
+ ```
119
+
120
+ Explore Hanami [guides](https://guides.hanamirb.org/), [API docs](http://docs.hanamirb.org/#{Hanami::VERSION}/), or jump in [chat](http://chat.hanamirb.org) for help. Enjoy! 🌸
121
+ END
122
+
123
+ #
124
+ # Gemfile
125
+ #
126
+ if Platform.match?(engine: :ruby)
127
+ expect('Gemfile').to have_file_content <<-END
128
+ source 'https://rubygems.org'
129
+
130
+ gem 'rake'
131
+ gem 'hanami', '#{Hanami::Version.gem_requirement}'
132
+ gem 'hanami-model', '~> 1.3'
133
+
134
+ gem 'sqlite3'
135
+
136
+ group :development do
137
+ # Code reloading
138
+ # See: https://guides.hanamirb.org/projects/code-reloading
139
+ gem 'shotgun', platforms: :ruby
140
+ gem 'hanami-webconsole'
141
+ end
142
+
143
+ group :test, :development do
144
+ gem 'dotenv', '~> 2.4'
145
+ end
146
+
147
+ group :test do
148
+ gem 'rspec'
149
+ gem 'capybara'
150
+ end
151
+
152
+ group :production do
153
+ # gem 'puma'
154
+ end
155
+ END
156
+ end
157
+
158
+ if Platform.match?(engine: :jruby)
159
+ expect("Gemfile").to have_file_content <<~END
160
+ source 'https://rubygems.org'
161
+
162
+ gem 'rake'
163
+ gem 'hanami', '#{Hanami::Version.gem_requirement}'
164
+ gem 'hanami-model', '~> 1.3'
165
+
166
+ gem 'jdbc-sqlite3'
167
+
168
+ group :test, :development do
169
+ gem 'dotenv', '~> 2.4'
170
+ end
171
+
172
+ group :test do
173
+ gem 'rspec'
174
+ gem 'capybara'
175
+ end
176
+
177
+ group :production do
178
+ # gem 'puma'
179
+ end
180
+ END
181
+ end
182
+
183
+ #
184
+ # config.ru
185
+ #
186
+ expect('config.ru').to have_file_content <<-END
187
+ require_relative 'config/environment'
188
+
189
+ run Hanami.app
190
+ END
191
+
192
+ #
193
+ # config/boot.rb
194
+ #
195
+ expect("config/boot.rb").to have_file_content <<~END
196
+ require_relative './environment'
197
+ Hanami.boot
198
+ END
199
+
200
+ #
201
+ # config/environment.rb
202
+ #
203
+ expect('config/environment.rb').to have_file_content <<-END
204
+ require 'bundler/setup'
205
+ require 'hanami/setup'
206
+ require 'hanami/model'
207
+ require_relative '../lib/#{project}'
208
+ require_relative '../apps/web/app'
209
+
210
+ Hanami.configure do
211
+ mount Web::App, at: '/'
212
+
213
+ model do
214
+ ##
215
+ # Database adapter
216
+ #
217
+ # Available options:
218
+ #
219
+ # * SQL adapter
220
+ # adapter :sql, 'sqlite://db/#{project}_development.sqlite3'
221
+ # adapter :sql, 'postgresql://localhost/#{project}_development'
222
+ # adapter :sql, 'mysql://localhost/#{project}_development'
223
+ #
224
+ adapter :sql, ENV.fetch('DATABASE_URL')
225
+
226
+ ##
227
+ # Migrations
228
+ #
229
+ migrations 'db/migrations'
230
+ schema 'db/schema.sql'
231
+ end
232
+
233
+ mailer do
234
+ root 'lib/#{project}/mailers'
235
+
236
+ # See https://guides.hanamirb.org/mailers/delivery
237
+ delivery :test
238
+ end
239
+
240
+ environment :development do
241
+ # See: https://guides.hanamirb.org/projects/logging
242
+ logger level: :debug
243
+ end
244
+
245
+ environment :production do
246
+ logger level: :info, formatter: :json, filter: []
247
+
248
+ mailer do
249
+ delivery :smtp, address: ENV.fetch('SMTP_HOST'), port: ENV.fetch('SMTP_PORT')
250
+ end
251
+ end
252
+ end
253
+ END
254
+
255
+ project_module = Hanami::Utils::String.new(project).classify
256
+ #
257
+ # lib/<project>.rb
258
+ #
259
+ expect("lib/#{project}.rb").to have_file_content <<~END
260
+ module #{project_module}
261
+ end
262
+ END
263
+
264
+ #
265
+ # public/.gitkeep
266
+ #
267
+ expect("public/.gitkeep").to be_an_existing_file
268
+
269
+ #
270
+ # config/initializers/.gitkeep
271
+ #
272
+ expect("config/initializers/.gitkeep").to be_an_existing_file
273
+
274
+ #
275
+ # lib/<project>/entities/.gitkeep
276
+ #
277
+ expect("lib/#{project}/entities/.gitkeep").to be_an_existing_file
278
+
279
+ #
280
+ # lib/<project>/mailers/.gitkeep
281
+ #
282
+ expect("lib/#{project}/mailers/.gitkeep").to be_an_existing_file
283
+
284
+ #
285
+ # lib/<project>/mailers/templates/.gitkeep
286
+ #
287
+ expect("lib/#{project}/mailers/templates/.gitkeep").to be_an_existing_file
288
+
289
+ #
290
+ # spec/<project>/entities/.gitkeep
291
+ #
292
+ expect("spec/#{project}/entities/.gitkeep").to be_an_existing_file
293
+
294
+ #
295
+ # spec/<project>/repositories/.gitkeep
296
+ #
297
+ expect("spec/#{project}/repositories/.gitkeep").to be_an_existing_file
298
+
299
+ #
300
+ # spec/<project>/mailers/.gitkeep
301
+ #
302
+ expect("spec/#{project}/mailers/.gitkeep").to be_an_existing_file
303
+
304
+ #
305
+ # spec/support/.gitkeep
306
+ #
307
+ expect("spec/support/.gitkeep").to be_an_existing_file
308
+
309
+ #
310
+ # Rakefile
311
+ #
312
+ expect("Rakefile").to have_file_content <<~END
313
+ require 'rake'
314
+ require 'hanami/rake_tasks'
315
+
316
+ begin
317
+ require 'rspec/core/rake_task'
318
+ RSpec::Core::RakeTask.new(:spec)
319
+ task default: :spec
320
+ rescue LoadError
321
+ end
322
+ END
323
+
324
+ #
325
+ # spec/spec_helper.rb
326
+ #
327
+ expect("spec/spec_helper.rb").to have_file_content <<~END
328
+ # Require this file for unit tests
329
+ ENV['HANAMI_ENV'] ||= 'test'
330
+
331
+ require_relative '../config/environment'
332
+ Hanami.boot
333
+ Hanami::Utils.require!("\#{__dir__}/support")
334
+
335
+ # This file was generated by the `rspec --init` command. Conventionally, all
336
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
337
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
338
+ # this file to always be loaded, without a need to explicitly require it in any
339
+ # files.
340
+ #
341
+ # Given that it is always loaded, you are encouraged to keep this file as
342
+ # light-weight as possible. Requiring heavyweight dependencies from this file
343
+ # will add to the boot time of your test suite on EVERY test run, even for an
344
+ # individual file that may not need all of that loaded. Instead, consider making
345
+ # a separate helper file that requires the additional dependencies and performs
346
+ # the additional setup, and require it from the spec files that actually need
347
+ # it.
348
+ #
349
+ # The `.rspec` file also contains a few flags that are not defaults but that
350
+ # users commonly want.
351
+ #
352
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
353
+ RSpec.configure do |config|
354
+ # rspec-expectations config goes here. You can use an alternate
355
+ # assertion/expectation library such as wrong or the stdlib/minitest
356
+ # assertions if you prefer.
357
+ config.expect_with :rspec do |expectations|
358
+ # This option will default to `true` in RSpec 4. It makes the `description`
359
+ # and `failure_message` of custom matchers include text for helper methods
360
+ # defined using `chain`, e.g.:
361
+ # be_bigger_than(2).and_smaller_than(4).description
362
+ # # => "be bigger than 2 and smaller than 4"
363
+ # ...rather than:
364
+ # # => "be bigger than 2"
365
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
366
+ end
367
+
368
+ # rspec-mocks config goes here. You can use an alternate test double
369
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
370
+ config.mock_with :rspec do |mocks|
371
+ # Prevents you from mocking or stubbing a method that does not exist on
372
+ # a real object. This is generally recommended, and will default to
373
+ # `true` in RSpec 4.
374
+ mocks.verify_partial_doubles = true
375
+ end
376
+
377
+ # The settings below are suggested to provide a good initial experience
378
+ # with RSpec, but feel free to customize to your heart's content.
379
+ =begin
380
+ # These two settings work together to allow you to limit a spec run
381
+ # to individual examples or groups you care about by tagging them with
382
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
383
+ # get run.
384
+ config.filter_run :focus
385
+ config.run_all_when_everything_filtered = true
386
+
387
+ # Allows RSpec to persist some state between runs in order to support
388
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
389
+ # you configure your source control system to ignore this file.
390
+ config.example_status_persistence_file_path = "spec/examples.txt"
391
+
392
+ # Limits the available syntax to the non-monkey patched syntax that is
393
+ # recommended. For more details, see:
394
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
395
+ # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
396
+ # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
397
+ config.disable_monkey_patching!
398
+
399
+ # This setting enables warnings. It's recommended, but in many cases may
400
+ # be too noisy due to issues in dependencies.
401
+ config.warnings = false
402
+
403
+ # Many RSpec users commonly either run the entire suite or an individual
404
+ # file, and it's useful to allow more verbose output when running an
405
+ # individual spec file.
406
+ if config.files_to_run.one?
407
+ # Use the documentation formatter for detailed output,
408
+ # unless a formatter has already been configured
409
+ # (e.g. via a command-line flag).
410
+ config.default_formatter = 'doc'
411
+ end
412
+
413
+ # Print the 10 slowest examples and example groups at the
414
+ # end of the spec run, to help surface which specs are running
415
+ # particularly slow.
416
+ config.profile_examples = 10
417
+
418
+ # Run specs in random order to surface order dependencies. If you find an
419
+ # order dependency and want to debug it, you can fix the order by providing
420
+ # the seed, which is printed after each run.
421
+ # --seed 1234
422
+ config.order = :random
423
+
424
+ # Seed global randomization in this process using the `--seed` CLI option.
425
+ # Setting this allows you to use `--seed` to deterministically reproduce
426
+ # test failures related to randomization by passing the same `--seed` value
427
+ # as the one that triggered the failure.
428
+ Kernel.srand config.seed
429
+ =end
430
+ end
431
+ END
432
+
433
+ #
434
+ # spec/features_helper.rb
435
+ #
436
+ expect("spec/features_helper.rb").to have_file_content <<~END
437
+ # Require this file for feature tests
438
+ require_relative './spec_helper'
439
+
440
+ require 'capybara'
441
+ require 'capybara/rspec'
442
+
443
+ RSpec.configure do |config|
444
+ config.include RSpec::FeatureExampleGroup
445
+
446
+ config.include Capybara::DSL, feature: true
447
+ config.include Capybara::RSpecMatchers, feature: true
448
+ end
449
+ END
450
+
451
+ #
452
+ # .gitignore
453
+ #
454
+ expect(".gitignore").to have_file_content <<-END
455
+ /db/*.sqlite
456
+ /public/assets*
457
+ /tmp
458
+ .env.local
459
+ .env.*.local
460
+ END
461
+
462
+ #
463
+ # apps/web/app.rb
464
+ #
465
+ expect("apps/web/app.rb").to have_file_content <<-END
466
+ require 'hanami/helpers'
467
+ require 'hanami/assets'
468
+
469
+ module Web
470
+ class App < Hanami::App
471
+ configure do
472
+ ##
473
+ # BASIC
474
+ #
475
+
476
+ # Define the root path of this app.
477
+ # All paths specified in this configuration are relative to path below.
478
+ #
479
+ root __dir__
480
+
481
+ # Relative load paths where this app will recursively load the
482
+ # code.
483
+ #
484
+ # When you add new directories, remember to add them here.
485
+ #
486
+ load_paths << [
487
+ 'controllers',
488
+ 'views'
489
+ ]
490
+
491
+ # Handle exceptions with HTTP statuses (true) or don't catch them (false).
492
+ # Defaults to true.
493
+ # See: http://www.rubydoc.info/gems/hanami-controller/#Exceptions_management
494
+ #
495
+ # handle_exceptions true
496
+
497
+ ##
498
+ # HTTP
499
+ #
500
+
501
+ # Routes definitions for this app
502
+ # See: http://www.rubydoc.info/gems/hanami-router#Usage
503
+ #
504
+ routes 'config/routes'
505
+
506
+ # URI scheme used by the routing system to generate absolute URLs
507
+ # Defaults to "http"
508
+ #
509
+ # scheme 'https'
510
+
511
+ # URI host used by the routing system to generate absolute URLs
512
+ # Defaults to "localhost"
513
+ #
514
+ # host 'example.org'
515
+
516
+ # URI port used by the routing system to generate absolute URLs
517
+ # Argument: An object coercible to integer, defaults to 80 if the scheme
518
+ # is http and 443 if it's https
519
+ #
520
+ # This should only be configured if app listens to non-standard ports
521
+ #
522
+ # port 443
523
+
524
+ # Enable cookies
525
+ # Argument: boolean to toggle the feature
526
+ # A Hash with options
527
+ #
528
+ # Options:
529
+ # :domain - The domain (String - nil by default, not required)
530
+ # :path - Restrict cookies to a relative URI
531
+ # (String - nil by default)
532
+ # :max_age - Cookies expiration expressed in seconds
533
+ # (Integer - nil by default)
534
+ # :secure - Restrict cookies to secure connections
535
+ # (Boolean - Automatically true when using HTTPS)
536
+ # See #scheme and #ssl?
537
+ # :httponly - Prevent JavaScript access (Boolean - true by default)
538
+ #
539
+ # cookies true
540
+ # or
541
+ # cookies max_age: 300
542
+
543
+ # Enable sessions
544
+ # Argument: Symbol the Rack session adapter
545
+ # A Hash with options
546
+ #
547
+ # See: http://www.rubydoc.info/gems/rack/Rack/Session/Cookie
548
+ #
549
+ # sessions :cookie, secret: ENV['WEB_SESSIONS_SECRET']
550
+
551
+ # Configure Rack middleware for this app
552
+ #
553
+ # middleware.use Rack::Protection
554
+
555
+ # Default format for the requests that don't specify an HTTP_ACCEPT header
556
+ # Argument: A symbol representation of a mime type, defaults to :html
557
+ #
558
+ # default_request_format :html
559
+
560
+ # Default format for responses that don't consider the request format
561
+ # Argument: A symbol representation of a mime type, defaults to :html
562
+ #
563
+ # default_response_format :html
564
+
565
+ ##
566
+ # TEMPLATES
567
+ #
568
+
569
+ # The layout to be used by all views
570
+ #
571
+ layout :app # It will load Web::Views::AppLayout
572
+
573
+ # The relative path to templates
574
+ #
575
+ templates 'templates'
576
+
577
+ ##
578
+ # ASSETS
579
+ #
580
+ assets do
581
+ # JavaScript compressor
582
+ #
583
+ # Supported engines:
584
+ #
585
+ # * :builtin
586
+ # * :uglifier
587
+ # * :yui
588
+ # * :closure
589
+ #
590
+ # See: https://guides.hanamirb.org/assets/compressors
591
+ #
592
+ # In order to skip JavaScript compression comment the following line
593
+ javascript_compressor :builtin
594
+
595
+ # Stylesheet compressor
596
+ #
597
+ # Supported engines:
598
+ #
599
+ # * :builtin
600
+ # * :yui
601
+ # * :sass
602
+ #
603
+ # See: https://guides.hanamirb.org/assets/compressors
604
+ #
605
+ # In order to skip stylesheet compression comment the following line
606
+ stylesheet_compressor :builtin
607
+
608
+ # Specify sources for assets
609
+ #
610
+ sources << [
611
+ 'assets'
612
+ ]
613
+ end
614
+
615
+ ##
616
+ # SECURITY
617
+ #
618
+
619
+ # X-Frame-Options is a HTTP header supported by modern browsers.
620
+ # It determines if a web page can or cannot be included via <frame> and
621
+ # <iframe> tags by untrusted domains.
622
+ #
623
+ # Web apps can send this header to prevent Clickjacking attacks.
624
+ #
625
+ # Read more at:
626
+ #
627
+ # * https://developer.mozilla.org/en-US/docs/Web/HTTP/X-Frame-Options
628
+ # * https://www.owasp.org/index.php/Clickjacking
629
+ #
630
+ security.x_frame_options 'DENY'
631
+
632
+ # X-Content-Type-Options prevents browsers from interpreting files as
633
+ # something else than declared by the content type in the HTTP headers.
634
+ #
635
+ # Read more at:
636
+ #
637
+ # * https://www.owasp.org/index.php/OWASP_Secure_Headers_Project#X-Content-Type-Options
638
+ # * https://msdn.microsoft.com/en-us/library/gg622941%28v=vs.85%29.aspx
639
+ # * https://blogs.msdn.microsoft.com/ie/2008/09/02/ie8-security-part-vi-beta-2-update
640
+ #
641
+ security.x_content_type_options 'nosniff'
642
+
643
+ # X-XSS-Protection is a HTTP header to determine the behavior of the
644
+ # browser in case an XSS attack is detected.
645
+ #
646
+ # Read more at:
647
+ #
648
+ # * https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)
649
+ # * https://www.owasp.org/index.php/OWASP_Secure_Headers_Project#X-XSS-Protection
650
+ #
651
+ security.x_xss_protection '1; mode=block'
652
+
653
+ # Content-Security-Policy (CSP) is a HTTP header supported by modern
654
+ # browsers. It determines trusted sources of execution for dynamic
655
+ # contents (JavaScript) or other web related assets: stylesheets, images,
656
+ # fonts, plugins, etc.
657
+ #
658
+ # Web apps can send this header to mitigate Cross Site Scripting
659
+ # (XSS) attacks.
660
+ #
661
+ # The default value allows images, scripts, AJAX, fonts and CSS from the
662
+ # same origin, and does not allow any other resources to load (eg object,
663
+ # frame, media, etc).
664
+ #
665
+ # Inline JavaScript is NOT allowed. To enable it, please use:
666
+ # "script-src 'unsafe-inline'".
667
+ #
668
+ # Content Security Policy introduction:
669
+ #
670
+ # * http://www.html5rocks.com/en/tutorials/security/content-security-policy/
671
+ # * https://www.owasp.org/index.php/Content_Security_Policy
672
+ # * https://www.owasp.org/index.php/Cross-site_Scripting_%28XSS%29
673
+ #
674
+ # Inline and eval JavaScript risks:
675
+ #
676
+ # * http://www.html5rocks.com/en/tutorials/security/content-security-policy/#inline-code-considered-harmful
677
+ # * http://www.html5rocks.com/en/tutorials/security/content-security-policy/#eval-too
678
+ #
679
+ # Content Security Policy usage:
680
+ #
681
+ # * http://content-security-policy.com/
682
+ # * https://developer.mozilla.org/en-US/docs/Web/Security/CSP/Using_Content_Security_Policy
683
+ #
684
+ # Content Security Policy references:
685
+ #
686
+ # * https://developer.mozilla.org/en-US/docs/Web/Security/CSP/CSP_policy_directives
687
+ #
688
+ security.content_security_policy %{
689
+ form-action 'self';
690
+ frame-ancestors 'self';
691
+ base-uri 'self';
692
+ default-src 'none';
693
+ script-src 'self';
694
+ connect-src 'self';
695
+ img-src 'self' https: data:;
696
+ style-src 'self' 'unsafe-inline' https:;
697
+ font-src 'self';
698
+ object-src 'none';
699
+ plugin-types app/pdf;
700
+ child-src 'self';
701
+ frame-src 'self';
702
+ media-src 'self'
703
+ }
704
+
705
+ ##
706
+ # FRAMEWORKS
707
+ #
708
+
709
+ # Configure the code that will yield each time Web::Action is included
710
+ # This is useful for sharing common functionality
711
+ #
712
+ # See: http://www.rubydoc.info/gems/hanami-controller#Configuration
713
+ controller.prepare do
714
+ # include MyAuthentication # included in all the actions
715
+ # before :authenticate! # run an authentication before callback
716
+ end
717
+
718
+ # Configure the code that will yield each time Web::View is included
719
+ # This is useful for sharing common functionality
720
+ #
721
+ # See: http://www.rubydoc.info/gems/hanami-view#Configuration
722
+ view.prepare do
723
+ include Hanami::Helpers
724
+ include Web::Assets::Helpers
725
+ end
726
+ end
727
+
728
+ ##
729
+ # DEVELOPMENT
730
+ #
731
+ configure :development do
732
+ # Don't handle exceptions, render the stack trace
733
+ handle_exceptions false
734
+ end
735
+
736
+ ##
737
+ # TEST
738
+ #
739
+ configure :test do
740
+ # Don't handle exceptions, render the stack trace
741
+ handle_exceptions false
742
+ end
743
+
744
+ ##
745
+ # PRODUCTION
746
+ #
747
+ configure :production do
748
+ # scheme 'https'
749
+ # host 'example.org'
750
+ # port 443
751
+
752
+ assets do
753
+ # Don't compile static assets in production mode (eg. Sass, ES6)
754
+ #
755
+ # See: http://www.rubydoc.info/gems/hanami-assets#Configuration
756
+ compile false
757
+
758
+ # Use fingerprint file name for asset paths
759
+ #
760
+ # See: https://guides.hanamirb.org/assets/overview
761
+ fingerprint true
762
+
763
+ # Content Delivery Network (CDN)
764
+ #
765
+ # See: https://guides.hanamirb.org/assets/content-delivery-network
766
+ #
767
+ # scheme 'https'
768
+ # host 'cdn.example.org'
769
+ # port 443
770
+
771
+ # Subresource Integrity
772
+ #
773
+ # See: https://guides.hanamirb.org/assets/content-delivery-network/#subresource-integrity
774
+ subresource_integrity :sha256
775
+ end
776
+ end
777
+ end
778
+ end
779
+ END
780
+
781
+ #
782
+ # apps/web/config/routes.rb
783
+ #
784
+ expect("apps/web/config/routes.rb").to have_file_content <<-END
785
+ # Configure your routes here
786
+ # See: https://guides.hanamirb.org/routing/overview
787
+ #
788
+ # Example:
789
+ # get '/hello', to: ->(env) { [200, {}, ['Hello from Hanami!']] }
790
+ END
791
+
792
+ #
793
+ # apps/web/views/app_layout.rb
794
+ #
795
+ expect("apps/web/views/app_layout.rb").to have_file_content <<~END
796
+ module Web
797
+ module Views
798
+ class AppLayout
799
+ include Web::Layout
800
+ end
801
+ end
802
+ end
803
+ END
804
+
805
+ #
806
+ # apps/web/templates/app.html.erb
807
+ #
808
+ expect("apps/web/templates/app.html.erb").to have_file_content <<~END
809
+ <!DOCTYPE html>
810
+ <html>
811
+ <head>
812
+ <title>Web</title>
813
+ <%= favicon %>
814
+ </head>
815
+ <body>
816
+ <%= yield %>
817
+ </body>
818
+ </html>
819
+ END
820
+
821
+ #
822
+ # apps/web/assets/favicon.ico
823
+ #
824
+ expect("apps/web/assets/favicon.ico").to be_an_existing_file
825
+
826
+ #
827
+ # apps/web/controllers/.gitkeep
828
+ #
829
+ expect("apps/web/controllers/.gitkeep").to be_an_existing_file
830
+
831
+ #
832
+ # apps/web/assets/images/.gitkeep
833
+ #
834
+ expect("apps/web/assets/images/.gitkeep").to be_an_existing_file
835
+
836
+ #
837
+ # apps/web/assets/javascripts/.gitkeep
838
+ #
839
+ expect("apps/web/assets/javascripts/.gitkeep").to be_an_existing_file
840
+
841
+ #
842
+ # apps/web/assets/stylesheets/.gitkeep
843
+ #
844
+ expect("apps/web/assets/stylesheets/.gitkeep").to be_an_existing_file
845
+
846
+ #
847
+ # spec/web/features/.gitkeep
848
+ #
849
+ expect("spec/web/features/.gitkeep").to be_an_existing_file
850
+
851
+ #
852
+ # spec/web/controllers/.gitkeep
853
+ #
854
+ expect("spec/web/controllers/.gitkeep").to be_an_existing_file
855
+ end
856
+ end
857
+
858
+ context "with underscored project name" do
859
+ it_behaves_like "a new project" do
860
+ let(:input) { "cool_name" }
861
+ end
862
+ end
863
+
864
+ context "with dashed project name" do
865
+ it_behaves_like "a new project" do
866
+ let(:input) { "awesome-project" }
867
+ end
868
+ end
869
+
870
+ context "with camel case project name" do
871
+ it_behaves_like "a new project" do
872
+ let(:input) { "CaMElCaSE" }
873
+ end
874
+ end
875
+
876
+ context "with dot as project name" do
877
+ before do
878
+ root.mkpath
879
+ end
880
+
881
+ let(:root) { Pathname.new(Dir.pwd).join("tmp", "aruba", dir) }
882
+ let(:project) { "terrific_product" }
883
+ let(:dir) { "terrific product" }
884
+
885
+ it "generates project" do
886
+ cd(dir) do
887
+ run_cmd "hanami new ."
888
+ end
889
+
890
+ [
891
+ "create lib/#{project}.rb",
892
+ "create lib/#{project}/entities/.gitkeep",
893
+ "create lib/#{project}/repositories/.gitkeep",
894
+ "create lib/#{project}/mailers/.gitkeep",
895
+ "create lib/#{project}/mailers/templates/.gitkeep",
896
+ "create spec/#{project}/entities/.gitkeep",
897
+ "create spec/#{project}/repositories/.gitkeep",
898
+ "create spec/#{project}/mailers/.gitkeep"
899
+ ].each do |output|
900
+ expect(all_output).to match(/#{output}/)
901
+ end
902
+
903
+ within_project_directory(dir) do
904
+ #
905
+ # .hanamirc
906
+ #
907
+ expect(".hanamirc").to have_file_content %r{project=#{project}}
908
+ end
909
+ end
910
+ end
911
+
912
+ context "with missing name" do
913
+ it "fails" do
914
+ output = <<~OUT
915
+ ERROR: "hanami new" was called with no arguments
916
+ Usage: "hanami new PROJECT"
917
+ OUT
918
+
919
+ run_cmd "hanami new", output, exit_status: 1
920
+ end
921
+ end
922
+
923
+ it 'prints help message' do
924
+ output = <<-OUT
925
+ Command:
926
+ hanami new
927
+
928
+ Usage:
929
+ hanami new PROJECT
930
+
931
+ Description:
932
+ Generate a new Hanami project
933
+
934
+ Arguments:
935
+ PROJECT # REQUIRED The project name
936
+
937
+ Options:
938
+ --database=VALUE, -d VALUE # Database (mysql/mysql2/postgresql/postgres/sqlite/sqlite3), default: "sqlite"
939
+ --app-name=VALUE # App name, default: "web"
940
+ --app-base-url=VALUE # App base URL, default: "/"
941
+ --template=VALUE # Template engine (erb/haml/slim), default: "erb"
942
+ --test=VALUE # Project testing framework (rspec/minitest), default: "rspec"
943
+ --[no-]hanami-head # Use Hanami HEAD (true/false), default: false
944
+ --help, -h # Print this help
945
+
946
+ Examples:
947
+ hanami new bookshelf # Basic usage
948
+ hanami new bookshelf --test=rspec # Setup RSpec testing framework
949
+ hanami new bookshelf --database=postgres # Setup Postgres database
950
+ hanami new bookshelf --template=slim # Setup Slim template engine
951
+ hanami new bookshelf --hanami-head # Use Hanami HEAD
952
+ OUT
953
+
954
+ run_cmd 'hanami new --help', output
955
+ end
956
+
957
+ private
958
+
959
+ def default_git_branch
960
+ result = `git config --list`.scan(/init\.defaultBranch\=[[:alpha:]]*/i).first
961
+
962
+ branch = if result.nil?
963
+ "(main|master)"
964
+ else
965
+ result.split("=").last
966
+ end
967
+
968
+ /On branch #{branch}/
969
+ end
970
+ end