feat: add EXE projects with versioned install configuration

- 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>
This commit is contained in:
jychoi4andClaude Opus 5.5 committed 2026-11-11 11:10:00 +09:00
1 parent 905e6d4eaa
commit 366c8fe173
69 files changed
+9295 -441

No files matched your search

@@ -0,0 +1,48 @@
# 설치파일 트리의 파일·폴더 삭제
2026-11-11. 설치 구성 › 설치파일 트리의 파일과 폴더 행에 삭제 버튼을 추가했다. 삭제는 이 버전의 설치 목록에서 빼는 것이며 소스 폴더의 실제 파일은 지우지 않는다. 화면과 규칙 편집까지이며 EXE 빌드·설치 시험은 범위 밖이다.
## 사용
1. 트리의 파일이나 폴더 행에 마우스를 올리면(키보드 포커스 포함) 오른쪽에 휴지통 버튼이 나온다. 설치 폴더(INSTALLDIR) 자체에는 없다.
2. 파일은 바로 빠진다. 폴더는 "폴더를 삭제할까요?" 팝업에서 경로와 안의 파일 수를 확인한 뒤 **삭제**를 누른다.
3. 저장해야 버전 파일에 반영된다. 저장 전에는 저장하지 않고 닫으면 되돌릴 수 있다. 잠긴 버전은 버튼이 비활성화된다.
## 모델과 실행
- 파일: 파일 추가로 넣은 파일(규칙의 포함 패턴이 그 파일 이름)은 그 이름을 포함 패턴에서 지우고, 포함 패턴이 비면 규칙도 지운다. `**/*` 같은 패턴으로 들어온 파일은 그 규칙의 제외 패턴에 경로를 문자 그대로(`[ ] * ? { }` 이스케이프) 더한다.
- 폴더: 그 폴더나 하위를 대상으로 하는 규칙을 지운다. 위쪽 폴더의 규칙이 그 폴더에 파일을 넣고 있으면 그 규칙의 제외 패턴에 `폴더/**`를 더한다. 추가만 하고 비어 있던 폴더도 함께 지운다. Windows 기본 폴더 루트(예: ProgramData)도 지울 수 있으며, 설치 폴더 쪽 규칙은 다른 루트에 영향을 주지 않는다.
- 어느 규칙이 파일을 넣었는지는 파일 목록 미리보기(`preview_files`)의 규칙 ID로 판단한다. 목록을 읽는 중에는 `NotScanned`로 막고, 규칙을 찾지 못하면 `UnknownRule`, 설치 폴더 자체는 `InstallFolderRemoval`로 거부한다.
- 패치 버전에서 이전 버전이 설치한 파일을 빼면 기존처럼 입력 검사가 `PatchRemovesFiles`로 거부한다.
- 범위 밖: 여러 항목 한꺼번에 삭제, 실행 취소, 드래그로 옮기기.
## 확인 결과
- 프런트엔드 테스트 82개 통과; TypeScript/Vite 빌드 통과. 이름 규칙에서 빼기와 빈 규칙 삭제, 패턴 규칙 제외(한 번만, 문자 그대로), 다른 루트의 파일 제외, 폴더 삭제 시 하위 규칙 삭제·위쪽 규칙 제외·대기 폴더 정리, 루트 폴더 삭제, 설치 폴더·읽는 중·모르는 규칙 거부, 버튼 표시·잠금, 확인 팝업 이스케이프를 검사한다.
- Rust 코드는 바뀌지 않았다(Rust 테스트 72개 기존 통과 상태).
- 실제 앱에서 버튼을 눌러 보는 GUI 시험은 수행하지 않았다.
## 후속 변경 (같은 날): 설치파일 화면 단순화
- 설치파일 탭에는 **폴더 추가**·**파일 추가** 버튼과 트리만 남겼다. 트리 아래 **파일 규칙(고급)**(패턴 규칙 카드·패턴 규칙 추가), 제목 줄(설치 폴더 경로), "추가할 위치" 줄, "파일 목록을 읽는 중" 문구를 없앴다. 경고(소스 alias 없음, 읽지 못한 규칙, VFS)는 있을 때만 표시한다.
- 소스 폴더 연결 버튼이 고급 영역에만 있었으므로, **파일 추가**를 눌렀을 때 이 PC에 연결된 소스 폴더가 없으면 먼저 소스 폴더 선택 창을 띄운다. 기존 폴더 선택과 같이 연결 전후로 프로젝트를 저장한다. `MissingSource` 안내 문구도 설치파일 탭 기준으로 바꿨다.
- 패턴(`**/*`, 제외 패턴)·소스 기준 폴더를 화면에서 고치는 기능과 연결된 소스 폴더를 바꾸는 기능은 화면에서 빠졌다. 규칙을 직접 고치려면 앱을 닫은 상태에서 `.isver`를 수정한다.
- 확인: 프런트엔드 테스트 78개 통과, TypeScript/Vite 빌드와 Rust 검사·데스크톱 빌드 통과. GUI 클릭 시험은 수행하지 않았다.
## 후속 변경 (같은 날): 버튼 위치·선택 기준·소스 연결
- 트리를 감싼 테두리 박스를 없애고 **폴더 추가**·**파일 추가**를 탭 설명 줄 오른쪽 끝으로 옮겼다.
- 폴더뿐 아니라 파일도 선택할 수 있다. 추가 위치는 선택한 폴더, 선택한 파일의 폴더, 선택이 없으면 최상위(설치 폴더)다. 처음에는 아무것도 선택되어 있지 않다. 선택한 파일을 다시 누르거나 트리의 빈 곳을 누르면 선택이 풀린다.
- **파일 추가**는 소스 폴더 선택 창 없이 바로 파일 선택 창을 연다. 이 PC에 연결된 소스 폴더가 없으면 고른 파일이 있는 폴더(여러 파일이면 공통 상위 폴더)를 첫 소스의 폴더로 연결한다. 드라이브 루트는 미리보기·빌드가 드라이브 전체를 읽게 되므로 `RootSource`로 거부한다. 연결은 세션에만 바뀌고 저장해야 로컬 설정 파일에 쓴다. 이미 연결된 소스 밖의 파일은 연결된 폴더 경로를 알려 주는 `OutsideSource`로 거부한다.
- 확인: Rust 테스트 통과(`common_folder`의 공통 폴더·드라이브 루트 거부, `OutsideSource` 문구 포함), 프런트엔드 테스트 80개 통과, 데스크톱 빌드 통과. GUI 클릭 시험은 수행하지 않았다.
## 후속 변경 (같은 날): 행별 추가 버튼과 설치 위치 추가
- 폴더 추가·파일 추가를 각 폴더 행 오른쪽의 아이콘 버튼으로 옮겼다. 추가는 버튼을 누른 그 폴더에 들어간다. 파일 행에는 삭제 버튼만 있다. 행 선택(강조)과 선택 기준 추가는 없앴고, 폴더 행을 누르면 접히거나 펼쳐진다.
- 탭 설명 줄 오른쪽 끝에는 **설치 위치 추가**(EXE만)만 둔다. 아직 트리에 없는 Windows 기본 폴더(`TARGET_ROOTS`, x86은 64비트 폴더 제외)를 골라 트리에 루트로 더하며, 모두 추가했으면 비활성화된다. 추가한 루트는 행의 삭제로 다시 뺄 수 있다.
- 폴더 추가 팝업은 기본 위치 선택·직접 입력 대신 그 폴더 아래에 만들 이름만 받는다. `Data\Config`처럼 여러 단계를 한 번에 만들 수 있다.
- 새 버전은 설치 폴더 행(폴더·파일 추가 버튼 포함)과 "*설치할 파일들을 추가하세요." 문구로 시작한다.
- 확인: 프런트엔드 테스트 78개 통과, TypeScript/Vite 빌드 통과. Rust 코드는 바뀌지 않았다. GUI 클릭 시험은 수행하지 않았다.
- 루트 행에 전체 설치 경로를 표시하고, 하위 폴더·파일 행은 마우스를 올리면 전체 경로를 보여 준다(프런트엔드 테스트 79개 통과).
- 기본 설치 폴더(EXE)도 삭제할 수 있다. 그 안을 대상으로 하는 규칙과 대기 폴더를 지우고 트리에서 숨긴다(다른 루트는 영향 없음). 설치 위치 추가로 다시 넣거나 그 안을 대상으로 하는 항목이 생기면 다시 보인다. 숨김은 화면 상태라 버전을 다시 열면 원래대로 보인다.
- 설치 위치 추가 팝업은 기본 설치 폴더와 허용된 Windows 폴더를 모두 나열하고, 이미 트리에 있는 위치는 "추가됨"으로 비활성화한다. **직접 입력…**으로 `[속성]하위\경로`(속성 없으면 기본 설치 폴더 기준)를 받는다. 허용되지 않은 속성은 `UnsupportedTargetRoot`, 이미 있는 위치·폴더는 `DuplicateFolder`로 팝업 안에 표시한다. 프런트엔드 테스트 81개 통과.