dgd-tools 0.1.6 → 0.1.7
Sign up to get free protection for your applications and to get access to all the features.
- 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
|