neocities-red 1.1.0 → 1.1.2
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/ISSUE_TEMPLATE/bug_report.md +32 -32
- data/.github/PULL_REQUEST_TEMPLATE.md +18 -18
- data/.github/dependabot.yml +6 -6
- data/.github/workflows/ci.yml +139 -139
- data/.gitignore +38 -38
- data/.rspec +3 -3
- data/.rubocop.yml +43 -43
- data/CODE_OF_CONDUCT.md +128 -128
- data/CONTRIBUTING.md +83 -83
- data/Gemfile +12 -12
- data/Gemfile.lock +194 -193
- data/LICENSE +21 -21
- data/README.md +153 -153
- data/SECURITY.md +7 -7
- data/bin/neocities-red +9 -9
- data/ext/mkrf_conf.rb +21 -21
- data/lib/neocities_red/cli.rb +340 -335
- data/lib/neocities_red/cli_display.rb +281 -271
- data/lib/neocities_red/client.rb +200 -200
- data/lib/neocities_red/services/common/pizza.rb +107 -107
- data/lib/neocities_red/services/file/folder_uploader.rb +65 -65
- data/lib/neocities_red/services/file/list.rb +65 -65
- data/lib/neocities_red/services/file/remover.rb +35 -35
- data/lib/neocities_red/services/file/uploader.rb +45 -45
- data/lib/neocities_red/services/site/differencer.rb +76 -76
- data/lib/neocities_red/services/site/exporter.rb +43 -43
- data/lib/neocities_red/services/site/informer.rb +43 -43
- data/lib/neocities_red/services/site/pusher.rb +146 -146
- data/lib/neocities_red/version.rb +5 -5
- data/lib/neocities_red.rb +17 -17
- data/neocities-red.gemspec +54 -54
- data/spec/neocities_red/cli_display_spec.rb +139 -139
- data/spec/neocities_red/cli_spec.rb +68 -68
- data/spec/neocities_red/client_spec.rb +306 -306
- data/spec/neocities_red/services/common/pizza_spec.rb +26 -26
- data/spec/neocities_red/services/file/folder_uploader_spec.rb +64 -64
- data/spec/neocities_red/services/file/list_spec.rb +177 -177
- data/spec/neocities_red/services/file/remover_spec.rb +125 -125
- data/spec/neocities_red/services/file/uploader_spec.rb +158 -158
- data/spec/neocities_red/services/site/differencer_spec.rb +162 -162
- data/spec/neocities_red/services/site/exporter_spec.rb +116 -116
- data/spec/neocities_red/services/site/informer_spec.rb +180 -180
- data/spec/neocities_red/services/site/pusher_spec.rb +167 -167
- data/spec/spec_helper.rb +20 -20
- metadata +4 -10
data/lib/neocities_red/cli.rb
CHANGED
|
@@ -1,335 +1,340 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "pathname"
|
|
4
|
-
require "tty/table"
|
|
5
|
-
require "tty/prompt"
|
|
6
|
-
require "fileutils"
|
|
7
|
-
require "json"
|
|
8
|
-
require "thor"
|
|
9
|
-
require_relative "cli_display"
|
|
10
|
-
|
|
11
|
-
module NeocitiesRed
|
|
12
|
-
class CLI < Thor
|
|
13
|
-
package_name "neocities-red"
|
|
14
|
-
default_task :help
|
|
15
|
-
map %w[-h --help] => :help
|
|
16
|
-
map %w[-v --version] => :version
|
|
17
|
-
|
|
18
|
-
class_option :api_key,
|
|
19
|
-
type: :string,
|
|
20
|
-
desc: "Use a specific API key instead of reading from env/config"
|
|
21
|
-
|
|
22
|
-
desc "diff [PATH]", "Compare local files with remote and show differences"
|
|
23
|
-
method_option :help, aliases: "-h", type: :boolean
|
|
24
|
-
method_option :ignore_dotfiles, type: :boolean, default: false
|
|
25
|
-
method_option :exclude, aliases: "-e", type: :string, repeatable: true, default: []
|
|
26
|
-
def diff(path = ".")
|
|
27
|
-
return display_help_for("diff") if help_requested?(options[:help], path)
|
|
28
|
-
|
|
29
|
-
client = ensure_client!
|
|
30
|
-
exclude = build_diff_exclusions(path, Array(options[:exclude]))
|
|
31
|
-
|
|
32
|
-
added, modified, removed = Services::Site::Differencer.new(
|
|
33
|
-
client,
|
|
34
|
-
path: path,
|
|
35
|
-
detail: false,
|
|
36
|
-
ignore_dotfiles: options[:ignore_dotfiles],
|
|
37
|
-
exclude: exclude
|
|
38
|
-
).show
|
|
39
|
-
|
|
40
|
-
display.display_diff_results(added: added, modified: modified, removed: removed)
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
desc "delete PATH [PATH ...]", "Delete files on your Neocities site"
|
|
44
|
-
method_option :help, aliases: "-h", type: :boolean
|
|
45
|
-
def delete(*paths)
|
|
46
|
-
return display_help_for("delete") if paths.empty? || help_requested?(options[:help], paths)
|
|
47
|
-
|
|
48
|
-
client = ensure_client!
|
|
49
|
-
paths.each { |path| Services::File::Remover.new(client, path).remove }
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
desc "logout", "Remove the site api key from the config"
|
|
53
|
-
method_option :help, aliases: "-h", type: :boolean
|
|
54
|
-
method_option :yes, aliases: "-y", type: :boolean, default: false
|
|
55
|
-
def logout
|
|
56
|
-
return display_help_for("logout") if help_requested?(options[:help]) || !options[:yes]
|
|
57
|
-
|
|
58
|
-
FileUtils.rm_f(app_config_path)
|
|
59
|
-
display.display_logout_success
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
desc "info [SITENAME]", "Get site info"
|
|
63
|
-
method_option :help, aliases: "-h", type: :boolean
|
|
64
|
-
def info(sitename = nil)
|
|
65
|
-
return display_help_for("info") if help_requested?(options[:help], sitename)
|
|
66
|
-
|
|
67
|
-
client = ensure_client!
|
|
68
|
-
profile_info = Services::Site::Informer.new(client, [sitename].compact, @sitename).pretty_print
|
|
69
|
-
display.say TTY::Table.new(profile_info)
|
|
70
|
-
rescue StandardError => e
|
|
71
|
-
display.display_response(e)
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
desc "list [PATH]", "List files on your Neocities site"
|
|
75
|
-
method_option :help, aliases: "-h", type: :boolean
|
|
76
|
-
method_option :detail, aliases: "-d", type: :boolean, default: false
|
|
77
|
-
method_option :all, aliases: "-a", type: :boolean, default: false
|
|
78
|
-
def list(path = nil)
|
|
79
|
-
if help_requested?(options[:help], path) || (path.nil? && options[:all].nil? && options[:detail].nil?)
|
|
80
|
-
display_help_for("list")
|
|
81
|
-
return
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
client = ensure_client!
|
|
85
|
-
path = nil if options[:all]
|
|
86
|
-
display.say Services::File::List.new(client, path, options[:detail]).show
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
desc "push PATH", "Recursively upload a local directory to your Neocities site"
|
|
90
|
-
method_option :help, aliases: "-h", type: :boolean
|
|
91
|
-
method_option :no_gitignore, type: :boolean, default: false
|
|
92
|
-
method_option :ignore_dotfiles, type: :boolean, default: false
|
|
93
|
-
method_option :exclude, aliases: "-e", type: :string, repeatable: true, default: []
|
|
94
|
-
method_option :dry_run, type: :boolean, default: false
|
|
95
|
-
method_option :prune, type: :boolean, default: false
|
|
96
|
-
method_option :optimized, type: :boolean, default: false
|
|
97
|
-
def push(root = nil)
|
|
98
|
-
return display_help_for("push") if help_requested?(options[:help], root)
|
|
99
|
-
|
|
100
|
-
client = ensure_client!
|
|
101
|
-
return display_help_for("push") if root.nil?
|
|
102
|
-
|
|
103
|
-
Services::Site::Pusher.new(
|
|
104
|
-
client,
|
|
105
|
-
display,
|
|
106
|
-
root: root,
|
|
107
|
-
no_gitignore: options[:no_gitignore],
|
|
108
|
-
ignore_dotfiles: options[:ignore_dotfiles],
|
|
109
|
-
exclude: Array(options[:exclude]),
|
|
110
|
-
dry_run: options[:dry_run],
|
|
111
|
-
prune: options[:prune],
|
|
112
|
-
optimized: options[:optimized]
|
|
113
|
-
).push
|
|
114
|
-
rescue ArgumentError => e
|
|
115
|
-
display.display_response(result: "error", message: e.message)
|
|
116
|
-
display_help_for("push")
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
desc "upload LOCAL_PATH REMOTE_PATH", "Upload a file/folder to your Neocities site"
|
|
120
|
-
method_option :help, aliases: "-h", type: :boolean
|
|
121
|
-
def upload(local_path = nil, remote_path = nil)
|
|
122
|
-
return display_help_for("upload") if help_requested?(options[:help], [local_path, remote_path])
|
|
123
|
-
return display_help_for("upload") if local_path.nil?
|
|
124
|
-
|
|
125
|
-
client = ensure_client!
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
folder_uploader.
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
method_option :
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
resp
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
end
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
when :
|
|
196
|
-
return File.join(ENV["
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
end
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
excludes
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "pathname"
|
|
4
|
+
require "tty/table"
|
|
5
|
+
require "tty/prompt"
|
|
6
|
+
require "fileutils"
|
|
7
|
+
require "json"
|
|
8
|
+
require "thor"
|
|
9
|
+
require_relative "cli_display"
|
|
10
|
+
|
|
11
|
+
module NeocitiesRed
|
|
12
|
+
class CLI < Thor
|
|
13
|
+
package_name "neocities-red"
|
|
14
|
+
default_task :help
|
|
15
|
+
map %w[-h --help] => :help
|
|
16
|
+
map %w[-v --version] => :version
|
|
17
|
+
|
|
18
|
+
class_option :api_key,
|
|
19
|
+
type: :string,
|
|
20
|
+
desc: "Use a specific API key instead of reading from env/config"
|
|
21
|
+
|
|
22
|
+
desc "diff [PATH]", "Compare local files with remote and show differences"
|
|
23
|
+
method_option :help, aliases: "-h", type: :boolean
|
|
24
|
+
method_option :ignore_dotfiles, type: :boolean, default: false
|
|
25
|
+
method_option :exclude, aliases: "-e", type: :string, repeatable: true, default: []
|
|
26
|
+
def diff(path = ".")
|
|
27
|
+
return display_help_for("diff") if help_requested?(options[:help], path)
|
|
28
|
+
|
|
29
|
+
client = ensure_client!
|
|
30
|
+
exclude = build_diff_exclusions(path, Array(options[:exclude]))
|
|
31
|
+
|
|
32
|
+
added, modified, removed = Services::Site::Differencer.new(
|
|
33
|
+
client,
|
|
34
|
+
path: path,
|
|
35
|
+
detail: false,
|
|
36
|
+
ignore_dotfiles: options[:ignore_dotfiles],
|
|
37
|
+
exclude: exclude
|
|
38
|
+
).show
|
|
39
|
+
|
|
40
|
+
display.display_diff_results(added: added, modified: modified, removed: removed)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
desc "delete PATH [PATH ...]", "Delete files on your Neocities site"
|
|
44
|
+
method_option :help, aliases: "-h", type: :boolean
|
|
45
|
+
def delete(*paths)
|
|
46
|
+
return display_help_for("delete") if paths.empty? || help_requested?(options[:help], paths)
|
|
47
|
+
|
|
48
|
+
client = ensure_client!
|
|
49
|
+
paths.each { |path| Services::File::Remover.new(client, path).remove }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
desc "logout", "Remove the site api key from the config"
|
|
53
|
+
method_option :help, aliases: "-h", type: :boolean
|
|
54
|
+
method_option :yes, aliases: "-y", type: :boolean, default: false
|
|
55
|
+
def logout
|
|
56
|
+
return display_help_for("logout") if help_requested?(options[:help]) || !options[:yes]
|
|
57
|
+
|
|
58
|
+
FileUtils.rm_f(app_config_path)
|
|
59
|
+
display.display_logout_success
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
desc "info [SITENAME]", "Get site info"
|
|
63
|
+
method_option :help, aliases: "-h", type: :boolean
|
|
64
|
+
def info(sitename = nil)
|
|
65
|
+
return display_help_for("info") if help_requested?(options[:help], sitename)
|
|
66
|
+
|
|
67
|
+
client = ensure_client!
|
|
68
|
+
profile_info = Services::Site::Informer.new(client, [sitename].compact, @sitename).pretty_print
|
|
69
|
+
display.say TTY::Table.new(profile_info)
|
|
70
|
+
rescue StandardError => e
|
|
71
|
+
display.display_response(e)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
desc "list [PATH]", "List files on your Neocities site"
|
|
75
|
+
method_option :help, aliases: "-h", type: :boolean
|
|
76
|
+
method_option :detail, aliases: "-d", type: :boolean, default: false
|
|
77
|
+
method_option :all, aliases: "-a", type: :boolean, default: false
|
|
78
|
+
def list(path = nil)
|
|
79
|
+
if help_requested?(options[:help], path) || (path.nil? && options[:all].nil? && options[:detail].nil?)
|
|
80
|
+
display_help_for("list")
|
|
81
|
+
return
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
client = ensure_client!
|
|
85
|
+
path = nil if options[:all]
|
|
86
|
+
display.say Services::File::List.new(client, path, options[:detail]).show
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
desc "push PATH", "Recursively upload a local directory to your Neocities site"
|
|
90
|
+
method_option :help, aliases: "-h", type: :boolean
|
|
91
|
+
method_option :no_gitignore, type: :boolean, default: false
|
|
92
|
+
method_option :ignore_dotfiles, type: :boolean, default: false
|
|
93
|
+
method_option :exclude, aliases: "-e", type: :string, repeatable: true, default: []
|
|
94
|
+
method_option :dry_run, type: :boolean, default: false
|
|
95
|
+
method_option :prune, type: :boolean, default: false
|
|
96
|
+
method_option :optimized, type: :boolean, default: false
|
|
97
|
+
def push(root = nil)
|
|
98
|
+
return display_help_for("push") if help_requested?(options[:help], root)
|
|
99
|
+
|
|
100
|
+
client = ensure_client!
|
|
101
|
+
return display_help_for("push") if root.nil?
|
|
102
|
+
|
|
103
|
+
Services::Site::Pusher.new(
|
|
104
|
+
client,
|
|
105
|
+
display,
|
|
106
|
+
root: root,
|
|
107
|
+
no_gitignore: options[:no_gitignore],
|
|
108
|
+
ignore_dotfiles: options[:ignore_dotfiles],
|
|
109
|
+
exclude: Array(options[:exclude]),
|
|
110
|
+
dry_run: options[:dry_run],
|
|
111
|
+
prune: options[:prune],
|
|
112
|
+
optimized: options[:optimized]
|
|
113
|
+
).push
|
|
114
|
+
rescue ArgumentError => e
|
|
115
|
+
display.display_response(result: "error", message: e.message)
|
|
116
|
+
display_help_for("push")
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
desc "upload LOCAL_PATH [REMOTE_PATH]", "Upload a file/folder to your Neocities site"
|
|
120
|
+
method_option :help, aliases: "-h", type: :boolean
|
|
121
|
+
def upload(local_path = nil, remote_path = nil)
|
|
122
|
+
return display_help_for("upload") if help_requested?(options[:help], [local_path, remote_path])
|
|
123
|
+
return display_help_for("upload") if local_path.nil?
|
|
124
|
+
|
|
125
|
+
client = ensure_client!
|
|
126
|
+
dest = remote_path || File.basename(local_path)
|
|
127
|
+
if File.file?(local_path)
|
|
128
|
+
Services::File::Uploader.new(client, local_path, dest).upload
|
|
129
|
+
elsif File.directory?(local_path)
|
|
130
|
+
folder_uploader = Services::File::FolderUploader.new(client, local_path, dest)
|
|
131
|
+
files_list = folder_uploader.files
|
|
132
|
+
folder_uploader.upload(files_list)
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
desc "pull", "Get the most recent version of files from your site"
|
|
137
|
+
method_option :help, aliases: "-h", type: :boolean
|
|
138
|
+
method_option :quiet, aliases: "-q", type: :boolean, default: false
|
|
139
|
+
def pull
|
|
140
|
+
return display_help_for("pull") if help_requested?(options[:help])
|
|
141
|
+
|
|
142
|
+
client = ensure_client!
|
|
143
|
+
data = read_config || {}
|
|
144
|
+
|
|
145
|
+
last_pull_time = data.dig("LAST_PULL", "time")
|
|
146
|
+
last_pull_loc = data.dig("LAST_PULL", "loc")
|
|
147
|
+
|
|
148
|
+
Services::Site::Exporter.new(client, @sitename, data, app_config_path)
|
|
149
|
+
.export(quiet: options[:quiet], last_pull_time: last_pull_time, last_pull_loc: last_pull_loc)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
desc "purge", "Delete everything from your site (development only)"
|
|
153
|
+
method_option :yes, aliases: "-y", type: :boolean, default: false
|
|
154
|
+
def purge
|
|
155
|
+
return display_help_for("purge") unless options[:yes]
|
|
156
|
+
|
|
157
|
+
client = ensure_client!
|
|
158
|
+
resp = client.list
|
|
159
|
+
deleted_dirs = []
|
|
160
|
+
resp[:files].sort_by { |f| f[:is_directory] ? 0 : 1 }.each do |file|
|
|
161
|
+
next if deleted_dirs.any? { |dir| file[:path].start_with?(dir) }
|
|
162
|
+
|
|
163
|
+
display.display_delete_progress(file[:path])
|
|
164
|
+
delete_resp = client.delete_wrapper_with_dry_run(file[:path], dry_run: options[:dry_run])
|
|
165
|
+
|
|
166
|
+
if delete_resp[:result] == "success"
|
|
167
|
+
deleted_dirs << file[:path] if file[:is_directory]
|
|
168
|
+
display.display_delete_success
|
|
169
|
+
else
|
|
170
|
+
display.display_delete_error(delete_resp)
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
desc "pizza", "Order a free pizza"
|
|
176
|
+
def pizza
|
|
177
|
+
display_help_for(__method__)
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def self.app_config_path(name)
|
|
181
|
+
platform = case RUBY_PLATFORM
|
|
182
|
+
when /cygwin|mswin|mingw|bccwin|wince|emx|win32/
|
|
183
|
+
:windows
|
|
184
|
+
when /darwin/
|
|
185
|
+
:darwin
|
|
186
|
+
when /linux/
|
|
187
|
+
:linux
|
|
188
|
+
when /freebsd/
|
|
189
|
+
:freebsd
|
|
190
|
+
else
|
|
191
|
+
:unknown
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
case platform
|
|
195
|
+
when :linux
|
|
196
|
+
return File.join(ENV["XDG_CONFIG_HOME"], name) if ENV["XDG_CONFIG_HOME"]
|
|
197
|
+
return File.join(Dir.home, ".config", name) if Dir.home
|
|
198
|
+
when :darwin
|
|
199
|
+
return File.join(Dir.home, "Library", "Application Support", name) if Dir.home
|
|
200
|
+
when :windows
|
|
201
|
+
return File.join(ENV["LOCALAPPDATA"], name) if ENV["LOCALAPPDATA"]
|
|
202
|
+
|
|
203
|
+
if ENV["USERPROFILE"]
|
|
204
|
+
return File.join(
|
|
205
|
+
ENV["USERPROFILE"],
|
|
206
|
+
"AppData",
|
|
207
|
+
"Local",
|
|
208
|
+
name
|
|
209
|
+
)
|
|
210
|
+
end
|
|
211
|
+
else
|
|
212
|
+
# FreeBSD and other unknown UNIX-like systems use dotfile directly in home directory
|
|
213
|
+
return File.join(Dir.home, ".#{name}") if Dir.home
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
nil
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
desc "help [COMMAND]", "Show help for a command"
|
|
220
|
+
def help(command = nil)
|
|
221
|
+
return display.display_help_and_exit if command.nil?
|
|
222
|
+
|
|
223
|
+
custom_help_method = "display_#{command}_help_and_exit"
|
|
224
|
+
return display.public_send(custom_help_method) if display.respond_to?(custom_help_method)
|
|
225
|
+
|
|
226
|
+
super
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
desc "version", "Display neocities-red version"
|
|
230
|
+
def version
|
|
231
|
+
display.say NeocitiesRed::VERSION
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
no_commands do
|
|
235
|
+
alias_method :display_help_for, :help
|
|
236
|
+
|
|
237
|
+
def display
|
|
238
|
+
@display ||= NeocitiesRed::CliDisplay.new
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def prompt
|
|
242
|
+
@prompt ||= TTY::Prompt.new
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def app_config_path
|
|
246
|
+
@app_config_path ||= File.join(self.class.app_config_path("neocities"), "config.json")
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
def read_config
|
|
250
|
+
file = File.read(app_config_path)
|
|
251
|
+
JSON.parse(file)
|
|
252
|
+
rescue Errno::ENOENT
|
|
253
|
+
nil
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
def ensure_client!
|
|
257
|
+
return @client if @client
|
|
258
|
+
|
|
259
|
+
config = read_config
|
|
260
|
+
@sitename = config && config["SITENAME"]
|
|
261
|
+
@last_pull = config && config["LAST_PULL"]
|
|
262
|
+
|
|
263
|
+
@api_key = options[:api_key] || ENV.fetch("NEOCITIES_API_KEY", nil)
|
|
264
|
+
@api_key ||= config && config["API_KEY"]&.strip
|
|
265
|
+
|
|
266
|
+
if @api_key.nil? || @api_key.empty?
|
|
267
|
+
authenticate_and_persist_key!
|
|
268
|
+
else
|
|
269
|
+
@client = NeocitiesRed::Client.new(api_key: @api_key)
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
@client
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
def authenticate_and_persist_key!
|
|
276
|
+
display.display_login_prompt
|
|
277
|
+
|
|
278
|
+
@sitename ||= prompt.ask("sitename/username:", default: ENV.fetch("NEOCITIES_SITENAME", nil))
|
|
279
|
+
password = prompt.mask("password:", default: ENV.fetch("NEOCITIES_PASSWORD", nil))
|
|
280
|
+
|
|
281
|
+
temp_client = NeocitiesRed::Client.new(sitename: @sitename, password: password)
|
|
282
|
+
resp = temp_client.key
|
|
283
|
+
|
|
284
|
+
unless resp[:api_key]
|
|
285
|
+
display.display_response(resp)
|
|
286
|
+
raise Thor::Error, "failed to obtain API key"
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
@api_key = resp[:api_key]
|
|
290
|
+
conf = {
|
|
291
|
+
API_KEY: @api_key,
|
|
292
|
+
SITENAME: @sitename
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
FileUtils.mkdir_p(Pathname(app_config_path).dirname)
|
|
296
|
+
File.write(app_config_path, conf.to_json)
|
|
297
|
+
display.display_api_key_saved(@sitename, app_config_path)
|
|
298
|
+
@client = NeocitiesRed::Client.new(api_key: @api_key)
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
def build_diff_exclusions(base_path, excluded_entries)
|
|
302
|
+
base = Pathname.new(base_path).expand_path
|
|
303
|
+
excludes = []
|
|
304
|
+
|
|
305
|
+
excluded_entries.each do |entry|
|
|
306
|
+
target = Pathname.new(entry).expand_path
|
|
307
|
+
next unless target.exist?
|
|
308
|
+
|
|
309
|
+
filepath = target.relative_path_from(base).to_s
|
|
310
|
+
|
|
311
|
+
if File.file?(target)
|
|
312
|
+
excludes << filepath
|
|
313
|
+
elsif File.directory?(target)
|
|
314
|
+
excludes.concat(
|
|
315
|
+
Dir.glob(File.join(target, "**", "*"), File::FNM_DOTMATCH).map do |path|
|
|
316
|
+
Pathname.new(path).expand_path.relative_path_from(base).to_s
|
|
317
|
+
end
|
|
318
|
+
)
|
|
319
|
+
excludes << filepath
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
excludes
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
def help_requested_for?(value)
|
|
327
|
+
case value
|
|
328
|
+
when Array
|
|
329
|
+
value.intersect?(["-h", "--help", "help"])
|
|
330
|
+
else
|
|
331
|
+
["-h", "--help", "help"].include?(value)
|
|
332
|
+
end
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
def help_requested?(help_option, value = nil)
|
|
336
|
+
help_option || (value && help_requested_for?(value))
|
|
337
|
+
end
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
end
|