diff --git a/.vscode/launch.json b/.vscode/launch.json index c0bbd09..909dc99 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -67,7 +67,7 @@ "id": "projectPath", "type": "promptString", "description": "프로젝트 JSON 경로 (절대 경로 또는 src 기준 상대 경로, 따옴표 없이 입력)", - "default": "fixtures/package-project.json" + "default": "fixtures/InstallerProject.isproj" }, { "id": "targetId", diff --git a/src/README.md b/src/README.md index 3c1b302..837b39e 100644 --- a/src/README.md +++ b/src/README.md @@ -12,7 +12,7 @@ npm.cmd ci npm.cmd run tauri dev ``` -새 프로젝트를 만들거나 `.json` 파일을 연 뒤 앱 정보 → 파일 구성에서 소스 폴더 연결 → 패키지 설정 → 검증·빌드에서 SDK 도구 선택 → 입력 검사 → 빌드 계획 생성 → MSIX 빌드 순서로 사용한다. 포함/제외 규칙과 의존성은 프로젝트 JSON 편집에서 수정한다. 기본 프로젝트의 Publisher는 예시이며 자신의 패키지 identity에 맞게 바꿔야 한다. +새 프로젝트를 만들거나 `.isproj` 파일을 연 뒤 앱 정보 → 파일 구성에서 소스 폴더 연결 → 패키지 설정 → 검증·빌드에서 SDK 도구 선택 → 입력 검사 → 빌드 계획 생성 → MSIX 빌드 순서로 사용한다. 포함/제외 규칙과 의존성은 프로젝트 JSON 편집에서 수정한다. 기본 프로젝트의 Publisher는 예시이며 자신의 패키지 identity에 맞게 바꿔야 한다. 시작 화면은 왼쪽 **최근 프로젝트 목록**, 오른쪽 **프로젝트 열기 / 새 프로젝트 만들기** 버튼으로 구성한다. 최근 목록은 이 버전의 GUI에서 열거나 만든 프로젝트를 최대 20개 보관하며 앱을 다시 실행해도 유지된다. 이름·경로 검색과 오늘/이번 주/이번 달/이전 그룹을 제공한다. 목록의 `×`는 기록만 제거하며 프로젝트 파일을 삭제하지 않는다. 이동·삭제된 파일은 위치 확인 안내를 표시한다. @@ -52,7 +52,7 @@ VS Code 빌드/시험 산출물은 `src/target/vscode`에 분리한다. 기존 ` | `MSIX CLI: Plan release` | 프로젝트 경로와 대상 ID를 받아 계획 생성 | | `MSIX CLI: Build plan` | 프로젝트 경로와 새 계획 UUID를 받아 실제 MSIX 생성 | -CLI 입력 경로는 절대 경로나 `src` 기준 상대 경로를 따옴표 없이 입력한다. 기본값 `fixtures/package-project.json`은 Publisher가 미확정인 초안이므로 검증 오류를 확인하는 용도다. 실제 빌드는 소스/SDK가 연결된 프로젝트를 사용한다. 시험 앱을 생성했다면 `.work/demo/FixtureAlpha/package-project.json`을 입력할 수 있다. 계획 ID는 `Plan release` 결과의 `id`를 사용한다. +CLI 입력 경로는 절대 경로나 `src` 기준 상대 경로를 따옴표 없이 입력한다. 기본값 `fixtures/InstallerProject.isproj`은 Publisher가 미확정인 초안이므로 검증 오류를 확인하는 용도다. 실제 빌드는 소스/SDK가 연결된 프로젝트를 사용한다. 시험 앱을 생성했다면 `.work/demo/FixtureAlpha/InstallerProject.isproj`을 입력할 수 있다. 계획 ID는 `Plan release` 결과의 `id`를 사용한다. 명령 팔레트의 `Tasks: Run Task`에서 `MSIX: test Rust`를 실행할 수 있다. MakeAppx 통합 시험은 기존 `scripts/Check.ps1 -MakeAppx ...`로 명시 실행한다. @@ -69,20 +69,20 @@ HKCU 초기화·COM/파일 연결·ISM 가져오기와 MSI 속성 치환은 아 아래 명령은 `src`에서 실행한다. stdout은 JSON, 오류는 stderr JSON이다. 개발자 서명 모드는 실제 MSIX 서명을 수행한다. 앱 설치와 PC의 인증서 신뢰 등록은 자동 수행하지 않는다. ```powershell -cargo run -p package-builder -- init --project D:\packages\demo\package-project.json -cargo run -p package-builder -- validate --project D:\packages\demo\package-project.json -cargo run -p package-builder -- plan release --project D:\packages\demo\package-project.json --target msix-direct -cargo run -p package-builder -- build --project D:\packages\demo\package-project.json --plan-id <계획의-id> -cargo run -p package-builder -- job status --project D:\packages\demo\package-project.json --id <계획의-id> -cargo run -p package-builder -- export --project D:\packages\demo\package-project.json --release <계획의-id> --output D:\exports\new-folder +cargo run -p package-builder -- init --project D:\packages\demo\InstallerProject.isproj +cargo run -p package-builder -- validate --project D:\packages\demo\InstallerProject.isproj +cargo run -p package-builder -- plan release --project D:\packages\demo\InstallerProject.isproj --target msix-direct +cargo run -p package-builder -- build --project D:\packages\demo\InstallerProject.isproj --plan-id <계획의-id> +cargo run -p package-builder -- job status --project D:\packages\demo\InstallerProject.isproj --id <계획의-id> +cargo run -p package-builder -- export --project D:\packages\demo\InstallerProject.isproj --release <계획의-id> --output D:\exports\new-folder cargo run -p package-builder -- schema ``` -프로젝트는 `.json`만 지원하며 내부 내용은 UTF-8 JSON v2다. 새 프로젝트의 기본 이름은 `package-project.json`이고, 확장자를 생략하면 `.json`를 붙인다. 기존 `.json` 프로젝트의 열기·호환·변환은 제공하지 않는다. 기존 JSON 항목은 최근 목록에서도 숨긴다. +프로젝트는 `.isproj`만 지원하며 내부 내용은 UTF-8 JSON v2다. 새 프로젝트의 기본 이름은 `InstallerProject.isproj`이고, 확장자를 생략하면 `.isproj`를 붙인다. 기존 `.json` 프로젝트의 열기·호환·변환은 제공하지 않는다. 기존 JSON 항목은 최근 목록에서도 숨긴다. 별도의 프로젝트 ID는 사용하지 않는다. MSIX 앱 계열은 패키지 설정의 Identity Name과 Publisher로 관리한다. 기존 `projectId` 필드가 포함된 개발용 파일은 자동 변환하지 않고 알 수 없는 필드로 거부한다. 현재 fixture와 샘플 생성 스크립트는 해당 필드 없이 프로젝트를 만든다. -프로젝트 옆 `<프로젝트 파일명>.local.json`에서 소스 alias와 SDK를 연결한다. 예를 들어 `package-project.local.json`이다. 상대 소스 경로는 프로젝트 폴더 기준이다. 기존 `package-project.local.json`은 읽지 않으며 local 파일은 Git에 넣지 않는다. 저장 시 이전 프로젝트는 `.json.bak`, 이전 로컬 설정은 `.json.local.json.bak`으로 보관한다. +프로젝트 옆 `<프로젝트 파일명>.local.json`에서 소스 alias와 SDK를 연결한다. 예를 들어 `InstallerProject.isproj.local.json`이다. 상대 소스 경로는 프로젝트 폴더 기준이다. 기존 `package-project.local.json`은 읽지 않으며 local 파일은 Git에 넣지 않는다. 저장 시 이전 프로젝트는 `.isproj.bak`, 이전 로컬 설정은 `.isproj.local.json.bak`으로 보관한다. ```json { diff --git a/src/apps/desktop/src-tauri/src/main.rs b/src/apps/desktop/src-tauri/src/main.rs index b4f4852..043c41b 100644 --- a/src/apps/desktop/src-tauri/src/main.rs +++ b/src/apps/desktop/src-tauri/src/main.rs @@ -121,7 +121,7 @@ async fn open_project( let Some(file) = rfd::AsyncFileDialog::new() .set_parent(&window) .set_title("프로젝트 열기") - .add_filter("Installer Studio 프로젝트", &["json"]) + .add_filter("Installer Studio 프로젝트", &["isproj"]) .pick_file() .await else { @@ -142,8 +142,8 @@ async fn new_project( let Some(file) = rfd::AsyncFileDialog::new() .set_parent(&window) .set_title("새 프로젝트 만들기") - .set_file_name("package-project.json") - .add_filter("Installer Studio 프로젝트", &["json"]) + .set_file_name("InstallerProject.isproj") + .add_filter("Installer Studio 프로젝트", &["isproj"]) .save_file() .await else { @@ -337,7 +337,7 @@ mod tests { #[test] fn close_clears_the_session_without_changing_the_project() { let temp = tempfile::tempdir().unwrap(); - let path = temp.path().join("project.json"); + let path = temp.path().join("project.isproj"); let doc = infra::create_project(&path).unwrap(); let original = std::fs::read(&path).unwrap(); let session = Session::default(); @@ -350,7 +350,7 @@ mod tests { #[test] fn close_is_rejected_while_build_is_running() { let temp = tempfile::tempdir().unwrap(); - let doc = infra::create_project(&temp.path().join("project.json")).unwrap(); + let doc = infra::create_project(&temp.path().join("project.isproj")).unwrap(); let session = Session::default(); set_document(&session, doc).unwrap(); session.busy.store(true, Ordering::SeqCst); diff --git a/src/apps/desktop/src-tauri/src/recent.rs b/src/apps/desktop/src-tauri/src/recent.rs index 6f52bac..8211ffc 100644 --- a/src/apps/desktop/src-tauri/src/recent.rs +++ b/src/apps/desktop/src-tauri/src/recent.rs @@ -74,6 +74,7 @@ impl RecentStore { Ok(history .projects .iter() + .filter(|project| package_infra::is_project_path(&project.path)) .map(|project| RecentView { available: project.path.is_file(), project: project.clone(), @@ -125,7 +126,7 @@ impl RecentStore { history .projects .iter() - .find(|entry| entry.id == id) + .find(|entry| entry.id == id && package_infra::is_project_path(&entry.path)) .map(|entry| entry.path.clone()) .context("최근 목록에서 프로젝트를 찾을 수 없습니다. 목록을 새로 고치세요.") }, @@ -163,8 +164,8 @@ mod tests { fn history_persists_deduplicates_and_removal_keeps_project_file() { let temp = tempfile::tempdir().unwrap(); let store = RecentStore(temp.path().join("history")); - let mut first = package_infra::create_project(&temp.path().join("first.json")).unwrap(); - let second = package_infra::create_project(&temp.path().join("second.json")).unwrap(); + let mut first = package_infra::create_project(&temp.path().join("first.isproj")).unwrap(); + let second = package_infra::create_project(&temp.path().join("second.isproj")).unwrap(); store.remember(&first, true).unwrap(); let first_id = store.list().unwrap()[0].project.id.clone(); store.remember(&second, true).unwrap(); @@ -186,14 +187,14 @@ mod tests { fn history_is_bounded_and_missing_files_are_visible() { let temp = tempfile::tempdir().unwrap(); let store = RecentStore(temp.path().join("history")); - let mut doc = package_infra::create_project(&temp.path().join("fixture.json")).unwrap(); + let mut doc = package_infra::create_project(&temp.path().join("fixture.isproj")).unwrap(); for i in 0..25 { - doc.path = temp.path().join(format!("missing-{i}.json")); + doc.path = temp.path().join(format!("missing-{i}.isproj")); store.remember(&doc, true).unwrap(); } let entries = store.list().unwrap(); assert_eq!(entries.len(), MAX_RECENT); - assert!(entries[0].project.path.ends_with("missing-24.json")); + assert!(entries[0].project.path.ends_with("missing-24.isproj")); assert!(entries.iter().all(|entry| !entry.available)); } @@ -204,10 +205,22 @@ mod tests { fs::create_dir_all(&store.0).unwrap(); let history_path = store.0.join("recent-projects.json"); fs::write(&history_path, b"broken").unwrap(); - let doc = package_infra::create_project(&temp.path().join("fixture.json")).unwrap(); + let doc = package_infra::create_project(&temp.path().join("fixture.isproj")).unwrap(); assert!(store.remember(&doc, true).is_err()); assert_eq!(fs::read(history_path).unwrap(), b"broken"); } - + #[test] + fn legacy_history_is_hidden_and_cannot_be_opened_by_id() { + let temp = tempfile::tempdir().unwrap(); + let store = RecentStore(temp.path().join("history")); + let mut doc = package_infra::create_project(&temp.path().join("current.isproj")).unwrap(); + store.remember(&doc, true).unwrap(); + doc.path = temp.path().join("legacy.json"); + store.remember(&doc, true).unwrap(); + let id = store.load().unwrap().projects[0].id.clone(); + assert_eq!(store.list().unwrap().len(), 1); + assert!(store.find(&id).is_err()); + assert_eq!(store.load().unwrap().projects.len(), 2); + } } diff --git a/src/apps/desktop/tests/start-screen.test.mjs b/src/apps/desktop/tests/start-screen.test.mjs index 9049155..baa8d7b 100644 --- a/src/apps/desktop/tests/start-screen.test.mjs +++ b/src/apps/desktop/tests/start-screen.test.mjs @@ -4,7 +4,7 @@ import { displayPath, groupRecentProjects, renderStartScreen } from '../src/star import { allowProjectTransition } from '../src/project-transition.ts'; const recent = (id, year, month, day, name = id) => ({ - id, path: `C:\\projects\\${id}\\package-project.json`, displayName: name, + id, path: `C:\\projects\\${id}\\InstallerProject.isproj`, displayName: name, lastOpenedAt: new Date(year, month - 1, day, 10).getTime() / 1000, available: true, }); @@ -18,8 +18,8 @@ test('recent projects are grouped in local calendar order and searchable by name }); test('extended Windows paths are displayed without changing their UNC semantics', () => { - assert.equal(displayPath('\\\\?\\C:\\apps\\project.json'), 'C:\\apps\\project.json'); - assert.equal(displayPath('\\\\?\\UNC\\server\\share\\project.json'), '\\\\server\\share\\project.json'); + assert.equal(displayPath('\\\\?\\C:\\apps\\project.isproj'), 'C:\\apps\\project.isproj'); + assert.equal(displayPath('\\\\?\\UNC\\server\\share\\project.isproj'), '\\\\server\\share\\project.isproj'); }); test('start screen has left recent projects and right actions without fabricated entries', () => { diff --git a/src/crates/package-domain/src/lib.rs b/src/crates/package-domain/src/lib.rs index 536f9a5..bc98244 100644 --- a/src/crates/package-domain/src/lib.rs +++ b/src/crates/package-domain/src/lib.rs @@ -430,7 +430,7 @@ mod tests { #[test] fn example_requires_publisher_but_not_exe() { let project: Project = - serde_json::from_str(include_str!("../../../fixtures/package-project.json")) + serde_json::from_str(include_str!("../../../fixtures/InstallerProject.isproj")) .unwrap(); assert_eq!( validate(&project) diff --git a/src/crates/package-infra/src/store.rs b/src/crates/package-infra/src/store.rs index 465f832..bbb8474 100644 --- a/src/crates/package-infra/src/store.rs +++ b/src/crates/package-infra/src/store.rs @@ -58,12 +58,39 @@ fn atomic_bytes(path: &Path, bytes: &[u8]) -> Result<()> { temp.persist(path).map_err(|error| error.error)?; Ok(()) } +pub fn is_project_path(path: &Path) -> bool { + path.extension() + .is_some_and(|ext| ext.eq_ignore_ascii_case("isproj")) + && !path.file_stem().is_some_and(|stem| { + Path::new(stem) + .extension() + .is_some_and(|ext| ext.eq_ignore_ascii_case("isproj")) + }) +} +fn check_project_path(path: &Path) -> Result<()> { + ensure!(is_project_path(path), "UnsupportedProjectExtension: .isproj 프로젝트만 지원합니다. 기존 .json 프로젝트는 지원하지 않습니다."); + Ok(()) +} +pub fn new_project_path(path: &Path) -> Result { + ensure!(path.file_name().is_some(), "MissingFilename"); + let path = if path.extension().is_none() { + path.with_extension("isproj") + } else { + path.to_path_buf() + }; + check_project_path(&path)?; + Ok(path) +} pub fn appended_path(path: &Path, suffix: &str) -> PathBuf { let mut name = path.as_os_str().to_os_string(); name.push(suffix); PathBuf::from(name) } +pub fn local_config_path(path: &Path) -> PathBuf { + appended_path(path, ".local.json") +} pub fn open_project(path: &Path) -> Result { + check_project_path(path)?; reject_links(path)?; let path = path.canonicalize()?; let bytes = fs::read(&path)?; @@ -73,7 +100,7 @@ pub fn open_project(path: &Path) -> Result { project.schema_version == 2, "UnsupportedSchema: v2 프로젝트만 열 수 있습니다. 원본을 자동 변환하지 않습니다." ); - let local_path = path.parent().unwrap().join("package-project.local.json"); + let local_path = local_config_path(&path); reject_links(&local_path)?; let local_bytes = if local_path.exists() { fs::read(&local_path)? @@ -112,8 +139,8 @@ pub fn save_project(document: &ProjectDocument) -> Result { ); // A draft may be incomplete, but never silently accept a different schema. ensure!(document.project.schema_version == 2, "UnsupportedSchema"); - let project_backup = document.path.with_extension("json.bak"); - let local_path = document.path.parent().unwrap().join("package-project.local.json"); + let project_backup = appended_path(&document.path, ".bak"); + let local_path = local_config_path(&document.path); let local_backup = appended_path(&local_path, ".bak"); for backup in [&project_backup, &local_backup] { reject_links(backup)?; @@ -141,12 +168,17 @@ pub fn save_project(document: &ProjectDocument) -> Result { open_project(&document.path) } pub fn create_project(path: &Path) -> Result { - ensure!(path.file_name().is_some(), "MissingFilename"); + let normalized = new_project_path(path)?; + let path = normalized.as_path(); reject_links(path)?; fs::create_dir_all(path.parent().context("MissingParent")?)?; let _lock = lock_project(path.parent().unwrap())?; + ensure!( + !local_config_path(path).exists(), + "LocalConfigAlreadyExists" + ); let mut value: serde_json::Value = - serde_json::from_str(include_str!("../../../fixtures/package-project.json"))?; + serde_json::from_str(include_str!("../../../fixtures/InstallerProject.isproj"))?; value["formats"]["msix"]["identity"]["publisher"] = serde_json::Value::String("CN=Example Publisher".into()); let mut file = File::options() diff --git a/src/crates/package-infra/tests/project_format.rs b/src/crates/package-infra/tests/project_format.rs new file mode 100644 index 0000000..08f61ec --- /dev/null +++ b/src/crates/package-infra/tests/project_format.rs @@ -0,0 +1,145 @@ +use package_infra as infra; +use std::fs; + +#[test] +fn new_projects_normalize_extension_and_roundtrip_local_settings_and_backups() { + let temp = tempfile::tempdir().unwrap(); + let mut doc = infra::create_project(&temp.path().join("한글 프로젝트")).unwrap(); + assert!(doc.path.ends_with("한글 프로젝트.isproj")); + let original = fs::read(&doc.path).unwrap(); + assert!(serde_json::from_slice::(&original) + .unwrap() + .get("projectId") + .is_some()); + doc.project.product.display_name = "변경된 제품".into(); + doc.local + .sources + .insert("appPayload".into(), "payload".into()); + doc.local.developer_certificate_thumbprint = Some("A".repeat(40)); + let saved = infra::save_project(&doc).unwrap(); + assert_eq!(saved.local.sources["appPayload"], "payload"); + assert_eq!( + saved.local.developer_certificate_thumbprint, + doc.local.developer_certificate_thumbprint + ); + assert_eq!( + saved.project.formats.msix.identity.name, + doc.project.formats.msix.identity.name + ); + assert_eq!( + saved.project.formats.msix.identity.publisher, + doc.project.formats.msix.identity.publisher + ); + assert_eq!( + fs::read(infra::appended_path(&doc.path, ".bak")).unwrap(), + original + ); + let local_path = infra::local_config_path(&doc.path); + assert!(local_path.ends_with("한글 프로젝트.isproj.local.json")); + let local_bytes = fs::read(&local_path).unwrap(); + infra::save_project(&saved).unwrap(); + assert_eq!( + fs::read(infra::appended_path(&local_path, ".bak")).unwrap(), + local_bytes + ); + assert!(!temp.path().join("한글 프로젝트.json.bak").exists()); +} + +#[test] +fn json_and_duplicate_extensions_are_rejected_even_with_valid_contents() { + let temp = tempfile::tempdir().unwrap(); + let doc = infra::create_project(&temp.path().join("Sample.ISPROJ")).unwrap(); + assert!(infra::open_project(&doc.path).is_ok()); + for name in [ + "legacy.json", + "bad.txt", + "duplicate.isproj.isproj", + "no-extension", + ] { + let path = temp.path().join(name); + fs::copy(&doc.path, &path).unwrap(); + assert!(infra::open_project(&path) + .unwrap_err() + .to_string() + .contains("UnsupportedProjectExtension")); + if name != "no-extension" { + assert!(infra::create_project(&path) + .unwrap_err() + .to_string() + .contains("UnsupportedProjectExtension")); + } + } + assert!(infra::create_project(&doc.path).is_err()); + fs::write(temp.path().join("broken.isproj"), "not json").unwrap(); + assert!(infra::open_project(&temp.path().join("broken.isproj")).is_err()); +} + +#[test] +fn no_legacy_local_fallback_and_no_overwrite_of_orphan_local_settings() { + let temp = tempfile::tempdir().unwrap(); + fs::write( + temp.path().join("package-project.local.json"), + r#"{"sources":{"legacy":"do-not-load"},"makeAppx":null}"#, + ) + .unwrap(); + let doc = infra::create_project(&temp.path().join("fresh.isproj")).unwrap(); + assert!(doc.local.sources.is_empty()); + let path = temp.path().join("orphan.isproj"); + fs::write(infra::local_config_path(&path), "keep").unwrap(); + assert!(infra::create_project(&path) + .unwrap_err() + .to_string() + .contains("LocalConfigAlreadyExists")); + assert!(!path.exists()); +} + + + +#[test] +fn local_revision_conflicts_and_failed_backup_preserve_both_files() { + let temp = tempfile::tempdir().unwrap(); + let doc = infra::create_project(&temp.path().join("sample.isproj")).unwrap(); + let mut doc = infra::save_project(&doc).unwrap(); + let local_path = infra::local_config_path(&doc.path); + let original = fs::read(&doc.path).unwrap(); + let local = fs::read(&local_path).unwrap(); + fs::write(&local_path, b"{\"sources\":{},\"makeAppx\":null}\n").unwrap(); + assert!(infra::save_project(&doc) + .unwrap_err() + .to_string() + .contains("RevisionConflict")); + fs::write(&local_path, &local).unwrap(); + fs::create_dir(infra::appended_path(&local_path, ".bak")).unwrap(); + doc.project.product.display_name = "must not commit".into(); + doc.local + .sources + .insert("appPayload".into(), "changed".into()); + assert!(infra::save_project(&doc).is_err()); + assert_eq!(fs::read(&doc.path).unwrap(), original); + assert_eq!(fs::read(&local_path).unwrap(), local); +} + +#[cfg(windows)] +#[test] +fn failed_project_replacement_restores_previous_local_settings() { + use std::os::windows::fs::OpenOptionsExt; + let temp = tempfile::tempdir().unwrap(); + let doc = infra::create_project(&temp.path().join("locked.isproj")).unwrap(); + let mut doc = infra::save_project(&doc).unwrap(); + let local_path = infra::local_config_path(&doc.path); + let project_before = fs::read(&doc.path).unwrap(); + let local_before = fs::read(&local_path).unwrap(); + // Permit reading and writing, but hold back FILE_SHARE_DELETE so replacement fails. + let _held = fs::OpenOptions::new() + .read(true) + .share_mode(3) + .open(&doc.path) + .unwrap(); + doc.project.product.display_name = "must roll back".into(); + doc.local + .sources + .insert("appPayload".into(), "changed".into()); + assert!(infra::save_project(&doc).is_err()); + assert_eq!(fs::read(&doc.path).unwrap(), project_before); + assert_eq!(fs::read(local_path).unwrap(), local_before); +} diff --git a/src/crates/package-infra/tests/workflow.rs b/src/crates/package-infra/tests/workflow.rs index b9b4e10..287c928 100644 --- a/src/crates/package-infra/tests/workflow.rs +++ b/src/crates/package-infra/tests/workflow.rs @@ -18,7 +18,7 @@ fn png(path: &Path, size: u32) { } fn fixture() -> (tempfile::TempDir, PathBuf) { let temp = tempfile::tempdir().unwrap(); - let path = temp.path().join("package-project.json"); + let path = temp.path().join("InstallerProject.isproj"); let mut doc = infra::create_project(&path).unwrap(); let payload = temp.path().join("payload"); fs::create_dir_all(payload.join("Assets")).unwrap(); diff --git a/src/fixtures/package-project.json b/src/fixtures/InstallerProject.isproj similarity index 100% rename from src/fixtures/package-project.json rename to src/fixtures/InstallerProject.isproj diff --git a/src/scripts/New-Fixtures.ps1 b/src/scripts/New-Fixtures.ps1 index 136b22f..06def48 100644 --- a/src/scripts/New-Fixtures.ps1 +++ b/src/scripts/New-Fixtures.ps1 @@ -22,13 +22,13 @@ foreach ($name in @('FixtureAlpha', 'FixtureBeta')) { } finally { $env:FIXTURE_NAME = $previousName } Copy-Item -LiteralPath (Join-Path $sourceRoot 'apps/desktop/src-tauri/icons/Square44x44Logo.png') -Destination (Join-Path $assetRoot 'Logo44.png') Copy-Item -LiteralPath (Join-Path $sourceRoot 'apps/desktop/src-tauri/icons/Square150x150Logo.png') -Destination (Join-Path $assetRoot 'Logo150.png') - $project = Get-Content -Raw -Encoding UTF8 (Join-Path $sourceRoot 'fixtures/package-project.json') | ConvertFrom-Json + $project = Get-Content -Raw -Encoding UTF8 (Join-Path $sourceRoot 'fixtures/InstallerProject.isproj') | ConvertFrom-Json $project.projectId = $name $project.product.displayName = $name $project.formats.msix.identity.name = "ExamplePublisher.$name" $project.formats.msix.identity.publisher = 'CN=Example Publisher' - [IO.File]::WriteAllText((Join-Path $projectRoot 'package-project.json'), ($project | ConvertTo-Json -Depth 30), $utf8) + [IO.File]::WriteAllText((Join-Path $projectRoot 'InstallerProject.isproj'), ($project | ConvertTo-Json -Depth 30), $utf8) $local = @{ sources = @{ appPayload = 'payload' }; makeAppx = $sdkTool } - [IO.File]::WriteAllText((Join-Path $projectRoot 'package-project.local.json'), ($local | ConvertTo-Json -Depth 10), $utf8) - Write-Output (Join-Path $projectRoot 'package-project.json') + [IO.File]::WriteAllText((Join-Path $projectRoot 'InstallerProject.isproj.local.json'), ($local | ConvertTo-Json -Depth 10), $utf8) + Write-Output (Join-Path $projectRoot 'InstallerProject.isproj') } diff --git a/src/scripts/Prepare-EgbimMsixSample.py b/src/scripts/Prepare-EgbimMsixSample.py index dd56667..75b1236 100644 --- a/src/scripts/Prepare-EgbimMsixSample.py +++ b/src/scripts/Prepare-EgbimMsixSample.py @@ -179,8 +179,8 @@ def main(): "capabilities": ["runFullTrust"], "extensions": [], "dependencies": []}}, "targets": [{"id": "msix-direct", "format": "msix", "delivery": "package", "distribution": "direct", "signingProfileRef": None}]} - write_json(out / "package-project.json", project) - write_json(out / "package-project.local.json", {"sources": local_sources, "makeAppx": str(args.makeappx.resolve())}) + write_json(out / "InstallerProject.isproj", project) + write_json(out / "InstallerProject.isproj.local.json", {"sources": local_sources, "makeAppx": str(args.makeappx.resolve())}) write_json(out / "reports/file-mapping.json", mappings) with (out / "reports/file-mapping.csv").open("w", encoding="utf-8-sig", newline="") as f: writer = csv.DictWriter(f, fieldnames=list(mappings[0])); writer.writeheader(); writer.writerows(mappings)