- EXE project kind next to MSIX: formats.exe, new EXE projects, EXE app info (architecture, UpgradeCode), per-kind workspace; EXE builds and signing are still refused explicitly (#9). - Install configuration tabs: registry grid, shortcuts and installer properties with formatted-text checks (#10). - Per-version .isver files: version list, add dialog, lock/unlock, delete with .isver.bak backups, description (#11). - Major/patch versions with cumulative patch checks and automatic kind selection (#12). - 설치화면 tab: setup steps, theme and scripts per version (#13). - Preferences: theme and display language (#14). - 설치파일 tab as an Explorer-style tree: per-row add/remove, Windows folder install locations (FileRule.targetRoot), picked files placed with FileRule.sourceFolder, unsaved-rule file preview (#17). Checks: cargo fmt/clippy/test, 82 frontend tests, Vite build and the msix-studio build pass. npm ci, GUI click tests and real EXE builds were not run. Refs #9 #10 #11 #12 #13 #14 #17 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
41 lines
5.4 KiB
Markdown
41 lines
5.4 KiB
Markdown
# EXE 버전별 메타파일
|
|
|
|
2026-11-09. EXE 프로젝트에서 버전마다 설치파일·레지스트리·바로가기를 따로 관리하도록 프로젝트 형식을 나눴다. `.isproj`는 모든 버전이 공유하는 설정만 두고, 버전마다 `<이름>.versions/<버전>.isver` 메타파일을 둔다. EXE 빌드·서명·업데이트와 버전 삭제는 범위 밖이다. MSIX 프로젝트는 바뀌지 않았다.
|
|
|
|
## 결정
|
|
|
|
- 메타파일 위치: 프로젝트 옆 `<이름>.versions/<버전>.isver`(JSON). 파일 이름은 버전과 같아야 한다.
|
|
- 버전마다 가지는 항목: 제품 버전, ProductCode, 잠금 여부, 설치파일 규칙, 레지스트리, 바로가기. 그 외(앱 이름·게시자·아키텍처·UpgradeCode·설치 폴더·설치 범위·속성문자·소스 alias)는 공유한다.
|
|
- 새 버전: 선택한 버전을 복사하고 새 ProductCode를 받으며 잠금이 풀린 상태로 시작한다.
|
|
- 잠금: 사용자가 잠그고 해제한다. 잠긴 버전은 내용을 바꿀 수 없다.
|
|
- 이전 단일 버전 EXE 형식은 자동 변환하지 않고 열기를 거부한다.
|
|
|
|
## 모델과 실행
|
|
|
|
- `package_domain::Exe`에서 `msiVersion`·`productCode`·`shortcuts`를 제거하고 `ExeVersion`(`version`, `productCode`, `locked`, `files`, `registry`, `shortcuts`)을 추가했다. 스키마는 `schemas/exe-version.schema.json`, CLI `package-builder version-schema`.
|
|
- 열기는 `.versions` 폴더의 `*.isver`를 읽어 버전 순으로 정렬한다. 파일 이름과 `version`이 다르면 `VersionFileMismatch`로 거부한다.
|
|
- 저장은 모든 버전을 먼저 검사한 뒤 쓴다. 다른 곳에서 바뀐 파일은 `RevisionConflict`, 잠긴 버전의 내용 변경은 `VersionLocked`, 목록에서 지운 버전은 패치가 사용하는 메이저(`VersionInUse`)가 아니면 저장할 때 `.isver.bak`으로 옮긴다. 잠긴 버전은 화면에서 휴지통을 숨기며, 잠금을 해제하면 삭제할 수 있다(같은 날 버전 삭제 추가로 `VersionDeletionUnsupported` 대체). 바꾼 버전만 `.isver.bak`을 남기고 다시 쓴다.
|
|
- 검증은 공유 설정과 선택한 버전을 함께 검사한다(`validate`, `validate_version`, 필드 경로 `version.*`). 바로가기 대상은 그 버전의 해석된 설치 파일과 비교한다. GUI `validate_project`와 CLI `validate`는 EXE에서 버전을 받는다(`--version`).
|
|
- 새 EXE 프로젝트는 버전 없이 시작한다. 설치 구성의 버전 목록은 버전이 없으면 "*기존 버전이 없습니다. 신규버전을 만드세요."를 표시하고, **버전 추가**로 번호를 지정해 빈 내용의 첫 버전을 만든다.
|
|
- 화면: 설치 구성은 버전 목록(버전·ProductCode·잠금·저장 상태·항목 수)과 버전 추가 양식을 먼저 보여 주고, 버전을 열면 위쪽에 **← 버전 목록**과 잠금 버튼, 아래에 일반 탭(버전·ProductCode·잠금 상태), 설치파일·레지스트리·바로가기 탭은 선택한 버전을 편집한다. 잠긴 버전은 읽기 전용이다. 설치 앱 정보에는 공유 설정만 남았다.
|
|
|
|
## 확인 결과
|
|
|
|
- 실행: `cargo fmt --check`, `cargo clippy -D warnings`, `cargo test --workspace`(56개 통과, SDK 통합 1개 무시), 프런트엔드 `npm test`(52개 통과)와 `npm run build`.
|
|
- 새로 검사한 항목: 버전 없는 새 프로젝트와 첫 버전 저장, 빈 버전 목록 안내·버전 목록·열린 버전 머리글 렌더링, 버전 파일 생성·재열기·저장 왕복, 새 버전 추가와 버전 순 정렬, 동시 추가 충돌, 잠금 시 내용 변경·삭제 거부와 해제 후 수정, 파일 이름 불일치 거부, 이전 형식 거부, 버전별 바로가기 대상 검사, 버전 필드 경로, 버전 복사의 독립성, 버전 스키마 계약.
|
|
- 실행하지 않음: GUI 클릭 시험(`guiClickTest: notRun`), `msix-studio` 데스크톱 빌드, EXE 빌드·설치 시험(미구현).
|
|
|
|
## 근거
|
|
|
|
- [Windows Installer ProductVersion](https://learn.microsoft.com/en-us/windows/win32/msi/productversion)
|
|
- [Windows Installer ProductCode](https://learn.microsoft.com/en-us/windows/win32/msi/productcode)
|
|
- [Windows Installer UpgradeCode](https://learn.microsoft.com/en-us/windows/win32/msi/upgradecode)
|
|
|
|
## 후속 변경 (같은 날): 버전 설명과 목록 정리
|
|
|
|
- `ExeVersion.description`(`#[serde(default)]`, 빈 문자열)을 추가했다. 제작자 메모이며 1000자를 넘으면 `DescriptionTooLong`(`version.description`)으로 거부한다. 설치 화면에는 쓰지 않는다. 버전을 복사해 추가하면 설명은 비운다. `schemas/exe-version.schema.json`을 다시 생성했다.
|
|
- 버전 목록 열을 버전·종류·ProductCode·설명으로 줄였다(설치파일 규칙·레지스트리·바로가기 개수 열 제거). 상태 아이콘과 삭제 버튼은 표 오른쪽 바깥에 둔다.
|
|
- 버전 › 일반 탭의 상태 행을 없애고 설명 입력을 추가했다. 잠금 상태는 위쪽 막대 오른쪽 끝의 **잠금** / **잠금 해제** 버튼으로 표시·변경한다.
|
|
- 위쪽 **← 버전 목록** 글자 버튼을 버전 번호 왼쪽의 화살표 아이콘 버튼으로 바꿨다. 버전이 열려 있을 때 사이드바의 **설치 구성**을 다시 눌러도 버전 목록으로 돌아간다.
|
|
- 검사: 설명 저장 왕복, 1000자 경계(문자 수 기준), 복사 시 설명 초기화, 목록 설명 이스케이프, 일반 탭 설명 입력과 잠금 시 비활성화, 머리글 버튼 상태.
|