utopia 2.21.0 → 2.22.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d99f06d0061224f93c7b6be1d0002d69ca7a06df9d132ba091cdf3bbbc2943e4
4
- data.tar.gz: 80bb32e00719fdc27832d28eab9202d674f766253bb8f51c8bca7702353d346a
3
+ metadata.gz: 64d6cd31c0780c6d2071157034b6d125da0b4e6c3649affafb9338208b0467b7
4
+ data.tar.gz: 9092ab79ee6fb441051e1114fefbe41761aa5339d2eee574d588729e7ea5c479
5
5
  SHA512:
6
- metadata.gz: 433eacbfcb8d1be7cf66aafad27b1a51cc5c2364b42c990f1251ad71e353b31040c841dc44a872270d95877088cc448784b41a9855242601aa0c41044e55b1d3
7
- data.tar.gz: d655055f8d8875ed8a7f471438bfd83d0f7c19c79549b10d297e411528d5cfc503b9fb9b6b9d674af6c3f43de087950a172f2252d4317bf9ad63c1855daf718f
6
+ metadata.gz: cd49ec085295dded939c0da489dfc6bb64a97207032bd3cf177b39cf84f131f00b935c96173c2c6196c50032a07f4786b2312144b776cbadd4c05840b96f9f70
7
+ data.tar.gz: 5fc0e4c878dfa11693481cbaf560d9024f69c66c48db29cc5722a56757d216449c4026e59f534578a784f6484a94ee0bd894831e93bcddeb26830dcadf17be2b
checksums.yaml.gz.sig CHANGED
Binary file
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2018-2022, by Samuel Williams.
5
+
6
+ # Update environment variables in config/environment.yaml
7
+ def initialize(...)
8
+ super
9
+
10
+ require 'securerandom'
11
+ require 'yaml/store'
12
+ require 'console'
13
+ end
14
+
15
+ # Setup default environemnts "testing" and "development".
16
+ # @parameter root [String] The root directory of the project.
17
+ def setup(root: context.root)
18
+ defaults(name: "testing", root: root)
19
+ defaults(name: "development", root: root)
20
+ end
21
+
22
+ # Setup the defaults for a specific environment.
23
+ # @parameter name [String] The name of the environment to setup.
24
+ # @parameter root [String] The root directory of the project.
25
+ def defaults(name, root: context.root)
26
+ update_environment(root, name) do |store|
27
+ # Set some useful defaults for the environment.
28
+ store['UTOPIA_SESSION_SECRET'] ||= SecureRandom.hex(40)
29
+ end
30
+ end
31
+
32
+ # Update the specified environment.
33
+ # @parameter name [String] The name of the environment to update.
34
+ # @parameter variables [Hash(String, String)] A list of environment KEY=VALUE pairs to set.
35
+ def update(name, root: context.root, **variables)
36
+ update_environment(root, name) do |store|
37
+ variables&.each do |variable|
38
+ key, value = variable.split('=', 2)
39
+
40
+ if value
41
+ puts "ENV[#{key.inspect}] will default to #{value.inspect} unless otherwise specified."
42
+ store[key] = value
43
+ else
44
+ puts "ENV[#{key.inspect}] will be unset unless otherwise specified."
45
+ store.delete(key)
46
+ end
47
+ end
48
+
49
+ yield store if block_given?
50
+
51
+ Console.logger.debug(self) do |buffer|
52
+ buffer.puts "Environment #{name} (#{path}):"
53
+ store.roots.each do |key|
54
+ value = store[key]
55
+
56
+ buffer.puts "#{key}=#{value.inspect}"
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ def read(name, root: context.root)
63
+ environment_path = self.environment_path(root, name)
64
+
65
+ if File.exist?(environment_path)
66
+ Console.logger.debug(self) {"Loading environment #{name} from #{environment_path}..."}
67
+ YAML.load_file(environment_path)
68
+ else
69
+ Console.logger.debug(self) {"No environment #{name} found at #{environment_path}."}
70
+ {}
71
+ end
72
+ end
73
+
74
+ private
75
+
76
+ def environment_path(root, name)
77
+ File.join(root, "config", "#{name}.yaml")
78
+ end
79
+
80
+ # Setup `config/environment.yaml` according to specified options.
81
+ def update_environment(root, name)
82
+ environment_path = self.environment_path(root, name)
83
+ FileUtils.mkpath File.dirname(environment_path)
84
+
85
+ store = YAML::Store.new(environment_path)
86
+
87
+ store.transaction do
88
+ yield store, name, environment_path
89
+ end
90
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2017-2022, by Samuel Williams.
5
+
6
+ def initialize(...)
7
+ super
8
+
9
+ require 'fileutils'
10
+ require 'socket'
11
+ end
12
+
13
+ # Create a remote Utopia website suitable for deployment using git.
14
+ def create(root: context.root)
15
+ FileUtils.mkdir_p File.join(root, "public")
16
+
17
+ update(root: root)
18
+
19
+ # Print out helpful git remote add message:
20
+ puts "Now add the git remote to your local repository:\n\tgit remote add production ssh://#{Socket.gethostname}#{root}"
21
+ puts "Then push to it:\n\tgit push --set-upstream production main"
22
+ end
23
+
24
+ # The path to the setup directory in the gem:
25
+ SETUP_ROOT = File.expand_path("../../setup", __dir__)
26
+
27
+ # The root directory of the template server deployment:
28
+ SERVER_ROOT = File.join(SETUP_ROOT, 'server')
29
+
30
+ # Update the git hooks in an existing server repository.
31
+ def update(root: context.root)
32
+ # It's okay to call this on an existing repo, it will only update config as required to enable --shared.
33
+ # --shared allows multiple users to access the site with the same group.
34
+ system("git", "init", "--shared", chdir: root) or fail "could not initialize repository"
35
+
36
+ system("git", "config", "receive.denyCurrentBranch", "ignore", chdir: root) or fail "could not set configuration"
37
+ system("git", "config", "core.worktree", root, chdir: root) or fail "could not set configuration"
38
+
39
+ # Doing this invokes a lot of behaviour that isn't always ideal...
40
+ # system("bundle", "config", "set", "--local", "deployment", "true")
41
+ system("bundle", "config", "set", "--local", "without", "development", chdir: root) or fail "could not set bundle configuration"
42
+
43
+ # In theory, to convert from non-shared to shared:
44
+ # chgrp -R <group-name> . # Change files and directories' group
45
+ # chmod -R g+w . # Change permissions
46
+ # chmod g-w .git/objects/pack/* # Git pack files should be immutable
47
+ # chmod g+s `find . -type d` # New files get group id of directory
48
+
49
+ # Set some useful defaults for the environment.
50
+ recipe = context.lookup("utopia:environment:update")
51
+ recipe.instance.update("environment", root: root) do |store|
52
+ store['VARIANT'] ||= 'production'
53
+ store['UTOPIA_SESSION_SECRET'] ||= SecureRandom.hex(40)
54
+ end
55
+
56
+ # Copy git hooks:
57
+ system("cp", "-r", File.join(SERVER_ROOT, 'git', 'hooks'), File.join(root, '.git')) or fail "could not copy git hooks"
58
+ # finally set everything in the .git directory to be group writable
59
+ # This failed for me and I had to do sudo chown http:http .git -R first.
60
+ system("chmod", "-Rf", "g+w", File.join(root, '.git')) or fail "could not update permissions of .git directory"
61
+ end
@@ -0,0 +1,188 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2017-2023, by Samuel Williams.
5
+ # Copyright, 2020, by Michael Adams.
6
+
7
+ def initialize(...)
8
+ super
9
+
10
+ require 'fileutils'
11
+ require 'find'
12
+ end
13
+
14
+ # The path to the setup directory in the gem:
15
+ SETUP_ROOT = File.expand_path("../../setup", __dir__)
16
+
17
+ # Configuration files which should be installed/updated:
18
+ CONFIGURATION_FILES = ['.gitignore', 'config.ru', 'config/environment.rb', 'falcon.rb', 'gems.rb', 'Guardfile', 'bake.rb', 'test/website.rb', 'fixtures/website.rb']
19
+
20
+ # Directories that should exist:
21
+ DIRECTORIES = ["config", "lib", "pages", "public", "bake", "test"]
22
+
23
+ # Directories that should be removed during upgrade process:
24
+ OLD_PATHS = ["access_log", "cache", "tmp", "Rakefile", "tasks", ".bowerrc"]
25
+
26
+ # The root directory of the template site:
27
+ SITE_ROOT = File.join(SETUP_ROOT, 'site')
28
+
29
+ # Create a new local Utopia website using the default template.
30
+ def create(root: context.root)
31
+ Console.logger.debug(self) {"Setting up site in #{root} for Utopia v#{Utopia::VERSION}..."}
32
+
33
+ DIRECTORIES.each do |directory|
34
+ FileUtils.mkdir_p(File.join(root, directory))
35
+ end
36
+
37
+ Find.find(SITE_ROOT) do |source_path|
38
+ # Compute the destination path:
39
+ destination_path = File.join(root, source_path[SITE_ROOT.size..-1])
40
+
41
+ if File.directory?(source_path)
42
+ # Create the directory:
43
+ FileUtils.mkdir_p(destination_path)
44
+ else
45
+ # Copy the file, unless it already exists:
46
+ unless File.exist? destination_path
47
+ FileUtils.copy_entry(source_path, destination_path)
48
+ end
49
+ end
50
+ end
51
+
52
+ CONFIGURATION_FILES.each do |configuration_file|
53
+ destination_path = File.join(root, configuration_file)
54
+
55
+ if File.exist?(destination_path)
56
+ buffer = File.read(destination_path).gsub('$UTOPIA_VERSION', Utopia::VERSION)
57
+ File.open(destination_path, "w") { |file| file.write(buffer) }
58
+ else
59
+ Console.logger.warn(self) {"Could not open #{destination_path}, maybe it should be removed from CONFIGURATION_FILES?"}
60
+ end
61
+ end
62
+
63
+ system("bundle", "install", chdir: root) or warn "could not install bundled gems"
64
+
65
+ if !File.exist?('.git')
66
+ Console.logger.info(self) {"Setting up git repository..."}
67
+
68
+ system("git", "init", chdir: root) or warn "could not create git repository"
69
+ system("git", "add", ".", chdir: root) or warn "could not add all files"
70
+ system("git", "commit", "-q", "-m", "Initial Utopia v#{Utopia::VERSION} site.", chdir: root) or warn "could not commit files"
71
+ end
72
+
73
+ context.lookup('utopia:environment:defaults').call(root)
74
+
75
+ name = `git config user.name || whoami`.chomp
76
+
77
+ puts
78
+ puts " #{name},".ljust(78)
79
+ puts "Thank you for using Utopia!".center(78)
80
+ puts "We sincerely hope that Utopia helps to".center(78)
81
+ puts "make your life easier and more enjoyable.".center(78)
82
+ puts ""
83
+ puts "To start the development server, run:".center(78)
84
+ puts "bake utopia:development".center(78)
85
+ puts ""
86
+ puts "For extreme productivity, please consult the online documentation".center(78)
87
+ puts "https://github.com/socketry/utopia".center(78)
88
+ puts " ~ Samuel. ".rjust(78)
89
+ end
90
+
91
+ # Upgrade an existing site to use the latest configuration files from the template.
92
+ def upgrade(root: context.root)
93
+ branch_name = "utopia-upgrade-#{Utopia::VERSION}"
94
+
95
+ $stderr.puts "Upgrading #{destination_root}..."
96
+
97
+ system('git', 'checkout', '-b', branch_name, chdir: root) or fail "could not change branch"
98
+
99
+ DIRECTORIES.each do |directory|
100
+ FileUtils.mkdir_p(File.join(root, directory))
101
+ end
102
+
103
+ OLD_PATHS.each do |path|
104
+ path = File.join(root, path)
105
+ Console.logger.info(self) {"Removing #{path}..."}
106
+ FileUtils.rm_rf(path)
107
+ end
108
+
109
+ CONFIGURATION_FILES.each do |configuration_file|
110
+ source_path = File.join(SITE_ROOT, configuration_file)
111
+ destination_path = File.join(root, configuration_file)
112
+
113
+ Console.logger.info(self) {"Updating #{destination_path}..."}
114
+
115
+ FileUtils.copy_entry(source_path, destination_path)
116
+ buffer = File.read(destination_path).gsub('$UTOPIA_VERSION', Utopia::VERSION)
117
+ File.open(destination_path, "w") { |file| file.write(buffer) }
118
+ end
119
+
120
+ context.lookup('environment:defaults').call(root)
121
+
122
+ begin
123
+ # Stage any files that have been changed or removed:
124
+ system("git", "add", "-u", chdir: root) or fail "could not add files"
125
+
126
+ # Stage any new files that we have explicitly added:
127
+ system("git", "add", *CONFIGURATION_FILES, chdir: root) or fail "could not add files"
128
+
129
+ move_static!(root)
130
+ update_gemfile!(root)
131
+
132
+ # Commit all changes:
133
+ system("git", "commit", "-m", "Upgrade to utopia #{Utopia::VERSION}.", chdir: root) or fail "could not commit changes"
134
+
135
+ # Checkout main..
136
+ system("git", "checkout", "main", chdir: root) or fail "could not checkout main"
137
+
138
+ # and merge:
139
+ system("git", "merge", "--squash", "--no-commit", branch_name, chdir: root) or fail "could not merge changes"
140
+ rescue => error
141
+ Console.logger.error(self, error) {"Upgrade failed."}
142
+
143
+ system("git", "checkout", "master", chdir: root)
144
+ ensure
145
+ system("git", "branch", "-D", branch_name, chdir: root)
146
+ end
147
+ end
148
+
149
+ private
150
+
151
+ # Move legacy `pages/_static` to `public/_static`.
152
+ def move_static!(root)
153
+ old_static_path = File.expand_path('pages/_static', root)
154
+
155
+ # If public/_static doens't exist, we are done.
156
+ return unless File.exist?(old_static_path)
157
+
158
+ new_static_path = File.expand_path('public/_static', root)
159
+
160
+ if File.exist?(new_static_path)
161
+ if File.lstat(new_static_path).symlink?
162
+ FileUtils.rm_f new_static_path
163
+ else
164
+ Console.logger.warn(self) {"Can't move pages/_static to public/_static, destination already exists."}
165
+ return
166
+ end
167
+ end
168
+
169
+ # One more sanity check:
170
+ if File.directory?(old_static_path)
171
+ system("git", "mv", "pages/_static", "public/")
172
+ end
173
+ end
174
+
175
+ # Move `Gemfile` to `gems.rb`.
176
+ def update_gemfile!(root)
177
+ gemfile_path = File.expand_path('Gemfile', root)
178
+
179
+ # If `Gemfile` doens't exist, we are done:
180
+ return unless File.exist?(gemfile_path)
181
+
182
+ # If `gems.rb` already exists, we are done:
183
+ gems_path = File.expand_path('gems.rb', root)
184
+ return if File.exist?(gems_path)
185
+
186
+ system("git", "mv", "Gemfile", "gems.rb", chdir: root)
187
+ system("git", "mv", "Gemfile.lock", "gems.locked", chdir: root)
188
+ end
@@ -4,5 +4,5 @@
4
4
  # Copyright, 2009-2022, by Samuel Williams.
5
5
 
6
6
  module Utopia
7
- VERSION = "2.21.0"
7
+ VERSION = "2.22.0"
8
8
  end
data/license.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # MIT License
2
2
 
3
- Copyright, 2009-2022, by Samuel Williams.
3
+ Copyright, 2009-2023, by Samuel Williams.
4
4
  Copyright, 2015-2019, by Huba Nagy.
5
5
  Copyright, 2020, by Olle Jonsson.
6
- Copyright, 2020, by k1tsu.
6
+ Copyright, 2020, by Pierre Montelle.
7
7
  Copyright, 2020, by Michael Adams.
8
8
 
9
9
  Permission is hereby granted, free of charge, to any person obtaining a copy
data/readme.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Utopia is a website generation framework which provides a robust set of tools to build highly complex dynamic websites. It uses the filesystem heavily for content and provides functions for interacting with files and directories as structure representing the website.
4
4
 
5
- [![Development Status](https://github.com/socketry/utopia/workflows/Test/badge.svg)](https://github.com/socketry/utopia/actions?workflow=Test)
5
+ [![Development Status](https://github.com/ioquatix/utopia/workflows/Test/badge.svg)](https://github.com/ioquatix/utopia/actions?workflow=Test)
6
6
 
7
7
  ## Features
8
8
 
@@ -1,5 +1,4 @@
1
1
  # Development specific:
2
- /.rspec_status
3
2
  /.bundle
4
3
 
5
4
  # Temporary data should not be added to the repository:
data/setup/site/Guardfile CHANGED
@@ -10,20 +10,20 @@ group :development do
10
10
  end
11
11
 
12
12
  group :test do
13
- guard :rspec, cmd: 'rspec' do
14
- # Notifications can get a bit tedious:
15
- # notification :off
13
+ # guard :rspec, cmd: 'rspec' do
14
+ # # Notifications can get a bit tedious:
15
+ # # notification :off
16
16
 
17
- # Re-run specs if they are changed:
18
- watch(%r{^spec/.+_spec\.rb$})
19
- watch('spec/spec_helper.rb') {'spec'}
17
+ # # Re-run specs if they are changed:
18
+ # watch(%r{^spec/.+_spec\.rb$})
19
+ # watch('spec/spec_helper.rb') {'spec'}
20
20
 
21
- # Run relevent specs if files in `lib/` or `pages/` are changed:
22
- watch(%r{^lib/(.+)\.rb$}) {|match| "spec/lib/#{match[1]}_spec.rb" }
23
- watch(%r{^pages/(.+)\.(rb|xnode)$}) {|match| "spec/pages/#{match[1]}_spec.rb"}
24
- watch(%r{^pages/(.+)controller\.rb$}) {|match| Dir.glob("spec/pages/#{match[1]}*_spec.rb")}
21
+ # # Run relevent specs if files in `lib/` or `pages/` are changed:
22
+ # watch(%r{^lib/(.+)\.rb$}) {|match| "spec/lib/#{match[1]}_spec.rb" }
23
+ # watch(%r{^pages/(.+)\.(rb|xnode)$}) {|match| "spec/pages/#{match[1]}_spec.rb"}
24
+ # watch(%r{^pages/(.+)controller\.rb$}) {|match| Dir.glob("spec/pages/#{match[1]}*_spec.rb")}
25
25
 
26
- # If any files in pages changes, ensure the website still works:
27
- watch(%r{^pages/.*}) {'spec/website_spec.rb'}
28
- end
26
+ # # If any files in pages changes, ensure the website still works:
27
+ # watch(%r{^pages/.*}) {'spec/website_spec.rb'}
28
+ # end
29
29
  end
File without changes
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2023, by Samuel Williams.
5
+
6
+ require 'variant'
7
+ Variant.force!(:testing)
8
+
9
+ require 'covered/sus'
10
+ include Covered::Sus
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2016-2023, by Samuel Williams.
5
+
6
+ require 'rack/test'
7
+ require 'sus/fixtures/async/http'
8
+ require 'protocol/rack'
9
+
10
+ AWebsite = Sus::Shared("a website") do
11
+ include Rack::Test::Methods
12
+
13
+ let(:rackup_path) {File.expand_path('../config.ru', __dir__)}
14
+ let(:rackup_directory) {File.dirname(rackup_path)}
15
+
16
+ let(:app) {Rack::Builder.parse_file(rackup_path)}
17
+ end
18
+
19
+ AValidPage = Sus::Shared("a valid page") do |path|
20
+ it "can access #{path}" do
21
+ get path
22
+
23
+ while last_response.redirect?
24
+ follow_redirect!
25
+ end
26
+
27
+ expect(last_response.status).to be == 200
28
+ end
29
+ end
30
+
31
+ AServer = Sus::Shared("a server") do
32
+ include Sus::Fixtures::Async::HTTP::ServerContext
33
+
34
+ let(:rackup_path) {File.expand_path('../config.ru', __dir__)}
35
+ let(:rackup_directory) {File.dirname(rackup_path)}
36
+
37
+ let(:rack_app) {Rack::Builder.parse_file(rackup_path)}
38
+ let(:app) {Protocol::Rack::Adapter.new(rack_app)}
39
+ end
data/setup/site/gems.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2012-2022, by Samuel Williams.
4
+ # Copyright, 2012-2023, by Samuel Williams.
5
5
 
6
6
  source 'https://rubygems.org'
7
7
 
@@ -13,20 +13,18 @@ group :preload do
13
13
  gem 'variant'
14
14
  end
15
15
 
16
- gem 'rake'
17
- gem 'bake'
18
- gem 'bundler'
19
- gem 'rack-test'
20
16
  gem 'net-smtp'
21
17
 
22
18
  group :development do
19
+ gem 'bake-test'
20
+ gem 'rack-test'
23
21
  gem 'guard-falcon', require: false
24
- gem 'guard-rspec', require: false
25
22
 
26
- gem 'rspec'
23
+ gem 'sus'
24
+ gem 'sus-fixtures-async-http'
25
+
27
26
  gem 'covered'
28
27
 
29
- gem 'async-rspec'
30
28
  gem 'benchmark-http'
31
29
  end
32
30
 
File without changes
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2016-2023, by Samuel Williams.
5
+
6
+ require 'website'
7
+ require 'benchmark/http'
8
+
9
+ describe "website" do
10
+ include_context AServer
11
+
12
+ let(:timeout) {10}
13
+ let(:spider) {Benchmark::HTTP::Spider.new(depth: 128)}
14
+ let(:statistics) {Benchmark::HTTP::Statistics.new}
15
+
16
+ it "should be responsive" do
17
+ spider.fetch(statistics, client, endpoint.url) do |method, uri, response|
18
+ if response.failure?
19
+ Console.logger.error(endpoint) {"#{method} #{uri} -> #{response.status}"}
20
+ end
21
+ end.wait
22
+
23
+ statistics.print
24
+
25
+ expect(statistics.samples).to be(:any?)
26
+ expect(statistics.failed).to be(:zero?)
27
+ end
28
+ end
data.tar.gz.sig CHANGED
Binary file