Entitlements reference check compares forward-slash paths on every OS (false 'not referenced by CODE_SIGN_ENTITLEMENTS' on Windows); test, pitfall 103

This commit is contained in:
CRTkafa 2026-10-22 16:03:07 +08:00
parent e7874a2c25
commit cbba936ed8
4 changed files with 33 additions and 3 deletions

View file

@ -2,6 +2,8 @@
## Unreleased
- Windows: no false "entitlements not referenced by CODE_SIGN_ENTITLEMENTS" warning (paths compared with forward slashes). Pitfall 103.
- **`storebound apps relink`** after a machine move: every "folder not found" entry of the app folder list is pointed at
the same app on this machine (by its path or its app name), ids kept so the desktop keeps its accounts and settings;
`apps folders` says so when entries are missing. `apps add` names an app after its config's app name.

View file

@ -14,7 +14,7 @@
import { ensureGcSwitch, gcSwitchPlan, readGcSwitch } from './game-center';
import { chmodSync, existsSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from 'node:fs';
import { homedir, tmpdir } from 'node:os';
import { basename, dirname, join, relative, resolve as resolvePath } from 'node:path';
import { basename, dirname, join, relative, resolve as resolvePath, sep } from 'node:path';
import type { Ctx } from '../lib/ctx';
import { confirm, need } from '../lib/ctx';
import { buildCsr, csrContent, newSigningKey, spkiOfKey } from '../lib/csr';
@ -83,9 +83,11 @@ export function readProjectEntitlements(root: string): ProjectEntitlements[] | n
for (const n of names) {
const f = join(dir, n);
if (n.endsWith('.entitlements')) {
const rel = relative(root, f);
// forward slashes on every OS: the pbxproj writes App/App.entitlements, Windows paths use backslashes
const rel = relative(root, f).split(sep).join('/');
const fwd = f.split(sep).join('/');
if (isBuildCopyPath(rel) || out.some(o => o.file === rel)) continue;
out.push(projectEntitlements(rel, readFileSync(f, 'utf8'), pbx ? refs.some(r => f.endsWith('/' + r)) : null));
out.push(projectEntitlements(rel, readFileSync(f, 'utf8'), pbx ? refs.some(r => fwd.endsWith('/' + r.replace(/\\/g, '/'))) : null));
} else if (d > 0 && !n.startsWith('.') && !['node_modules', 'Pods', 'build', 'DerivedData'].includes(n) && !n.endsWith('.xcodeproj')) {
try { if (statSync(f).isDirectory()) walk(f, d - 1); } catch { /* unreadable */ }
}

View file

@ -1243,3 +1243,11 @@ that fails without the fix (see CONTRIBUTING.md).
language in the same edit. Then run `play images` for the screenshots.
- **Guard:** `firstGraphics` in `cli/play/images.ts`, used by `cli/play/listing.ts` for languages Play does not have yet;
it stops with the fix when the 512x512 icon is missing.
## 103. "App.entitlements is not referenced by CODE_SIGN_ENTITLEMENTS" on Windows although it is
- **Symptom:** on Windows, `apple status` / `apple signing` warned that `ios\App\App\App.entitlements` is not
referenced, while project.pbxproj sets `CODE_SIGN_ENTITLEMENTS = App/App.entitlements` for both configurations.
- **Cause:** the check compared the Windows path (backslashes) with the pbxproj's forward-slash path.
- **Do:** update storebound; the warning was false.
- **Guard:** `readProjectEntitlements` in `cli/apple/signing.ts` compares forward-slash paths on every OS
(`tests/entitlements-ref.test.ts`).

View file

@ -0,0 +1,18 @@
// The entitlements file the pbxproj names is "referenced" on every OS (Windows paths use backslashes; pitfall 103).
import { expect, test } from 'bun:test';
import { mkdirSync, mkdtempSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { readProjectEntitlements } from '../cli/apple/signing';
test('CODE_SIGN_ENTITLEMENTS = App/App.entitlements matches ios/App/App/App.entitlements', () => {
const root = mkdtempSync(join(tmpdir(), 'sb-ent-'));
mkdirSync(join(root, 'ios/App/App.xcodeproj'), { recursive: true });
mkdirSync(join(root, 'ios/App/App'), { recursive: true });
writeFileSync(join(root, 'ios/App/App.xcodeproj/project.pbxproj'), 'buildSettings = { CODE_SIGN_ENTITLEMENTS = App/App.entitlements; };\n');
writeFileSync(join(root, 'ios/App/App/App.entitlements'), '<plist><dict><key>com.apple.developer.game-center</key><true/></dict></plist>');
const r = readProjectEntitlements(root)!;
expect(r).toHaveLength(1);
expect(r[0]!.file).toBe('ios/App/App/App.entitlements');
expect(r[0]!.referenced).toBe(true);
});