neocities-red 1.1.1 → 1.2.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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +29 -15
- data/.gitignore +4 -0
- data/CHANGELOG.md +95 -0
- data/Gemfile +3 -2
- data/Gemfile.lock +38 -34
- data/README.md +6 -0
- data/lib/neocities_red/cli.rb +157 -32
- data/lib/neocities_red/cli_display.rb +200 -5
- data/lib/neocities_red/client.rb +84 -77
- data/lib/neocities_red/errors.rb +20 -0
- data/lib/neocities_red/services/common/exclusions.rb +69 -0
- data/lib/neocities_red/services/common/pizza.rb +34 -21
- data/lib/neocities_red/services/common/worker_pool.rb +54 -0
- data/lib/neocities_red/services/file/folder_uploader.rb +39 -25
- data/lib/neocities_red/services/file/list.rb +60 -30
- data/lib/neocities_red/services/file/remover.rb +27 -12
- data/lib/neocities_red/services/file/uploader.rb +33 -13
- data/lib/neocities_red/services/site/differencer.rb +42 -12
- data/lib/neocities_red/services/site/exporter.rb +120 -7
- data/lib/neocities_red/services/site/informer.rb +29 -4
- data/lib/neocities_red/services/site/pusher.rb +74 -38
- data/lib/neocities_red/version.rb +2 -1
- data/lib/neocities_red.rb +32 -13
- data/neocities-red.gemspec +12 -7
- data/spec/neocities_red/cli_display_spec.rb +0 -6
- data/spec/neocities_red/cli_spec.rb +85 -0
- data/spec/neocities_red/client_spec.rb +7 -50
- data/spec/neocities_red/services/common/exclusions_spec.rb +47 -0
- data/spec/neocities_red/services/common/worker_pool_spec.rb +48 -0
- data/spec/neocities_red/services/file/folder_uploader_spec.rb +8 -6
- data/spec/neocities_red/services/file/list_spec.rb +13 -10
- data/spec/neocities_red/services/file/remover_spec.rb +15 -21
- data/spec/neocities_red/services/file/uploader_spec.rb +25 -20
- data/spec/neocities_red/services/site/differencer_spec.rb +32 -6
- data/spec/neocities_red/services/site/exporter_spec.rb +105 -38
- data/spec/neocities_red/services/site/informer_spec.rb +3 -3
- data/spec/neocities_red/services/site/pusher_spec.rb +1 -1
- data/spec/spec_helper.rb +1 -1
- metadata +14 -34
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require "spec_helper"
|
|
4
4
|
require "json"
|
|
5
5
|
require "fileutils"
|
|
6
|
+
require "time"
|
|
6
7
|
|
|
7
8
|
RSpec.describe NeocitiesRed::Services::Site::Exporter do
|
|
8
9
|
let(:client) { instance_double(NeocitiesRed::Client) }
|
|
@@ -11,29 +12,42 @@ RSpec.describe NeocitiesRed::Services::Site::Exporter do
|
|
|
11
12
|
let(:tmp_root) { File.join(spec_root, "tmp", "site_exporter_spec") }
|
|
12
13
|
let(:config_path) { File.join(tmp_root, "config.json") }
|
|
13
14
|
let(:data) { { "LAST_PULL" => { "time" => nil, "loc" => nil } } }
|
|
15
|
+
let(:display) do
|
|
16
|
+
instance_double(
|
|
17
|
+
NeocitiesRed::CliDisplay,
|
|
18
|
+
display_pull_progress: nil,
|
|
19
|
+
display_pull_no_updates: nil,
|
|
20
|
+
display_pull_success: nil,
|
|
21
|
+
display_pull_failure: nil,
|
|
22
|
+
display_pull_stats: nil
|
|
23
|
+
)
|
|
24
|
+
end
|
|
25
|
+
let(:exporter) { described_class.new(client, sitename, data, config_path, display: display) }
|
|
26
|
+
let(:info_response) { { result: "success", info: { domain: nil } } }
|
|
27
|
+
let(:list_response) { { result: "success", files: [] } }
|
|
14
28
|
|
|
15
|
-
|
|
29
|
+
around do |example|
|
|
16
30
|
FileUtils.rm_rf(tmp_root)
|
|
17
31
|
FileUtils.mkdir_p(tmp_root)
|
|
18
32
|
File.write(config_path, data.to_json)
|
|
19
|
-
end
|
|
20
33
|
|
|
21
|
-
|
|
34
|
+
original_dir = Dir.pwd
|
|
35
|
+
Dir.chdir(tmp_root)
|
|
36
|
+
example.run
|
|
37
|
+
ensure
|
|
38
|
+
Dir.chdir(original_dir)
|
|
22
39
|
FileUtils.rm_rf(tmp_root)
|
|
23
40
|
end
|
|
24
41
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
before do
|
|
30
|
-
allow(client).to receive(:pull).and_return(nil)
|
|
31
|
-
end
|
|
42
|
+
before do
|
|
43
|
+
allow(client).to receive_messages(info: info_response, list: list_response)
|
|
44
|
+
end
|
|
32
45
|
|
|
33
|
-
|
|
46
|
+
describe "#export" do
|
|
47
|
+
context "when the site has no files" do
|
|
48
|
+
it "updates the config file with last pull data" do
|
|
34
49
|
expect { exporter.export(quiet: true, last_pull_time: nil, last_pull_loc: nil) }.not_to raise_error
|
|
35
50
|
|
|
36
|
-
expect(File.exist?(config_path)).to be(true)
|
|
37
51
|
updated_data = JSON.parse(File.read(config_path))
|
|
38
52
|
expect(updated_data["LAST_PULL"]).to have_key("time")
|
|
39
53
|
expect(updated_data["LAST_PULL"]).to have_key("loc")
|
|
@@ -62,51 +76,104 @@ RSpec.describe NeocitiesRed::Services::Site::Exporter do
|
|
|
62
76
|
expect(Whirly).not_to have_received(:stop)
|
|
63
77
|
end
|
|
64
78
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
79
|
+
it "displays pull stats" do
|
|
80
|
+
exporter.export(quiet: false, last_pull_time: nil, last_pull_loc: nil)
|
|
81
|
+
|
|
82
|
+
expect(display).to have_received(:display_pull_stats).with(0, anything)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
context "when the site has files" do
|
|
87
|
+
let(:list_response) do
|
|
88
|
+
{
|
|
89
|
+
result: "success",
|
|
90
|
+
files: [
|
|
91
|
+
{ path: "index.html", is_directory: false, updated_at: "2024-01-01T00:00:00Z" },
|
|
92
|
+
{ path: "assets/", is_directory: true, updated_at: "2024-01-01T00:00:00Z" }
|
|
93
|
+
]
|
|
94
|
+
}
|
|
95
|
+
end
|
|
96
|
+
let(:file_response) { instance_double(Faraday::Response, status: 200, body: "<h1>Hello</h1>") }
|
|
97
|
+
|
|
98
|
+
it "downloads files and writes them locally" do
|
|
99
|
+
allow(client).to receive(:download).with("https://test-site.neocities.org/index.html").and_return(file_response)
|
|
100
|
+
|
|
101
|
+
exporter.export(quiet: false, last_pull_time: nil, last_pull_loc: nil)
|
|
102
|
+
|
|
103
|
+
expect(File.read(File.join(tmp_root, "index.html"))).to eq("<h1>Hello</h1>")
|
|
104
|
+
expect(File.directory?(File.join(tmp_root, "assets"))).to be(true)
|
|
105
|
+
expect(display).to have_received(:display_pull_success)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it "uses the custom domain when present" do
|
|
109
|
+
allow(client).to receive(:info).and_return(result: "success", info: { domain: "example.com" })
|
|
110
|
+
allow(client).to receive(:download).with("https://example.com/index.html").and_return(file_response)
|
|
111
|
+
|
|
112
|
+
exporter.export(quiet: false, last_pull_time: nil, last_pull_loc: nil)
|
|
113
|
+
|
|
114
|
+
expect(client).to have_received(:download).with("https://example.com/index.html")
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it "skips download when the file has not changed since last pull" do
|
|
118
|
+
allow(client).to receive(:download)
|
|
119
|
+
File.write(File.join(tmp_root, "index.html"), "existing content")
|
|
120
|
+
|
|
121
|
+
last_pull_time = Time.now.iso8601
|
|
122
|
+
exporter.export(quiet: false, last_pull_time: last_pull_time, last_pull_loc: Dir.pwd)
|
|
123
|
+
|
|
124
|
+
expect(display).to have_received(:display_pull_no_updates)
|
|
125
|
+
expect(client).not_to have_received(:download)
|
|
126
|
+
expect(File.read(File.join(tmp_root, "index.html"))).to eq("existing content")
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
it "reports failure when the download fails" do
|
|
130
|
+
allow(client).to receive(:download).with("https://test-site.neocities.org/index.html").and_return(
|
|
131
|
+
instance_double(Faraday::Response, status: 500, body: "")
|
|
132
|
+
)
|
|
68
133
|
|
|
69
|
-
|
|
70
|
-
expect { exporter.export(quiet: true, last_pull_time: last_pull_time, last_pull_loc: last_pull_loc) }.not_to raise_error
|
|
134
|
+
exporter.export(quiet: false, last_pull_time: nil, last_pull_loc: nil)
|
|
71
135
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
)
|
|
75
|
-
end
|
|
136
|
+
expect(display).to have_received(:display_pull_failure)
|
|
137
|
+
expect(File.exist?(File.join(tmp_root, "index.html"))).to be(false)
|
|
76
138
|
end
|
|
77
139
|
end
|
|
78
140
|
|
|
79
|
-
context "when
|
|
80
|
-
let(:
|
|
141
|
+
context "when the API returns an error for info" do
|
|
142
|
+
let(:info_response) { { result: "error", message: "Site not found" } }
|
|
81
143
|
|
|
82
|
-
it "
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
144
|
+
it "raises APIError" do
|
|
145
|
+
expect do
|
|
146
|
+
exporter.export(quiet: true, last_pull_time: nil, last_pull_loc: nil)
|
|
147
|
+
end.to raise_error(NeocitiesRed::APIError, /Site not found/)
|
|
148
|
+
end
|
|
149
|
+
end
|
|
86
150
|
|
|
87
|
-
|
|
151
|
+
context "when the API returns an error for list" do
|
|
152
|
+
let(:list_response) { { result: "error", message: "List failed" } }
|
|
88
153
|
|
|
89
|
-
|
|
90
|
-
expect
|
|
91
|
-
|
|
154
|
+
it "raises APIError" do
|
|
155
|
+
expect do
|
|
156
|
+
exporter.export(quiet: true, last_pull_time: nil, last_pull_loc: nil)
|
|
157
|
+
end.to raise_error(NeocitiesRed::APIError, /List failed/)
|
|
92
158
|
end
|
|
159
|
+
end
|
|
93
160
|
|
|
94
|
-
|
|
161
|
+
context "when fetching raises an error" do
|
|
162
|
+
it "propagates the error and stops Whirly" do
|
|
163
|
+
allow(client).to receive(:info).and_raise(StandardError.new("network error"))
|
|
95
164
|
allow(Whirly).to receive(:start)
|
|
96
165
|
allow(Whirly).to receive(:stop)
|
|
97
|
-
allow(client).to receive(:pull).and_raise(StandardError.new("network error"))
|
|
98
166
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
167
|
+
expect do
|
|
168
|
+
exporter.export(quiet: true, last_pull_time: nil, last_pull_loc: nil)
|
|
169
|
+
end.to raise_error(StandardError, "network error")
|
|
170
|
+
expect(Whirly).to have_received(:stop)
|
|
102
171
|
end
|
|
103
172
|
end
|
|
104
173
|
end
|
|
105
174
|
|
|
106
175
|
describe "#initialize" do
|
|
107
176
|
it "stores client, sitename, data, and app_config_path" do
|
|
108
|
-
exporter = described_class.new(client, sitename, data, config_path)
|
|
109
|
-
|
|
110
177
|
expect(exporter.client).to eq(client)
|
|
111
178
|
expect(exporter.sitename).to eq(sitename)
|
|
112
179
|
expect(exporter.data).to eq(data)
|
|
@@ -54,10 +54,10 @@ RSpec.describe NeocitiesRed::Services::Site::Informer do
|
|
|
54
54
|
allow(client).to receive(:info).and_return(error_response)
|
|
55
55
|
end
|
|
56
56
|
|
|
57
|
-
it "raises
|
|
57
|
+
it "raises APIError with the message" do
|
|
58
58
|
expect { profile_info.stats }.to raise_error(
|
|
59
|
-
NeocitiesRed::
|
|
60
|
-
/
|
|
59
|
+
NeocitiesRed::APIError,
|
|
60
|
+
/could not find site nonexistent/
|
|
61
61
|
)
|
|
62
62
|
end
|
|
63
63
|
end
|
|
@@ -47,7 +47,7 @@ RSpec.describe NeocitiesRed::Services::Site::Pusher do
|
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
before do
|
|
50
|
-
allow(NeocitiesRed::Services::File::Uploader).to receive(:new) do |_client, filepath, remote_path|
|
|
50
|
+
allow(NeocitiesRed::Services::File::Uploader).to receive(:new) do |_client, filepath, remote_path, _display|
|
|
51
51
|
upload_calls << [filepath.to_s, remote_path.to_s]
|
|
52
52
|
uploader_instance
|
|
53
53
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: neocities-red
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kyle Drake
|
|
@@ -16,20 +16,14 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version:
|
|
20
|
-
- - ">="
|
|
21
|
-
- !ruby/object:Gem::Version
|
|
22
|
-
version: 2.14.0
|
|
19
|
+
version: 2.14.3
|
|
23
20
|
type: :runtime
|
|
24
21
|
prerelease: false
|
|
25
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
26
23
|
requirements:
|
|
27
24
|
- - "~>"
|
|
28
25
|
- !ruby/object:Gem::Version
|
|
29
|
-
version:
|
|
30
|
-
- - ">="
|
|
31
|
-
- !ruby/object:Gem::Version
|
|
32
|
-
version: 2.14.0
|
|
26
|
+
version: 2.14.3
|
|
33
27
|
- !ruby/object:Gem::Dependency
|
|
34
28
|
name: faraday-follow_redirects
|
|
35
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -90,9 +84,6 @@ dependencies:
|
|
|
90
84
|
name: pastel
|
|
91
85
|
requirement: !ruby/object:Gem::Requirement
|
|
92
86
|
requirements:
|
|
93
|
-
- - "~>"
|
|
94
|
-
- !ruby/object:Gem::Version
|
|
95
|
-
version: '0.8'
|
|
96
87
|
- - '='
|
|
97
88
|
- !ruby/object:Gem::Version
|
|
98
89
|
version: 0.8.0
|
|
@@ -100,9 +91,6 @@ dependencies:
|
|
|
100
91
|
prerelease: false
|
|
101
92
|
version_requirements: !ruby/object:Gem::Requirement
|
|
102
93
|
requirements:
|
|
103
|
-
- - "~>"
|
|
104
|
-
- !ruby/object:Gem::Version
|
|
105
|
-
version: '0.8'
|
|
106
94
|
- - '='
|
|
107
95
|
- !ruby/object:Gem::Version
|
|
108
96
|
version: 0.8.0
|
|
@@ -113,9 +101,6 @@ dependencies:
|
|
|
113
101
|
- - "~>"
|
|
114
102
|
- !ruby/object:Gem::Version
|
|
115
103
|
version: '13'
|
|
116
|
-
- - ">="
|
|
117
|
-
- !ruby/object:Gem::Version
|
|
118
|
-
version: 13.3.0
|
|
119
104
|
type: :runtime
|
|
120
105
|
prerelease: false
|
|
121
106
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -123,9 +108,6 @@ dependencies:
|
|
|
123
108
|
- - "~>"
|
|
124
109
|
- !ruby/object:Gem::Version
|
|
125
110
|
version: '13'
|
|
126
|
-
- - ">="
|
|
127
|
-
- !ruby/object:Gem::Version
|
|
128
|
-
version: 13.3.0
|
|
129
111
|
- !ruby/object:Gem::Dependency
|
|
130
112
|
name: thor
|
|
131
113
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -150,9 +132,6 @@ dependencies:
|
|
|
150
132
|
name: tty-prompt
|
|
151
133
|
requirement: !ruby/object:Gem::Requirement
|
|
152
134
|
requirements:
|
|
153
|
-
- - "~>"
|
|
154
|
-
- !ruby/object:Gem::Version
|
|
155
|
-
version: '0.23'
|
|
156
135
|
- - '='
|
|
157
136
|
- !ruby/object:Gem::Version
|
|
158
137
|
version: 0.23.1
|
|
@@ -160,9 +139,6 @@ dependencies:
|
|
|
160
139
|
prerelease: false
|
|
161
140
|
version_requirements: !ruby/object:Gem::Requirement
|
|
162
141
|
requirements:
|
|
163
|
-
- - "~>"
|
|
164
|
-
- !ruby/object:Gem::Version
|
|
165
|
-
version: '0.23'
|
|
166
142
|
- - '='
|
|
167
143
|
- !ruby/object:Gem::Version
|
|
168
144
|
version: 0.23.1
|
|
@@ -170,9 +146,6 @@ dependencies:
|
|
|
170
146
|
name: tty-table
|
|
171
147
|
requirement: !ruby/object:Gem::Requirement
|
|
172
148
|
requirements:
|
|
173
|
-
- - "~>"
|
|
174
|
-
- !ruby/object:Gem::Version
|
|
175
|
-
version: '0.12'
|
|
176
149
|
- - '='
|
|
177
150
|
- !ruby/object:Gem::Version
|
|
178
151
|
version: 0.12.0
|
|
@@ -180,9 +153,6 @@ dependencies:
|
|
|
180
153
|
prerelease: false
|
|
181
154
|
version_requirements: !ruby/object:Gem::Requirement
|
|
182
155
|
requirements:
|
|
183
|
-
- - "~>"
|
|
184
|
-
- !ruby/object:Gem::Version
|
|
185
|
-
version: '0.12'
|
|
186
156
|
- - '='
|
|
187
157
|
- !ruby/object:Gem::Version
|
|
188
158
|
version: 0.12.0
|
|
@@ -219,6 +189,7 @@ files:
|
|
|
219
189
|
- ".gitignore"
|
|
220
190
|
- ".rspec"
|
|
221
191
|
- ".rubocop.yml"
|
|
192
|
+
- CHANGELOG.md
|
|
222
193
|
- CODE_OF_CONDUCT.md
|
|
223
194
|
- CONTRIBUTING.md
|
|
224
195
|
- Gemfile
|
|
@@ -232,7 +203,10 @@ files:
|
|
|
232
203
|
- lib/neocities_red/cli.rb
|
|
233
204
|
- lib/neocities_red/cli_display.rb
|
|
234
205
|
- lib/neocities_red/client.rb
|
|
206
|
+
- lib/neocities_red/errors.rb
|
|
207
|
+
- lib/neocities_red/services/common/exclusions.rb
|
|
235
208
|
- lib/neocities_red/services/common/pizza.rb
|
|
209
|
+
- lib/neocities_red/services/common/worker_pool.rb
|
|
236
210
|
- lib/neocities_red/services/file/folder_uploader.rb
|
|
237
211
|
- lib/neocities_red/services/file/list.rb
|
|
238
212
|
- lib/neocities_red/services/file/remover.rb
|
|
@@ -246,7 +220,9 @@ files:
|
|
|
246
220
|
- spec/neocities_red/cli_display_spec.rb
|
|
247
221
|
- spec/neocities_red/cli_spec.rb
|
|
248
222
|
- spec/neocities_red/client_spec.rb
|
|
223
|
+
- spec/neocities_red/services/common/exclusions_spec.rb
|
|
249
224
|
- spec/neocities_red/services/common/pizza_spec.rb
|
|
225
|
+
- spec/neocities_red/services/common/worker_pool_spec.rb
|
|
250
226
|
- spec/neocities_red/services/file/folder_uploader_spec.rb
|
|
251
227
|
- spec/neocities_red/services/file/list_spec.rb
|
|
252
228
|
- spec/neocities_red/services/file/remover_spec.rb
|
|
@@ -261,6 +237,10 @@ licenses:
|
|
|
261
237
|
- MIT
|
|
262
238
|
metadata:
|
|
263
239
|
rubygems_mfa_required: 'true'
|
|
240
|
+
homepage_uri: https://github.com/o-200/neocities-red
|
|
241
|
+
source_code_uri: https://github.com/o-200/neocities-red
|
|
242
|
+
changelog_uri: https://github.com/o-200/neocities-red/blob/main/CHANGELOG.md
|
|
243
|
+
documentation_uri: https://github.com/o-200/neocities-red#readme
|
|
264
244
|
rdoc_options: []
|
|
265
245
|
require_paths:
|
|
266
246
|
- lib
|
|
@@ -275,7 +255,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
275
255
|
- !ruby/object:Gem::Version
|
|
276
256
|
version: '0'
|
|
277
257
|
requirements: []
|
|
278
|
-
rubygems_version: 4.0.
|
|
258
|
+
rubygems_version: 4.0.16
|
|
279
259
|
specification_version: 4
|
|
280
260
|
summary: Yet Another Neocities.org CLI and API client with improvements
|
|
281
261
|
test_files: []
|