@tsplc/build 0.2.10 → 0.2.11
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.
package/package.json
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"url": "git+https://github.com/livingforjesus/tsplc.git",
|
|
16
16
|
"directory": "packages/build"
|
|
17
17
|
},
|
|
18
|
-
"version": "0.2.
|
|
18
|
+
"version": "0.2.11",
|
|
19
19
|
"type": "module",
|
|
20
20
|
"exports": {
|
|
21
21
|
".": {
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"zod": "4.3.6",
|
|
46
|
-
"@tsplc/config": "0.2.
|
|
47
|
-
"@tsplc/typegen": "0.2.
|
|
46
|
+
"@tsplc/config": "0.2.11",
|
|
47
|
+
"@tsplc/typegen": "0.2.11"
|
|
48
48
|
},
|
|
49
49
|
"bin": {
|
|
50
50
|
"tsplc-build": "./dist/cli.js"
|
package/python/codesys_online.py
CHANGED
|
@@ -186,16 +186,16 @@ def run_online(engine, request, prepared=None):
|
|
|
186
186
|
with io.open(progress_path, 'a', encoding='utf-8') as output:
|
|
187
187
|
output.write(u'{0}Z {1}\n'.format(time.strftime('%Y-%m-%dT%H:%M:%S', time.gmtime()), stage))
|
|
188
188
|
progress('Starting; processor count {0}'.format(Environment.ProcessorCount))
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
189
|
+
previous = request.get('baseline')
|
|
190
|
+
# Operations reuse the downloaded project, which has its controller and tree; a download without one starts from the template.
|
|
191
|
+
if prepared is not None and os.path.normcase(prepared.path) != os.path.normcase(request['project']):
|
|
192
192
|
prepared.close()
|
|
193
193
|
prepared = None
|
|
194
|
-
if
|
|
195
|
-
project, pinned, generated = open_template(engine, request, request['project'], request.get('devices'), request['caches'], progress)
|
|
196
|
-
elif prepared is not None:
|
|
194
|
+
if prepared is not None:
|
|
197
195
|
progress('Using the project opened ahead')
|
|
198
196
|
project, pinned, generated = prepared, {}, None
|
|
197
|
+
elif request['operation'] == 'download' and previous is None:
|
|
198
|
+
project, pinned, generated = open_template(engine, request, request['project'], request.get('devices'), request['caches'], progress)
|
|
199
199
|
else:
|
|
200
200
|
progress('Opening project')
|
|
201
201
|
project = engine.projects.open(request['project'], primary=True)
|
|
@@ -214,7 +214,6 @@ def run_online(engine, request, prepared=None):
|
|
|
214
214
|
raise RuntimeError('Initial controller user requires an explicit download and credentials')
|
|
215
215
|
online_device.set_credentials_for_initial_user(*credentials)
|
|
216
216
|
progress('Controller connection configured')
|
|
217
|
-
previous = request.get('baseline')
|
|
218
217
|
if request['operation'] != 'download':
|
|
219
218
|
online_app = engine.online.create_online_application(application)
|
|
220
219
|
core = core_application(online_app)
|
|
@@ -238,8 +237,8 @@ def run_online(engine, request, prepared=None):
|
|
|
238
237
|
'state': state, 'values': {expression: online_app.read_value(expression) for expression in request.get('read', [])}}
|
|
239
238
|
finally:
|
|
240
239
|
core.Logout()
|
|
241
|
-
#
|
|
242
|
-
held = previous['objects'] if
|
|
240
|
+
# Only what changed since the baseline is written; a template gets every object.
|
|
241
|
+
held = previous['objects'] if previous is not None else None
|
|
243
242
|
gone = reconcile(application, held, request['objects']) if held is not None else []
|
|
244
243
|
import_objects(engine, application, request, held, progress)
|
|
245
244
|
for obj in gone:
|
|
@@ -196,12 +196,23 @@ class OnlineLifecycleTests(unittest.TestCase):
|
|
|
196
196
|
self.engine.projects.open.assert_not_called()
|
|
197
197
|
self.project.close.assert_called_once()
|
|
198
198
|
|
|
199
|
-
def
|
|
199
|
+
def test_another_project_than_the_one_opened_ahead_closes_it(self):
|
|
200
200
|
stale = SimpleNamespace(path='Other.project', close=Mock())
|
|
201
201
|
codesys_online.run_online(self.engine, self.request, stale)
|
|
202
202
|
stale.close.assert_called_once()
|
|
203
203
|
codesys_online.open_template.assert_called_once()
|
|
204
204
|
|
|
205
|
+
def test_download_with_a_baseline_imports_only_changes_into_the_project_opened_ahead_and_rebuilds(self):
|
|
206
|
+
self.request.update(baseline={
|
|
207
|
+
'applicationGuid': self.app.guid, 'controllerIds': self.ids, 'objects': [],
|
|
208
|
+
})
|
|
209
|
+
self.project.path = 'Application.project'
|
|
210
|
+
codesys_online.run_online(self.engine, self.request, self.project)
|
|
211
|
+
codesys_online.open_template.assert_not_called()
|
|
212
|
+
self.engine.projects.open.assert_not_called()
|
|
213
|
+
self.assertIs(codesys_online.import_objects.call_args.args[3], self.request['baseline']['objects'])
|
|
214
|
+
self.assertEqual(self.events, ['import', 'clean', 'compile', 'generate', 'online-wrapper'])
|
|
215
|
+
|
|
205
216
|
def test_full_download_rejects_library_errors_reported_after_transfer(self):
|
|
206
217
|
def report_library_error(core):
|
|
207
218
|
self.messages.append(SimpleNamespace(text="Could not open library '#VisuShared'."))
|
|
@@ -140,24 +140,26 @@ export const runControllerSession = async (
|
|
|
140
140
|
const resultPath = resolve(root, "result.json");
|
|
141
141
|
await rm(resultPath, { force: true });
|
|
142
142
|
const templateHash = sha256(await readFile(config.template));
|
|
143
|
-
// A different controller or device tree needs a fresh download from the template.
|
|
143
|
+
// A different image, template, controller or device tree needs a fresh download from the template.
|
|
144
144
|
const target = controllerTarget(config, config.online);
|
|
145
|
+
const expected = { imageId: options.imageId, templateHash, target };
|
|
146
|
+
// A download reuses the baseline when it still fits, and imports only what changed since.
|
|
145
147
|
const previous =
|
|
146
148
|
operation === "download"
|
|
147
|
-
? undefined
|
|
148
|
-
: await readBaseline(root,
|
|
149
|
+
? await readBaseline(root, expected).catch(() => undefined)
|
|
150
|
+
: await readBaseline(root, expected);
|
|
149
151
|
const baseline = previous?.baseline;
|
|
150
152
|
if (options.initializeUser && operation !== "download") {
|
|
151
153
|
throw new Error("Initial user creation requires an explicit download");
|
|
152
154
|
}
|
|
153
155
|
const opened = worker?.prepared;
|
|
154
156
|
const prepared =
|
|
155
|
-
operation
|
|
157
|
+
operation !== "inspect" && opened?.baseline === baseline?.generation ? opened : undefined;
|
|
156
158
|
const generation = prepared?.generation ?? randomUUID();
|
|
157
159
|
const candidate = resolve(root, "generations", generation);
|
|
158
160
|
const project = resolve(candidate, "project", "Application.project");
|
|
159
161
|
await mkdir(resolve(candidate, "project"), { recursive: true });
|
|
160
|
-
//
|
|
162
|
+
// Opens a copy of the baseline unless the worker opened one ahead; a download without a baseline saves the template here.
|
|
161
163
|
if (previous && !prepared) {
|
|
162
164
|
await cp(previous.project, resolve(candidate, "project"), {
|
|
163
165
|
recursive: true,
|
|
@@ -183,17 +185,18 @@ export const runControllerSession = async (
|
|
|
183
185
|
const sources = operation === "inspect" ? undefined : await loadSources(config);
|
|
184
186
|
const request = {
|
|
185
187
|
libraryReferences: config.libraryReferences,
|
|
186
|
-
//
|
|
187
|
-
...(operation === "download" &&
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
188
|
+
// Only a download without a baseline starts from the template; the others keep the downloaded project's tree.
|
|
189
|
+
...(operation === "download" &&
|
|
190
|
+
!previous && {
|
|
191
|
+
template: await toWindowsPath(config.template, config.codesys.wine),
|
|
192
|
+
templateHash,
|
|
193
|
+
// Kept across jobs: generating a device tree takes minutes, and the same inputs make the same one.
|
|
194
|
+
caches: await toWindowsPath(root, config.codesys.wine),
|
|
195
|
+
...(config.deviceTree && {
|
|
196
|
+
deviceTree: await writeDeviceTree(config.deviceTree, jobDirectory),
|
|
197
|
+
devices: await toWindowsPath(jobDirectory, config.codesys.wine),
|
|
198
|
+
}),
|
|
195
199
|
}),
|
|
196
|
-
}),
|
|
197
200
|
libraries: await Promise.all(
|
|
198
201
|
(config.libraries ?? []).map(async (library) => ({
|
|
199
202
|
...library,
|