blob: a546544b3b6bb6bde8513e04dc95b5a4adf6b811 [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import assert from 'node:assert/strict';
import { execFile } from 'node:child_process';
import { mkdir, mkdtemp, readlink, rm, stat, symlink, utimes, writeFile } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import test from 'node:test';
import { promisify } from 'node:util';
import { archive } from 'app-builder-lib/out/targets/archive.js';
// electron-builder 26.16 moved macOS ZIPs from the system zip to 7za, where
// the patch that keeps Windows ZIPs reproducible also drops every
// modification time. The patch keeps the macOS update archive on the system
// zip, as the releases already shipped were built.
test('the macOS update ZIP keeps bundle symlinks and modification times', {
skip: process.platform !== 'darwin' && 'the macOS update ZIP is built on macOS',
}, async (t) => {
const root = await mkdtemp(join(tmpdir(), 'maka-macos-archive-'));
t.after(() => rm(root, { recursive: true, force: true }));
const app = join(root, 'Maka.app');
const versions = join(app, 'Contents', 'Frameworks', 'Fixture.framework', 'Versions');
await mkdir(join(versions, 'A'), { recursive: true });
await symlink('A', join(versions, 'Current'));
const binary = join(versions, 'A', 'Fixture');
await writeFile(binary, '#!/bin/sh\n');
const modified = new Date('2024-01-01T00:00:00Z');
await utimes(binary, modified, modified);
const zip = join(root, 'Maka.zip');
// What ArchiveTarget passes for a macOS `zip` target.
await archive('zip', zip, app, { withoutDir: false, preserveSymlinks: true });
// Squirrel.Mac and verify-macos-autoupdate both unpack with ditto.
const out = join(root, 'out');
await promisify(execFile)('ditto', ['-x', '-k', zip, out]);
const extracted = join(out, 'Maka.app', 'Contents', 'Frameworks', 'Fixture.framework');
assert.equal(await readlink(join(extracted, 'Versions', 'Current')), 'A');
const unpacked = await stat(join(extracted, 'Versions', 'A', 'Fixture'));
assert.equal(unpacked.mtime.toISOString(), modified.toISOString());
});