dgd-tools 0.1.6 → 0.1.7
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/Gemfile.lock +3 -1
- data/README.md +14 -0
- data/dgd-tools.gemspec +1 -0
- data/exe/dgd-manifest +11 -0
- data/exe/skotos-xml-diff +16 -17
- data/goods/chattheatre_kernellib.goods +12 -0
- data/lib/dgd-tools/manifest.rb +169 -54
- data/lib/dgd-tools/skotos_xml_obj.rb +116 -16
- data/lib/dgd-tools/version.rb +1 -1
- metadata +17 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2b3639fa674b53796ffe654f0e7e0deb9506868eece4550b99b4f28b98940e97
|
|
4
|
+
data.tar.gz: b0f115747b8f790ba079a9789d18e5bbe024de6e9b1c6cc1c476d21066a1b48a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c739260975e503e32a44bfeaf4775d6693e606f35a247f6d432008d0b9e813ac7b29208d1db641dee46be7aec8bbb86e92c1f8fe7e9c7b1c2aadb2ce93e4fb8e
|
|
7
|
+
data.tar.gz: 50cc3537969a52ca379857a8936b900212e18567bdc10c1cb1152cffb7901f88db53b75a04126b8848e0edb3151d74a4514cc3fe02d7c1ae1f0ece0cbbe7d6f3
|
data/Gemfile.lock
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
dgd-tools (0.1.
|
|
4
|
+
dgd-tools (0.1.7)
|
|
5
5
|
nokogiri (~> 1.10.5)
|
|
6
|
+
optimist (~> 3.0.1)
|
|
6
7
|
|
|
7
8
|
GEM
|
|
8
9
|
remote: https://rubygems.org/
|
|
@@ -11,6 +12,7 @@ GEM
|
|
|
11
12
|
minitest (5.14.2)
|
|
12
13
|
nokogiri (1.10.10)
|
|
13
14
|
mini_portile2 (~> 2.4.0)
|
|
15
|
+
optimist (3.0.1)
|
|
14
16
|
rake (12.3.3)
|
|
15
17
|
|
|
16
18
|
PLATFORMS
|
data/README.md
CHANGED
|
@@ -14,6 +14,18 @@ DGD Manifest is a simple initial library system. I'm sure I'll figure more out a
|
|
|
14
14
|
|
|
15
15
|
This work has grown out of [SkotOS and ChatTheatre](https://github.com/ChatTheatre) tasks.
|
|
16
16
|
|
|
17
|
+
You can find example DGD manifest files under the "test" directory and also in [various](https://github.com/noahgibbs/prototype_vRWOT) [SkotOS-based games](https://github.com/ChatTheatre/gables_game) that use the DGD Manifest system.
|
|
18
|
+
|
|
19
|
+
You can find example "goods" (library) files under the "goods" subdirectory of this repo.
|
|
20
|
+
|
|
21
|
+
## WOE Objects and skotos-xml-diff
|
|
22
|
+
|
|
23
|
+
SkotOS-based games use an XML format for in-game objects called WOE, which is [documented in SkotOS-Doc](https://ChatTheatre.github.io/SkotOS-Doc). The skotos-xml-diff utility will diff between WOE objects or directories of WOE objects.
|
|
24
|
+
|
|
25
|
+
See SkotOS-Doc for more detail about how this can be used with a SkotOS game.
|
|
26
|
+
|
|
27
|
+
Run "skotos-xml-diff --help" for a list of options. You can tell it to ignore whitespace, to diff only the Merry (script) contents of the objects, and to ignore certain XML node types.
|
|
28
|
+
|
|
17
29
|
## Installation
|
|
18
30
|
|
|
19
31
|
You would normally install DGDTools directly: `gem install dgd-tools`.
|
|
@@ -26,6 +38,8 @@ If you have a DGD application that uses DGD Manifest, run `dgd-manifest install`
|
|
|
26
38
|
|
|
27
39
|
That fully-assembled DGD directory is named ".root". To run your dgd server, type "dgd-manifest server".
|
|
28
40
|
|
|
41
|
+
If you update files in your root and want to update files under the generated root directory, use "dgd-manifest update".
|
|
42
|
+
|
|
29
43
|
## Using DGD Manifest with your DGD Application
|
|
30
44
|
|
|
31
45
|
Your app will need a dgd.manifest file, which is a lot like NPM's package.json file.
|
data/dgd-tools.gemspec
CHANGED
data/exe/dgd-manifest
CHANGED
|
@@ -51,6 +51,17 @@ when "install"
|
|
|
51
51
|
repo.precheck(current_dir)
|
|
52
52
|
repo.assemble_app(current_dir)
|
|
53
53
|
puts "Assembled DGD application into #{current_dir}"
|
|
54
|
+
when "update"
|
|
55
|
+
unless File.exist?("dgd.manifest")
|
|
56
|
+
raise "I don't see a dgd.manifest file in this directory!"
|
|
57
|
+
end
|
|
58
|
+
puts "Running DGD Manifest installer..."
|
|
59
|
+
repo = DGD::Manifest::Repo.new
|
|
60
|
+
repo.manifest_file("dgd.manifest")
|
|
61
|
+
current_dir = File.expand_path(".")
|
|
62
|
+
repo.precheck(current_dir)
|
|
63
|
+
repo.update_app(current_dir)
|
|
64
|
+
puts "Updated DGD application in #{current_dir}"
|
|
54
65
|
when "server"
|
|
55
66
|
puts "Starting DGD server..."
|
|
56
67
|
DGD::Manifest.system_call("~/.dgd-tools/dgd/bin/dgd dgd.config")
|
data/exe/skotos-xml-diff
CHANGED
|
@@ -4,28 +4,27 @@
|
|
|
4
4
|
# SkotOS-or-similar game to find out what updates should
|
|
5
5
|
# be merged between them.
|
|
6
6
|
|
|
7
|
+
require 'optimist'
|
|
7
8
|
require "dgd-tools/skotos_xml_obj"
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
10
|
+
OPTS = Optimist::options do
|
|
11
|
+
version "DGD-tools version #{DGD::VERSION}"
|
|
12
|
+
banner <<BANNER
|
|
13
|
+
Usage:
|
|
14
|
+
skotos-xml-diff [options] <file_or_dir_1> <file_or_dir_2>
|
|
15
|
+
where [options] are:
|
|
16
|
+
BANNER
|
|
17
|
+
opt :merry_only, "Only diff Merry scripts"
|
|
18
|
+
opt :ignore_whitespace, "Ignore whitespace in final diff"
|
|
19
|
+
opt :ignore_types, "Comma-separated list of XML node types to ignore (e.g. Combat:Base,Base:Exit)", type: :string
|
|
18
20
|
end
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
exit -1
|
|
23
|
-
end
|
|
22
|
+
Optimist::die "Supply exactly two files or directories -- you supplied #{ARGV.size}!" unless ARGV.size == 2
|
|
23
|
+
Optimist::die "Supply both files or both directories, not one of each!" if File.directory?(ARGV[0]) ^ File.directory?(ARGV[1])
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
end
|
|
25
|
+
SkotOS::XMLObject.merry_only = true if OPTS[:merry_only]
|
|
26
|
+
SkotOS::XMLObject.ignore_whitespace = true if OPTS[:ignore_whitespace]
|
|
27
|
+
SkotOS::XMLObject.ignore_types = OPTS[:ignore_types].split(",") if OPTS[:ignore_types]
|
|
29
28
|
|
|
30
29
|
if File.directory?(ARGV[0])
|
|
31
30
|
diff = SkotOS::XMLObject.diff_dirs(*ARGV)
|
data/lib/dgd-tools/manifest.rb
CHANGED
|
@@ -16,7 +16,6 @@ module DGD::Manifest
|
|
|
16
16
|
}
|
|
17
17
|
KERNEL_PATHS = KERNEL_PATH_MAP.values
|
|
18
18
|
DEFAULT_KERNELLIB_URL = "https://github.com/ChatTheatre/kernellib"
|
|
19
|
-
|
|
20
19
|
GENERATED_ROOT = ".root"
|
|
21
20
|
|
|
22
21
|
def self.system_call(cmd)
|
|
@@ -78,12 +77,12 @@ module DGD::Manifest
|
|
|
78
77
|
raise("No manifest file!") if @no_manifest_file
|
|
79
78
|
|
|
80
79
|
@manifest_file.specs.each do |spec|
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
spec_git_repo = spec.source
|
|
81
|
+
spec_git_repo.use_details(spec.source_details) # This sets things like checked-out branch
|
|
83
82
|
|
|
84
83
|
spec.paths.each do |from, to|
|
|
85
|
-
# Note:
|
|
86
|
-
from_path = "#{
|
|
84
|
+
# Note: spec_git_repo.local_dir is an absolute path.
|
|
85
|
+
from_path = "#{spec_git_repo.local_dir}/#{from}"
|
|
87
86
|
if File.directory?(from_path)
|
|
88
87
|
files = Dir["#{from_path}/**/*"].to_a + Dir["#{from_path}/**/.*"].to_a
|
|
89
88
|
dirs = files.select { |file| File.directory?(file) }
|
|
@@ -95,13 +94,13 @@ module DGD::Manifest
|
|
|
95
94
|
no_wild_from_path = components[0..(first_wild_idx-1)].join("/")
|
|
96
95
|
wild_path = components[first_wild_idx..-1].join("/")
|
|
97
96
|
|
|
98
|
-
files = Dir["#{
|
|
97
|
+
files = Dir["#{spec_git_repo.local_dir}/#{no_wild_from_path}/#{wild_path}"].to_a
|
|
99
98
|
dirs = files.select { |file| File.directory?(file) }
|
|
100
99
|
dirs += files.map { |f| File.dirname(f) }
|
|
101
100
|
dirs.uniq!
|
|
102
101
|
|
|
103
102
|
non_dirs = files - dirs
|
|
104
|
-
operations << { cmd: "cp", from: "#{
|
|
103
|
+
operations << { cmd: "cp", from: "#{spec_git_repo.local_dir}/#{no_wild_from_path}", to: to, dirs: dirs, non_dirs: non_dirs, comment: :path_wildcard }
|
|
105
104
|
else
|
|
106
105
|
# A single file
|
|
107
106
|
operations << { cmd: "cp", from: from_path, to: to, dirs: [], non_dirs: [from_path], comment: :single_file }
|
|
@@ -122,16 +121,29 @@ module DGD::Manifest
|
|
|
122
121
|
|
|
123
122
|
public
|
|
124
123
|
|
|
124
|
+
def dgd_root(location)
|
|
125
|
+
"#{File.expand_path(location)}/#{GENERATED_ROOT}"
|
|
126
|
+
end
|
|
127
|
+
|
|
125
128
|
def assemble_app(location)
|
|
126
|
-
|
|
127
|
-
|
|
129
|
+
Dir[File.join(dgd_root(location), "*")].each { |dir| FileUtils.rm_rf dir }
|
|
130
|
+
|
|
131
|
+
write_app_files(location)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def update_app(location)
|
|
135
|
+
write_app_files(location) # TODO: maybe check files dates? Some way to do update-only
|
|
136
|
+
end
|
|
128
137
|
|
|
138
|
+
protected
|
|
139
|
+
|
|
140
|
+
def write_app_files(location)
|
|
129
141
|
Dir.chdir(location) do
|
|
130
142
|
write_config_file("#{location}/dgd.config")
|
|
131
143
|
FileUtils.mkdir_p("#{location}/state") # Statedir for statedumps, editor files, etc.
|
|
132
144
|
|
|
133
145
|
assembly_operations(location).each do |sd_hash|
|
|
134
|
-
to_path = "#{dgd_root}/#{sd_hash[:to]}"
|
|
146
|
+
to_path = "#{dgd_root(location)}/#{sd_hash[:to]}"
|
|
135
147
|
|
|
136
148
|
# Make appropriate dirs, including empty ones
|
|
137
149
|
sd_hash[:dirs].each do |dir|
|
|
@@ -140,7 +152,7 @@ module DGD::Manifest
|
|
|
140
152
|
|
|
141
153
|
# Copy all files
|
|
142
154
|
sd_hash[:non_dirs].each do |from_file|
|
|
143
|
-
to_file = from_file.sub(sd_hash[:from], "#{dgd_root}/#{sd_hash[:to]}")
|
|
155
|
+
to_file = from_file.sub(sd_hash[:from], "#{dgd_root(location)}/#{sd_hash[:to]}")
|
|
144
156
|
to_dir = File.dirname(to_file)
|
|
145
157
|
FileUtils.mkdir_p to_dir
|
|
146
158
|
FileUtils.cp from_file, to_file
|
|
@@ -149,6 +161,8 @@ module DGD::Manifest
|
|
|
149
161
|
end
|
|
150
162
|
end
|
|
151
163
|
|
|
164
|
+
public
|
|
165
|
+
|
|
152
166
|
def precheck(location)
|
|
153
167
|
all_files = assembly_operations(location).flat_map { |sd| sd[:non_dirs] }
|
|
154
168
|
|
|
@@ -160,40 +174,7 @@ module DGD::Manifest
|
|
|
160
174
|
|
|
161
175
|
def write_config_file(path)
|
|
162
176
|
File.open(path, "wb") do |f|
|
|
163
|
-
f.write
|
|
164
|
-
/* These are SkotOS limits. They are larger than you are likely to need. They should
|
|
165
|
-
be configurable but they are not yet. */
|
|
166
|
-
telnet_port = ([
|
|
167
|
-
"*":50100 /* telnet port number */
|
|
168
|
-
]);
|
|
169
|
-
binary_port = ([
|
|
170
|
-
"*":50110 /* Failsafe */
|
|
171
|
-
]); /* binary ports */
|
|
172
|
-
directory = "./#{GENERATED_ROOT}";
|
|
173
|
-
|
|
174
|
-
users = 100; /* max # of users */
|
|
175
|
-
editors = 40; /* max # of editor sessions */
|
|
176
|
-
ed_tmpfile = "../state/ed"; /* proto editor tmpfile */
|
|
177
|
-
swap_file = "../state/swap"; /* swap file */
|
|
178
|
-
swap_size = 1048576; /* # sectors in swap file */
|
|
179
|
-
sector_size = 512; /* swap sector size */
|
|
180
|
-
swap_fragment = 4096; /* fragment to swap out */
|
|
181
|
-
static_chunk = 64512; /* static memory chunk */
|
|
182
|
-
dynamic_chunk = 261120; /* dynamic memory chunk */
|
|
183
|
-
dump_file = "../state/dump"; /* dump file */
|
|
184
|
-
dump_interval = 3600; /* dump interval */
|
|
185
|
-
|
|
186
|
-
typechecking = 2; /* highest level of typechecking */
|
|
187
|
-
include_file = "/include/std.h"; /* standard include file */
|
|
188
|
-
include_dirs = ({ "/include", "~/include" }); /* directories to search */
|
|
189
|
-
auto_object = "/kernel/lib/auto"; /* auto inherited object */
|
|
190
|
-
driver_object = "/kernel/sys/driver"; /* driver object */
|
|
191
|
-
create = "_F_create"; /* name of create function */
|
|
192
|
-
|
|
193
|
-
array_size = 16384; /* max array size */
|
|
194
|
-
objects = 262144; /* max # of objects */
|
|
195
|
-
call_outs = 16384; /* max # of call_outs */
|
|
196
|
-
CONTENTS
|
|
177
|
+
f.write @manifest_file.dgd_config.as_file
|
|
197
178
|
end
|
|
198
179
|
end
|
|
199
180
|
end
|
|
@@ -226,11 +207,11 @@ CONTENTS
|
|
|
226
207
|
def use_details(details)
|
|
227
208
|
if details["branch"]
|
|
228
209
|
Dir.chdir(@local_dir) do
|
|
229
|
-
DGD::Manifest.system_call("git checkout #{details["branch"]}")
|
|
210
|
+
DGD::Manifest.system_call("git checkout #{details["branch"]} && git pull")
|
|
230
211
|
end
|
|
231
212
|
else
|
|
232
213
|
Dir.chdir(@local_dir) do
|
|
233
|
-
DGD::Manifest.system_call("git checkout #{default_branch}")
|
|
214
|
+
DGD::Manifest.system_call("git checkout #{default_branch} && git pull")
|
|
234
215
|
end
|
|
235
216
|
end
|
|
236
217
|
end
|
|
@@ -240,7 +221,7 @@ CONTENTS
|
|
|
240
221
|
attr_reader :path
|
|
241
222
|
attr_reader :repo
|
|
242
223
|
attr_reader :specs
|
|
243
|
-
attr_reader :
|
|
224
|
+
attr_reader :dgd_config
|
|
244
225
|
|
|
245
226
|
def initialize(repo, path)
|
|
246
227
|
@path = path
|
|
@@ -250,8 +231,6 @@ CONTENTS
|
|
|
250
231
|
|
|
251
232
|
read_manifest_file(contents)
|
|
252
233
|
|
|
253
|
-
@app_root = contents["app_root"] || "app"
|
|
254
|
-
|
|
255
234
|
output_paths = @specs.flat_map { |s| s.paths.values }
|
|
256
235
|
unless output_paths == output_paths.uniq
|
|
257
236
|
repeated_paths = output_paths.select { |p| output_paths.count(p) > 1 }
|
|
@@ -267,9 +246,9 @@ CONTENTS
|
|
|
267
246
|
#else
|
|
268
247
|
# puts "This dgd.manifest needs the default Kernel Library."
|
|
269
248
|
# # This app has specified no kernellib paths -- add them
|
|
270
|
-
#
|
|
249
|
+
# spec_git_repo = @repo.git_repo(DEFAULT_KERNELLIB_URL)
|
|
271
250
|
# klib_spec = GoodsSpec.new @repo, name: "default Kernel Library",
|
|
272
|
-
# source:
|
|
251
|
+
# source: spec_git_repo, paths: KERNEL_PATH_MAP
|
|
273
252
|
# specs.unshift klib_spec
|
|
274
253
|
#end
|
|
275
254
|
|
|
@@ -298,6 +277,8 @@ CONTENTS
|
|
|
298
277
|
|
|
299
278
|
@specs = []
|
|
300
279
|
|
|
280
|
+
@dgd_config = DGDRuntimeConfig.new (contents["config"] || {})
|
|
281
|
+
|
|
301
282
|
if contents["unbundled_goods"]
|
|
302
283
|
raise "Unbundled_goods must be an array!" unless contents["unbundled_goods"].is_a?(Array)
|
|
303
284
|
|
|
@@ -319,9 +300,15 @@ CONTENTS
|
|
|
319
300
|
end
|
|
320
301
|
end
|
|
321
302
|
|
|
303
|
+
def app_root
|
|
304
|
+
@dgd_config.app_root
|
|
305
|
+
end
|
|
306
|
+
|
|
322
307
|
def unbundled_json_to_spec(fields)
|
|
323
308
|
source = nil
|
|
324
309
|
source_details = nil
|
|
310
|
+
dependencies = []
|
|
311
|
+
|
|
325
312
|
if fields["git"]
|
|
326
313
|
raise "A git source requires a git url: #{fields.inspect}!" unless fields["git"]["url"]
|
|
327
314
|
source = @repo.git_repo(fields["git"]["url"])
|
|
@@ -334,7 +321,23 @@ CONTENTS
|
|
|
334
321
|
raise "Paths in Goods files must map strings to strings! #{fields["paths"].inspect}"
|
|
335
322
|
end
|
|
336
323
|
|
|
337
|
-
|
|
324
|
+
if fields["dependencies"]
|
|
325
|
+
# For now, permit a single string as a dependency.
|
|
326
|
+
fields["dependencies"] = [ fields["dependencies"] ] if fields["dependencies"].is_a?(String)
|
|
327
|
+
|
|
328
|
+
fields["dependencies"].each do |dep|
|
|
329
|
+
if dep.is_a?(String)
|
|
330
|
+
dependencies.push "url" => dep
|
|
331
|
+
elsif dep.is_a?(Hash)
|
|
332
|
+
raise "Currently only URL-based dependencies on Goods files are supported!" unless dep["url"]
|
|
333
|
+
dependencies.push dep
|
|
334
|
+
else
|
|
335
|
+
raise "Unexpected dependency type #{dep.class} when parsing DGD Manifest specs, item: #{dep.inspect}"
|
|
336
|
+
end
|
|
337
|
+
end
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
spec = GoodsSpec.new(@repo, name: fields["name"], source: source, source_details: source_details, paths: fields["paths"], dependencies: dependencies)
|
|
338
341
|
return spec
|
|
339
342
|
end
|
|
340
343
|
end
|
|
@@ -345,8 +348,9 @@ CONTENTS
|
|
|
345
348
|
attr_reader :source
|
|
346
349
|
attr_reader :source_details
|
|
347
350
|
attr_reader :paths
|
|
351
|
+
attr_reader :dependencies
|
|
348
352
|
|
|
349
|
-
def initialize(repo, name:, source:, source_details: {}, paths:)
|
|
353
|
+
def initialize(repo, name:, source:, source_details: {}, paths:, dependencies:)
|
|
350
354
|
@repo = repo
|
|
351
355
|
@name = name
|
|
352
356
|
@source = source
|
|
@@ -359,6 +363,7 @@ CONTENTS
|
|
|
359
363
|
end
|
|
360
364
|
|
|
361
365
|
@paths = cleaned_paths
|
|
366
|
+
@dependencies = dependencies
|
|
362
367
|
end
|
|
363
368
|
end
|
|
364
369
|
|
|
@@ -455,4 +460,114 @@ FILE_CONTENTS
|
|
|
455
460
|
puts "Successfully created project at #{@location}."
|
|
456
461
|
end
|
|
457
462
|
end
|
|
463
|
+
|
|
464
|
+
class DGDRuntimeConfig
|
|
465
|
+
attr_reader :app_root
|
|
466
|
+
|
|
467
|
+
DEFAULT_CONFIG = {
|
|
468
|
+
users: 100,
|
|
469
|
+
editors: 40,
|
|
470
|
+
swap_size: 1048576,
|
|
471
|
+
sector_size: 512,
|
|
472
|
+
swap_fragment: 4096,
|
|
473
|
+
static_chunk: 64512,
|
|
474
|
+
dynamic_chunk: 261120,
|
|
475
|
+
dump_interval: 3600,
|
|
476
|
+
typechecking: 2,
|
|
477
|
+
include_file: "/include/std.h",
|
|
478
|
+
include_dirs: ["/include", "~/include"],
|
|
479
|
+
auto_object: "/kernel/lib/auto",
|
|
480
|
+
driver_object: "/kernel/sys/driver",
|
|
481
|
+
create: "_F_create",
|
|
482
|
+
array_size: 16384,
|
|
483
|
+
objects: 262144,
|
|
484
|
+
call_outs: 16384,
|
|
485
|
+
}
|
|
486
|
+
CONFIG_KEYS = DEFAULT_CONFIG.keys.map(&:to_s) + [ "app_root", "ports", "telnet_ports", "dump_file", "statedir" ]
|
|
487
|
+
|
|
488
|
+
def initialize(config_data)
|
|
489
|
+
@app_root = config_data["app_root"] || "app"
|
|
490
|
+
@ports = {
|
|
491
|
+
"*" => 50100,
|
|
492
|
+
}
|
|
493
|
+
@telnet_ports = {
|
|
494
|
+
"*" => 50110,
|
|
495
|
+
}
|
|
496
|
+
@statedir = config_data["statedir"] || "state"
|
|
497
|
+
@dump_file = if config_data["dump_file"]
|
|
498
|
+
"../" + config_data["dump_file"]
|
|
499
|
+
else
|
|
500
|
+
"../#{@statedir}/dump"
|
|
501
|
+
end
|
|
502
|
+
@config = DEFAULT_CONFIG.dup
|
|
503
|
+
|
|
504
|
+
@raw_data = config_data
|
|
505
|
+
@config.keys.each do |prop|
|
|
506
|
+
# For now, assume and require that JSON data is the correct type if present
|
|
507
|
+
@config[prop] = config_data[prop.to_s] if config_data[prop.to_s]
|
|
508
|
+
end
|
|
509
|
+
unexpected_config_keys = config_data.keys - CONFIG_KEYS
|
|
510
|
+
unless unexpected_config_keys.empty?
|
|
511
|
+
raise "Unexpected key names in DGD configuration: #{unexpected_config_keys.inspect}!"
|
|
512
|
+
end
|
|
513
|
+
|
|
514
|
+
if config_data["telnet_ports"]
|
|
515
|
+
@telnet_ports = config_to_ports(config_data["telnet_ports"])
|
|
516
|
+
end
|
|
517
|
+
if config_data["ports"]
|
|
518
|
+
@ports = config_to_ports(config_data["ports"])
|
|
519
|
+
end
|
|
520
|
+
end
|
|
521
|
+
|
|
522
|
+
def config_to_ports(data)
|
|
523
|
+
if data.is_a?(Hash)
|
|
524
|
+
# TODO: verify that keys are IP addr strings and values are legal port numbers
|
|
525
|
+
return data
|
|
526
|
+
elsif data.is_a?(Array)
|
|
527
|
+
# TODO: verify that data is an array of legal integer port numbers
|
|
528
|
+
ports = {}
|
|
529
|
+
data.each { |p| ports["*"] = p }
|
|
530
|
+
return ports
|
|
531
|
+
elsif data.is_a?(Integer)
|
|
532
|
+
return { "*": data }
|
|
533
|
+
else
|
|
534
|
+
raise "dgd-manifest: not sure how to get port data from a #{data.class.name} -- #{data.inspect}!"
|
|
535
|
+
end
|
|
536
|
+
end
|
|
537
|
+
|
|
538
|
+
def as_file
|
|
539
|
+
return <<DGD_CONFIG
|
|
540
|
+
telnet_port = ([
|
|
541
|
+
#{@telnet_ports.map { |ip, p| "#{ip.inspect}:#{p}" }.join(",\n ") }
|
|
542
|
+
]); /* legacy telnet ports */
|
|
543
|
+
binary_port = ([
|
|
544
|
+
#{@ports.map { |ip, p| "#{ip.inspect}:#{p}" }.join(",\n ") }
|
|
545
|
+
]); /* binary ports */
|
|
546
|
+
directory = "./#{GENERATED_ROOT}";
|
|
547
|
+
|
|
548
|
+
users = #{@config[:users]}; /* max # of connections */
|
|
549
|
+
editors = #{@config[:editors]}; /* max # of built-in-editor sessions */
|
|
550
|
+
ed_tmpfile = "../#{@statedir}/ed"; /* proto editor tmpfile */
|
|
551
|
+
swap_file = "../#{@statedir}/swap"; /* swap file */
|
|
552
|
+
swap_size = #{@config[:swap_size]}; /* # sectors in swap file */
|
|
553
|
+
sector_size = #{@config[:sector_size]}; /* swap sector size */
|
|
554
|
+
swap_fragment = #{@config[:swap_fragment]}; /* fragment to swap out */
|
|
555
|
+
static_chunk = #{@config[:static_chunk]}; /* static memory chunk */
|
|
556
|
+
dynamic_chunk = #{@config[:dynamic_chunk]}; /* dynamic memory chunk */
|
|
557
|
+
dump_file = #{@dump_file.inspect}; /* dump file */
|
|
558
|
+
dump_interval = #{@config[:dump_interval]}; /* expected statedump interval in seconds */
|
|
559
|
+
|
|
560
|
+
typechecking = #{@config[:typechecking]}; /* level of typechecking (2 is highest) */
|
|
561
|
+
include_file = #{@config[:include_file].inspect}; /* standard include file */
|
|
562
|
+
include_dirs = ({ #{@config[:include_dirs].map(&:inspect).join(", ")} }); /* directories to search */
|
|
563
|
+
auto_object = #{@config[:auto_object].inspect}; /* auto inherited object */
|
|
564
|
+
driver_object = #{@config[:driver_object].inspect}; /* driver object */
|
|
565
|
+
create = #{@config[:create].inspect}; /* name of create function */
|
|
566
|
+
|
|
567
|
+
array_size = #{@config[:array_size]}; /* max array size */
|
|
568
|
+
objects = #{@config[:objects]}; /* max # of objects */
|
|
569
|
+
call_outs = #{@config[:call_outs]}; /* max # of callouts */
|
|
570
|
+
DGD_CONFIG
|
|
571
|
+
end
|
|
572
|
+
end
|
|
458
573
|
end
|
|
@@ -8,13 +8,21 @@ require "tempfile"
|
|
|
8
8
|
|
|
9
9
|
module SkotOS; end
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
class SkotOS::XMLObject; end
|
|
12
|
+
|
|
13
|
+
class << SkotOS::XMLObject
|
|
14
|
+
attr_accessor :merry_only
|
|
15
|
+
attr_accessor :ignore_whitespace
|
|
16
|
+
attr_accessor :ignore_types
|
|
17
|
+
end
|
|
12
18
|
|
|
13
19
|
class SkotOS::XMLObject
|
|
14
20
|
attr_reader :pretty
|
|
21
|
+
attr_reader :noko_doc
|
|
15
22
|
|
|
16
|
-
def initialize(pretty)
|
|
23
|
+
def initialize(pretty, noko_doc: nil)
|
|
17
24
|
@pretty = pretty
|
|
25
|
+
@noko_doc = noko_doc
|
|
18
26
|
end
|
|
19
27
|
|
|
20
28
|
def self.from_file(filename)
|
|
@@ -25,9 +33,7 @@ class SkotOS::XMLObject
|
|
|
25
33
|
remove_undiffed(doc)
|
|
26
34
|
|
|
27
35
|
pretty = doc.to_xml(indent:3)
|
|
28
|
-
|
|
29
|
-
#prune_whitespace(data)
|
|
30
|
-
SkotOS::XMLObject.new pretty
|
|
36
|
+
SkotOS::XMLObject.new pretty, noko_doc: doc
|
|
31
37
|
end
|
|
32
38
|
|
|
33
39
|
def self.diff_between(obj1, obj2, o1_name: "Object 1", o2_name: "Object 2")
|
|
@@ -40,8 +46,11 @@ class SkotOS::XMLObject
|
|
|
40
46
|
of1.close
|
|
41
47
|
of2.close
|
|
42
48
|
|
|
49
|
+
diff_opts = [ "-c" ]
|
|
50
|
+
diff_opts += [ "-w", "-B" ] if self.ignore_whitespace
|
|
51
|
+
|
|
43
52
|
# Diff 'fails' if there's a difference between the two files.
|
|
44
|
-
diff = system_call("diff
|
|
53
|
+
diff = system_call("diff #{diff_opts.join(" ")} #{of1.path} #{of2.path}", fail_ok: true)
|
|
45
54
|
diff.sub!(of1.path, o1_name)
|
|
46
55
|
diff.sub!(of2.path, o2_name)
|
|
47
56
|
ensure
|
|
@@ -51,28 +60,35 @@ class SkotOS::XMLObject
|
|
|
51
60
|
diff
|
|
52
61
|
end
|
|
53
62
|
|
|
54
|
-
def self.skip_ignored_files(list)
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
63
|
+
def self.skip_ignored_files(list, base_dir)
|
|
64
|
+
if self.merry_only
|
|
65
|
+
list.select { |path| File.directory?(base_dir + "/" + path) ||
|
|
66
|
+
path[/.xml$/] || path[/.XML$/] }
|
|
67
|
+
else
|
|
68
|
+
list.select do |path|
|
|
69
|
+
!path[/,v$/] && # Ignore files ending in comma-v
|
|
70
|
+
!path[/-backup-\d+-\d+-\d+\.xml/] && # Ignore files ending in -backup-[DATE].xml
|
|
71
|
+
path != ".git" && # Ignore .git directories
|
|
72
|
+
path != "MOVED" # Ignore MOVED - it's a sort of recycle, waiting to be emptied
|
|
73
|
+
end
|
|
58
74
|
end
|
|
59
75
|
end
|
|
60
76
|
|
|
61
77
|
def self.diff_dirs(dir1, dir2)
|
|
62
|
-
entries1 = skip_ignored_files(Dir.glob("*", base: dir1).to_a)
|
|
63
|
-
entries2 = skip_ignored_files(Dir.glob("*", base: dir2).to_a)
|
|
78
|
+
entries1 = skip_ignored_files(Dir.glob("*", base: dir1).to_a, dir1)
|
|
79
|
+
entries2 = skip_ignored_files(Dir.glob("*", base: dir2).to_a, dir2)
|
|
64
80
|
|
|
65
81
|
only_in_1 = entries1 - entries2
|
|
66
82
|
only_in_2 = entries2 - entries1
|
|
67
83
|
in_both = entries1 & entries2
|
|
68
84
|
|
|
69
85
|
diff = []
|
|
70
|
-
diff << "Only in first: #{only_in_1.join(", ")}" unless only_in_1.empty?
|
|
71
|
-
diff << "Only in second: #{only_in_2.join(", ")}" unless only_in_2.empty?
|
|
86
|
+
diff << "Only in first: #{only_in_1.map { |s| dir1 + "/" + s }.join(", ")}" unless only_in_1.empty?
|
|
87
|
+
diff << "Only in second: #{only_in_2.map { |s| dir2 + "/" + s }.join(", ")}" unless only_in_2.empty?
|
|
72
88
|
|
|
73
89
|
in_both.each do |file|
|
|
74
|
-
in_1 =
|
|
75
|
-
in_2 =
|
|
90
|
+
in_1 = File.join dir1, file
|
|
91
|
+
in_2 = File.join dir2, file
|
|
76
92
|
if File.directory?(in_1) ^ File.directory?(in_2)
|
|
77
93
|
diff << "Only a directory in one, not both: #{dir1}/#{file}"
|
|
78
94
|
elsif File.directory?(in_1)
|
|
@@ -97,6 +113,90 @@ class SkotOS::XMLObject
|
|
|
97
113
|
end
|
|
98
114
|
end
|
|
99
115
|
end
|
|
116
|
+
|
|
117
|
+
rev = noko_single_node(doc.root, "Core:Property", attrs: { "property" => "revisions" })
|
|
118
|
+
rev.remove if rev
|
|
119
|
+
|
|
120
|
+
list = noko_single_node(doc.root, "Core:Property", attrs: { "property" => "#list#" })
|
|
121
|
+
list.remove if list
|
|
122
|
+
|
|
123
|
+
if self.merry_only
|
|
124
|
+
# Kill off all the non-Merry nodes
|
|
125
|
+
noko_remove_non_merry_nodes(doc.root)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
if self.ignore_types
|
|
129
|
+
self.ignore_types.each do |ignored_type|
|
|
130
|
+
skipped = noko_with_name_and_attrs(doc.root, ignored_type)
|
|
131
|
+
skipped.each { |n| n.remove }
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
base_combat = noko_single_node(doc.root, "Base:Combat")
|
|
136
|
+
if base_combat
|
|
137
|
+
base_strength = noko_single_node(base_combat, "Base:Strength", attrs: { "value" => "1" })
|
|
138
|
+
base_max_fatigue = noko_single_node(base_combat, "Base:MaxFatigue", attrs: { "value" => "1" })
|
|
139
|
+
if base_strength && base_max_fatigue && noko_non_text(base_combat.children).size == 2
|
|
140
|
+
next_text = base_combat.next
|
|
141
|
+
base_combat.remove
|
|
142
|
+
next_text.remove
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def self.noko_single_node(node, name, attrs: {})
|
|
148
|
+
choices = noko_with_name_and_attrs(node, name, attrs)
|
|
149
|
+
if choices.size < 1
|
|
150
|
+
nil
|
|
151
|
+
elsif choices.size > 1
|
|
152
|
+
raise "Single-node search returned more than one node! #{name.inspect}, #{attrs.inspect}"
|
|
153
|
+
else
|
|
154
|
+
choices[0]
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def self.noko_non_text(nodes)
|
|
159
|
+
nodes.select { |n| !n.is_a? Nokogiri::XML::Text }
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def self.noko_with_name_and_attrs(node, name, attrs = {})
|
|
163
|
+
results = node.children.flat_map { |n| noko_with_name_and_attrs(n, name, attrs) }
|
|
164
|
+
if node.name == name &&
|
|
165
|
+
attrs.all? { |k, v| node.attribute(k).value == v }
|
|
166
|
+
results << node
|
|
167
|
+
end
|
|
168
|
+
results
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def self.noko_remove_non_merry_nodes(root)
|
|
172
|
+
root.children.each do |node|
|
|
173
|
+
if node.name != "Core:PropertyContainer"
|
|
174
|
+
node.remove
|
|
175
|
+
next
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
node.children.each do |node2|
|
|
179
|
+
if node2.name != "Core:PCProperties"
|
|
180
|
+
node2.remove
|
|
181
|
+
next
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
node2.children.each do |property_node|
|
|
185
|
+
if property_node.name != "Core:Property" || property_node.attribute("property").value[0..5] != "merry:"
|
|
186
|
+
property_node.remove
|
|
187
|
+
next
|
|
188
|
+
end
|
|
189
|
+
# Leave the Merry node alone
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
if node2.children.size == 0
|
|
193
|
+
node2.remove
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
if node.children.size == 0
|
|
197
|
+
node.remove
|
|
198
|
+
end
|
|
199
|
+
end
|
|
100
200
|
end
|
|
101
201
|
|
|
102
202
|
def self.system_call(cmd, fail_ok: false)
|
data/lib/dgd-tools/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dgd-tools
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Noah Gibbs
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2021-
|
|
11
|
+
date: 2021-03-03 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: nokogiri
|
|
@@ -24,6 +24,20 @@ dependencies:
|
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: 1.10.5
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: optimist
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: 3.0.1
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: 3.0.1
|
|
27
41
|
description: dgd-tools supplies DGD Manifest and eventually perhaps other tools. DGD
|
|
28
42
|
Manifest is an experimental DGD library and packaging system.
|
|
29
43
|
email:
|
|
@@ -53,6 +67,7 @@ files:
|
|
|
53
67
|
- example_xml/t2/Thing.xml
|
|
54
68
|
- exe/dgd-manifest
|
|
55
69
|
- exe/skotos-xml-diff
|
|
70
|
+
- goods/chattheatre_kernellib.goods
|
|
56
71
|
- goods/skotos_httpd.goods
|
|
57
72
|
- lib/dgd-tools/manifest.rb
|
|
58
73
|
- lib/dgd-tools/skotos_xml_obj.rb
|