textus 0.10.5 → 0.14.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.
Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/ARCHITECTURE.md +60 -40
  3. data/CHANGELOG.md +318 -3
  4. data/README.md +34 -27
  5. data/SPEC.md +226 -145
  6. data/docs/conventions.md +8 -8
  7. data/lib/textus/application/context.rb +4 -0
  8. data/lib/textus/application/reads/blame.rb +1 -1
  9. data/lib/textus/application/reads/deps.rb +15 -0
  10. data/lib/textus/application/reads/freshness.rb +4 -4
  11. data/lib/textus/application/reads/get.rb +9 -12
  12. data/lib/textus/application/reads/list.rb +15 -0
  13. data/lib/textus/application/reads/policy_explain.rb +2 -2
  14. data/lib/textus/application/reads/published.rb +15 -0
  15. data/lib/textus/application/reads/rdeps.rb +15 -0
  16. data/lib/textus/application/reads/schema_envelope.rb +15 -0
  17. data/lib/textus/application/reads/stale.rb +15 -0
  18. data/lib/textus/application/reads/uid.rb +15 -0
  19. data/lib/textus/application/reads/validate_all.rb +15 -0
  20. data/lib/textus/application/reads/where.rb +15 -0
  21. data/lib/textus/application/refresh/all.rb +2 -2
  22. data/lib/textus/application/refresh/orchestrator.rb +1 -1
  23. data/lib/textus/application/refresh/worker.rb +8 -8
  24. data/lib/textus/application/writes/accept.rb +26 -8
  25. data/lib/textus/application/writes/build.rb +12 -49
  26. data/lib/textus/application/writes/delete.rb +1 -1
  27. data/lib/textus/application/writes/mv.rb +144 -0
  28. data/lib/textus/application/writes/publish.rb +42 -10
  29. data/lib/textus/application/writes/put.rb +1 -1
  30. data/lib/textus/application/writes/reject.rb +37 -0
  31. data/lib/textus/builder/pipeline.rb +1 -1
  32. data/lib/textus/builder/renderer/json.rb +1 -1
  33. data/lib/textus/builder/renderer/yaml.rb +1 -1
  34. data/lib/textus/cli/group/key.rb +1 -1
  35. data/lib/textus/cli/group/refresh.rb +21 -0
  36. data/lib/textus/cli/group/rule.rb +11 -0
  37. data/lib/textus/cli/verb/accept.rb +1 -2
  38. data/lib/textus/cli/verb/audit.rb +3 -3
  39. data/lib/textus/cli/verb/blame.rb +1 -2
  40. data/lib/textus/cli/verb/build.rb +6 -2
  41. data/lib/textus/cli/verb/delete.rb +1 -2
  42. data/lib/textus/cli/verb/deps.rb +1 -1
  43. data/lib/textus/cli/verb/freshness.rb +1 -2
  44. data/lib/textus/cli/verb/get.rb +2 -3
  45. data/lib/textus/cli/verb/hook_run.rb +3 -2
  46. data/lib/textus/cli/verb/hooks.rb +1 -1
  47. data/lib/textus/cli/verb/{migrate_keys.rb → key_normalize.rb} +1 -1
  48. data/lib/textus/cli/verb/list.rb +1 -1
  49. data/lib/textus/cli/verb/mv.rb +1 -1
  50. data/lib/textus/cli/verb/published.rb +1 -1
  51. data/lib/textus/cli/verb/put.rb +3 -3
  52. data/lib/textus/cli/verb/rdeps.rb +1 -1
  53. data/lib/textus/cli/verb/refresh.rb +1 -2
  54. data/lib/textus/cli/verb/reject.rb +1 -1
  55. data/lib/textus/cli/verb/{policy_explain.rb → rule_explain.rb} +2 -3
  56. data/lib/textus/cli/verb/{policy_list.rb → rule_list.rb} +3 -3
  57. data/lib/textus/cli/verb/schema.rb +1 -1
  58. data/lib/textus/cli/verb/uid.rb +1 -1
  59. data/lib/textus/cli/verb/where.rb +1 -1
  60. data/lib/textus/cli/verb.rb +9 -3
  61. data/lib/textus/cli.rb +6 -6
  62. data/lib/textus/doctor/check/handler_allowlist.rb +1 -1
  63. data/lib/textus/doctor/check/illegal_keys.rb +39 -16
  64. data/lib/textus/doctor/check/intake_registration.rb +4 -4
  65. data/lib/textus/doctor/check/protocol_version.rb +47 -0
  66. data/lib/textus/doctor/check/{policy_ambiguity.rb → rule_ambiguity.rb} +6 -6
  67. data/lib/textus/doctor/check/schema_violations.rb +1 -1
  68. data/lib/textus/doctor.rb +6 -5
  69. data/lib/textus/domain/freshness/evaluator.rb +1 -1
  70. data/lib/textus/domain/permission.rb +4 -4
  71. data/lib/textus/domain/policy/predicates/human_accept.rb +31 -0
  72. data/lib/textus/domain/policy/predicates/schema_valid.rb +50 -0
  73. data/lib/textus/domain/policy/promotion.rb +45 -0
  74. data/lib/textus/entry/base.rb +28 -0
  75. data/lib/textus/entry/json.rb +59 -0
  76. data/lib/textus/entry/markdown.rb +46 -0
  77. data/lib/textus/entry/text.rb +35 -0
  78. data/lib/textus/entry/yaml.rb +59 -0
  79. data/lib/textus/entry.rb +16 -0
  80. data/lib/textus/envelope.rb +44 -14
  81. data/lib/textus/errors.rb +24 -5
  82. data/lib/textus/hooks/builtin.rb +5 -5
  83. data/lib/textus/hooks/dispatcher.rb +1 -1
  84. data/lib/textus/hooks/dsl.rb +3 -10
  85. data/lib/textus/hooks/loader.rb +1 -2
  86. data/lib/textus/hooks/registry.rb +22 -21
  87. data/lib/textus/infra/refresh/detached.rb +1 -1
  88. data/lib/textus/init.rb +25 -34
  89. data/lib/textus/intro.rb +65 -9
  90. data/lib/textus/manifest/entry/parser.rb +84 -0
  91. data/lib/textus/manifest/entry/validators/events.rb +21 -0
  92. data/lib/textus/manifest/entry/validators/format_matrix.rb +26 -0
  93. data/lib/textus/manifest/entry/validators/index_filename.rb +45 -0
  94. data/lib/textus/manifest/entry/validators/inject_intro.rb +18 -0
  95. data/lib/textus/manifest/entry/validators/publish_each.rb +37 -0
  96. data/lib/textus/manifest/entry/validators.rb +20 -0
  97. data/lib/textus/manifest/entry.rb +38 -189
  98. data/lib/textus/manifest/{policies.rb → rules.rb} +12 -10
  99. data/lib/textus/manifest/schema.rb +49 -0
  100. data/lib/textus/manifest.rb +50 -24
  101. data/lib/textus/migrate_keys.rb +1 -1
  102. data/lib/textus/operations/reads.rb +39 -0
  103. data/lib/textus/operations/refresh.rb +27 -0
  104. data/lib/textus/operations/writes.rb +21 -0
  105. data/lib/textus/operations.rb +44 -0
  106. data/lib/textus/projection.rb +9 -8
  107. data/lib/textus/refresh.rb +4 -5
  108. data/lib/textus/schema/tools.rb +8 -7
  109. data/lib/textus/store/reader.rb +1 -1
  110. data/lib/textus/store/staleness/intake_check.rb +1 -1
  111. data/lib/textus/store/validator.rb +3 -3
  112. data/lib/textus/store/writer.rb +5 -74
  113. data/lib/textus/store.rb +1 -55
  114. data/lib/textus/version.rb +2 -2
  115. data/lib/textus.rb +1 -0
  116. metadata +35 -10
  117. data/lib/textus/cli/group/policy.rb +0 -11
  118. data/lib/textus/composition.rb +0 -72
  119. data/lib/textus/proposal.rb +0 -10
  120. data/lib/textus/store/mover.rb +0 -167
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: textus
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.5
4
+ version: 0.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Patrick
@@ -112,17 +112,28 @@ files:
112
112
  - lib/textus/application/context.rb
113
113
  - lib/textus/application/reads/audit.rb
114
114
  - lib/textus/application/reads/blame.rb
115
+ - lib/textus/application/reads/deps.rb
115
116
  - lib/textus/application/reads/freshness.rb
116
117
  - lib/textus/application/reads/get.rb
118
+ - lib/textus/application/reads/list.rb
117
119
  - lib/textus/application/reads/policy_explain.rb
120
+ - lib/textus/application/reads/published.rb
121
+ - lib/textus/application/reads/rdeps.rb
122
+ - lib/textus/application/reads/schema_envelope.rb
123
+ - lib/textus/application/reads/stale.rb
124
+ - lib/textus/application/reads/uid.rb
125
+ - lib/textus/application/reads/validate_all.rb
126
+ - lib/textus/application/reads/where.rb
118
127
  - lib/textus/application/refresh/all.rb
119
128
  - lib/textus/application/refresh/orchestrator.rb
120
129
  - lib/textus/application/refresh/worker.rb
121
130
  - lib/textus/application/writes/accept.rb
122
131
  - lib/textus/application/writes/build.rb
123
132
  - lib/textus/application/writes/delete.rb
133
+ - lib/textus/application/writes/mv.rb
124
134
  - lib/textus/application/writes/publish.rb
125
135
  - lib/textus/application/writes/put.rb
136
+ - lib/textus/application/writes/reject.rb
126
137
  - lib/textus/builder/pipeline.rb
127
138
  - lib/textus/builder/renderer.rb
128
139
  - lib/textus/builder/renderer/json.rb
@@ -133,7 +144,8 @@ files:
133
144
  - lib/textus/cli/group.rb
134
145
  - lib/textus/cli/group/hook.rb
135
146
  - lib/textus/cli/group/key.rb
136
- - lib/textus/cli/group/policy.rb
147
+ - lib/textus/cli/group/refresh.rb
148
+ - lib/textus/cli/group/rule.rb
137
149
  - lib/textus/cli/group/schema.rb
138
150
  - lib/textus/cli/verb.rb
139
151
  - lib/textus/cli/verb/accept.rb
@@ -149,24 +161,23 @@ files:
149
161
  - lib/textus/cli/verb/hooks.rb
150
162
  - lib/textus/cli/verb/init.rb
151
163
  - lib/textus/cli/verb/intro.rb
164
+ - lib/textus/cli/verb/key_normalize.rb
152
165
  - lib/textus/cli/verb/list.rb
153
- - lib/textus/cli/verb/migrate_keys.rb
154
166
  - lib/textus/cli/verb/mv.rb
155
- - lib/textus/cli/verb/policy_explain.rb
156
- - lib/textus/cli/verb/policy_list.rb
157
167
  - lib/textus/cli/verb/published.rb
158
168
  - lib/textus/cli/verb/put.rb
159
169
  - lib/textus/cli/verb/rdeps.rb
160
170
  - lib/textus/cli/verb/refresh.rb
161
171
  - lib/textus/cli/verb/refresh_stale.rb
162
172
  - lib/textus/cli/verb/reject.rb
173
+ - lib/textus/cli/verb/rule_explain.rb
174
+ - lib/textus/cli/verb/rule_list.rb
163
175
  - lib/textus/cli/verb/schema.rb
164
176
  - lib/textus/cli/verb/schema_diff.rb
165
177
  - lib/textus/cli/verb/schema_init.rb
166
178
  - lib/textus/cli/verb/schema_migrate.rb
167
179
  - lib/textus/cli/verb/uid.rb
168
180
  - lib/textus/cli/verb/where.rb
169
- - lib/textus/composition.rb
170
181
  - lib/textus/dependencies.rb
171
182
  - lib/textus/doctor.rb
172
183
  - lib/textus/doctor/check.rb
@@ -176,7 +187,8 @@ files:
176
187
  - lib/textus/doctor/check/illegal_keys.rb
177
188
  - lib/textus/doctor/check/intake_registration.rb
178
189
  - lib/textus/doctor/check/manifest_files.rb
179
- - lib/textus/doctor/check/policy_ambiguity.rb
190
+ - lib/textus/doctor/check/protocol_version.rb
191
+ - lib/textus/doctor/check/rule_ambiguity.rb
180
192
  - lib/textus/doctor/check/schema_parse_error.rb
181
193
  - lib/textus/doctor/check/schema_violations.rb
182
194
  - lib/textus/doctor/check/schemas.rb
@@ -192,7 +204,10 @@ files:
192
204
  - lib/textus/domain/policy.rb
193
205
  - lib/textus/domain/policy/handler_allowlist.rb
194
206
  - lib/textus/domain/policy/matcher.rb
207
+ - lib/textus/domain/policy/predicates/human_accept.rb
208
+ - lib/textus/domain/policy/predicates/schema_valid.rb
195
209
  - lib/textus/domain/policy/promote.rb
210
+ - lib/textus/domain/policy/promotion.rb
196
211
  - lib/textus/domain/policy/refresh.rb
197
212
  - lib/textus/entry.rb
198
213
  - lib/textus/entry/base.rb
@@ -220,18 +235,28 @@ files:
220
235
  - lib/textus/key/path.rb
221
236
  - lib/textus/manifest.rb
222
237
  - lib/textus/manifest/entry.rb
223
- - lib/textus/manifest/policies.rb
238
+ - lib/textus/manifest/entry/parser.rb
239
+ - lib/textus/manifest/entry/validators.rb
240
+ - lib/textus/manifest/entry/validators/events.rb
241
+ - lib/textus/manifest/entry/validators/format_matrix.rb
242
+ - lib/textus/manifest/entry/validators/index_filename.rb
243
+ - lib/textus/manifest/entry/validators/inject_intro.rb
244
+ - lib/textus/manifest/entry/validators/publish_each.rb
245
+ - lib/textus/manifest/rules.rb
246
+ - lib/textus/manifest/schema.rb
224
247
  - lib/textus/migrate_keys.rb
225
248
  - lib/textus/mustache.rb
249
+ - lib/textus/operations.rb
250
+ - lib/textus/operations/reads.rb
251
+ - lib/textus/operations/refresh.rb
252
+ - lib/textus/operations/writes.rb
226
253
  - lib/textus/projection.rb
227
- - lib/textus/proposal.rb
228
254
  - lib/textus/refresh.rb
229
255
  - lib/textus/role.rb
230
256
  - lib/textus/schema.rb
231
257
  - lib/textus/schema/tools.rb
232
258
  - lib/textus/store.rb
233
259
  - lib/textus/store/audit_log.rb
234
- - lib/textus/store/mover.rb
235
260
  - lib/textus/store/reader.rb
236
261
  - lib/textus/store/sentinel.rb
237
262
  - lib/textus/store/staleness.rb
@@ -1,11 +0,0 @@
1
- module Textus
2
- class CLI
3
- class Group
4
- class Policy < Group
5
- self.cli_name = "policy"
6
- subcommands["list"] = Verb::PolicyList
7
- subcommands["explain"] = Verb::PolicyExplain
8
- end
9
- end
10
- end
11
- end
@@ -1,72 +0,0 @@
1
- module Textus
2
- module Composition
3
- module_function
4
-
5
- def context(store, role:, correlation_id: nil, dry_run: false)
6
- Textus::Application::Context.new(
7
- store: store,
8
- role: role,
9
- correlation_id: correlation_id,
10
- dry_run: dry_run,
11
- )
12
- end
13
-
14
- def reads_get(ctx)
15
- Textus::Application::Reads::Get.new(ctx: ctx, orchestrator: refresh_orchestrator(ctx))
16
- end
17
-
18
- def freshness(ctx)
19
- Textus::Application::Reads::Freshness.new(ctx: ctx)
20
- end
21
-
22
- def audit(ctx)
23
- Textus::Application::Reads::Audit.new(ctx: ctx)
24
- end
25
-
26
- def blame(ctx)
27
- Textus::Application::Reads::Blame.new(ctx: ctx)
28
- end
29
-
30
- def policy_explain(ctx)
31
- Textus::Application::Reads::PolicyExplain.new(ctx: ctx)
32
- end
33
-
34
- def refresh_worker(ctx)
35
- Textus::Application::Refresh::Worker.new(ctx: ctx, bus: ctx.store.bus)
36
- end
37
-
38
- def refresh_orchestrator(ctx)
39
- Textus::Application::Refresh::Orchestrator.new(
40
- worker: refresh_worker(ctx),
41
- bus: ctx.store.bus,
42
- store_root: ctx.store.root,
43
- store: ctx.store,
44
- role: ctx.role,
45
- )
46
- end
47
-
48
- def writes_put(ctx)
49
- Textus::Application::Writes::Put.new(ctx: ctx, bus: ctx.store.bus)
50
- end
51
-
52
- def writes_delete(ctx)
53
- Textus::Application::Writes::Delete.new(ctx: ctx, bus: ctx.store.bus)
54
- end
55
-
56
- def writes_build(ctx)
57
- Textus::Application::Writes::Build.new(ctx: ctx, bus: ctx.store.bus)
58
- end
59
-
60
- def writes_accept(ctx)
61
- Textus::Application::Writes::Accept.new(ctx: ctx, bus: ctx.store.bus)
62
- end
63
-
64
- def writes_publish(ctx)
65
- Textus::Application::Writes::Publish.new(ctx: ctx, bus: ctx.store.bus)
66
- end
67
-
68
- def event_bus(ctx)
69
- Textus::Infra::EventBus.new(registry: ctx.store.registry)
70
- end
71
- end
72
- end
@@ -1,10 +0,0 @@
1
- module Textus
2
- module Proposal
3
- # Deprecated as of 0.9.1: use Textus::Application::Writes::Accept (via
4
- # Textus::Composition.writes_accept).
5
- def self.accept(store, pending_key, as:)
6
- ctx = Textus::Composition.context(store, role: as)
7
- Textus::Application::Writes::Accept.new(ctx: ctx, bus: store.bus).call(pending_key)
8
- end
9
- end
10
- end
@@ -1,167 +0,0 @@
1
- require "fileutils"
2
-
3
- module Textus
4
- class Store
5
- class Mover
6
- MovePlan = Data.define(
7
- :old_key, :new_key, :old_path, :new_path,
8
- :new_mentry, :uid, :etag_before, :as
9
- )
10
-
11
- def initialize(store:, reader:, writer:, manifest:, audit_log:)
12
- @store = store
13
- @reader = reader
14
- @writer = writer
15
- @manifest = manifest
16
- @audit_log = audit_log
17
- end
18
-
19
- def call(old_key, new_key, as: Role::DEFAULT, dry_run: false, correlation_id: nil)
20
- plan, pre_env = prepare_plan(old_key, new_key, as: as)
21
- return dry_run_result(plan) if dry_run
22
-
23
- plan = ensure_uid!(plan, pre_env: pre_env)
24
- etag_after = perform_move!(plan)
25
- new_envelope = record_move(plan, etag_after: etag_after, correlation_id: correlation_id)
26
- success_result(plan, new_envelope: new_envelope)
27
- end
28
-
29
- private
30
-
31
- # Validates inputs, resolves manifest entries, and reads the source
32
- # envelope. Returns [MovePlan, pre_envelope]; the pre_envelope is only
33
- # needed by ensure_uid! and is threaded separately to keep MovePlan
34
- # focused on the planned operation.
35
- def prepare_plan(old_key, new_key, as:)
36
- @manifest.validate_key!(old_key)
37
- @manifest.validate_key!(new_key)
38
- raise UsageError.new("mv: old and new keys are identical") if old_key == new_key
39
-
40
- old_mentry, old_path, = @manifest.resolve(old_key)
41
- raise UnknownKey.new(old_key) unless File.exist?(old_path)
42
-
43
- new_mentry, new_path, = @manifest.resolve(new_key)
44
- validate_zone_and_format!(old_mentry, new_mentry)
45
- validate_writer!(old_mentry, old_key, as)
46
- raise UsageError.new("mv: target '#{new_key}' already exists at #{new_path}") if File.exist?(new_path)
47
-
48
- pre_env = @reader.get(old_key)
49
- plan = MovePlan.new(
50
- old_key: old_key, new_key: new_key,
51
- old_path: old_path, new_path: new_path,
52
- new_mentry: new_mentry,
53
- uid: pre_env["uid"], etag_before: pre_env["etag"], as: as
54
- )
55
- [plan, pre_env]
56
- end
57
-
58
- def validate_zone_and_format!(old_mentry, new_mentry)
59
- if old_mentry.zone != new_mentry.zone
60
- raise UsageError.new(
61
- "mv: cross-zone move refused (#{old_mentry.zone} → #{new_mentry.zone}). " \
62
- "Use put+delete for cross-zone moves.",
63
- )
64
- end
65
- return if old_mentry.format == new_mentry.format
66
-
67
- raise UsageError.new(
68
- "mv: format mismatch (#{old_mentry.format} → #{new_mentry.format}); refusing.",
69
- )
70
- end
71
-
72
- def validate_writer!(mentry, key, as)
73
- writers = @manifest.zone_writers(mentry.zone)
74
- return if writers.include?(as)
75
-
76
- raise WriteForbidden.new(key, mentry.zone, writers: writers)
77
- end
78
-
79
- def ensure_uid!(plan, pre_env:)
80
- return plan if plan.uid
81
-
82
- env = @writer.put(
83
- plan.old_key,
84
- meta: pre_env["_meta"],
85
- body: pre_env["body"],
86
- content: pre_env["content"],
87
- as: plan.as,
88
- suppress_events: true,
89
- )
90
- plan.with(uid: env["uid"], etag_before: env["etag"])
91
- end
92
-
93
- def perform_move!(plan)
94
- FileUtils.mkdir_p(File.dirname(plan.new_path))
95
- FileUtils.mv(plan.old_path, plan.new_path)
96
- rewrite_name_for_mv!(plan.new_mentry, plan.new_path, plan.new_key)
97
- Etag.for_file(plan.new_path)
98
- end
99
-
100
- def record_move(plan, etag_after:, correlation_id:)
101
- extras = {
102
- "from_key" => plan.old_key, "to_key" => plan.new_key,
103
- "from_path" => plan.old_path, "to_path" => plan.new_path,
104
- "uid" => plan.uid
105
- }
106
- extras["correlation_id"] = correlation_id if correlation_id
107
-
108
- @audit_log.append(
109
- role: plan.as, verb: "mv", key: plan.new_key,
110
- etag_before: plan.etag_before, etag_after: etag_after,
111
- extras: extras
112
- )
113
- new_envelope = @reader.get(plan.new_key)
114
- @store.fire_event(
115
- :mv,
116
- key: plan.new_key, from_key: plan.old_key, to_key: plan.new_key,
117
- envelope: new_envelope
118
- )
119
- new_envelope
120
- end
121
-
122
- def dry_run_result(plan)
123
- {
124
- "protocol" => PROTOCOL, "ok" => true, "dry_run" => true,
125
- "from_key" => plan.old_key, "to_key" => plan.new_key,
126
- "from_path" => plan.old_path, "to_path" => plan.new_path,
127
- "uid" => plan.uid
128
- }
129
- end
130
-
131
- def success_result(plan, new_envelope:)
132
- {
133
- "protocol" => PROTOCOL, "ok" => true,
134
- "from_key" => plan.old_key, "to_key" => plan.new_key,
135
- "from_path" => plan.old_path, "to_path" => plan.new_path,
136
- "uid" => plan.uid,
137
- "envelope" => new_envelope
138
- }
139
- end
140
-
141
- # If the moved file carries a `name:` field (markdown) or `_meta.name`
142
- # (json/yaml), rewrite it to the new basename so enforce_name_match! stays
143
- # happy on the next read. Only touches the bytes when name actually changes.
144
- def rewrite_name_for_mv!(mentry, new_path, new_key)
145
- strategy = Entry.for_format(mentry.format)
146
- raw = File.binread(new_path)
147
- parsed = strategy.parse(raw, path: new_path)
148
- basename = new_key.split(".").last
149
-
150
- case mentry.format
151
- when "markdown"
152
- meta = parsed["_meta"] || {}
153
- return unless meta.is_a?(Hash) && meta["name"].is_a?(String) && meta["name"] != basename
154
-
155
- meta = meta.merge("name" => basename)
156
- File.binwrite(new_path, strategy.serialize(meta: meta, body: parsed["body"]))
157
- when "json", "yaml"
158
- meta = parsed["_meta"]
159
- return unless meta.is_a?(Hash) && meta["name"].is_a?(String) && meta["name"] != basename
160
-
161
- new_meta = meta.merge("name" => basename)
162
- File.binwrite(new_path, strategy.serialize(meta: new_meta, body: "", content: parsed["content"]))
163
- end
164
- end
165
- end
166
- end
167
- end