(info, verbose=False)
| 627 | |
| 628 | |
| 629 | def create(info, verbose=False): |
| 630 | if not IS_WINDOWS: |
| 631 | raise OSError(f"Invalid platform '{sys.platform}'. MSI installers require Windows.") |
| 632 | |
| 633 | if not info.get("_conda_exe_supports_logging"): |
| 634 | raise ValueError("MSI installers require conda-standalone with logging support.") |
| 635 | |
| 636 | # Check briefcase exists before doing any work |
| 637 | briefcase = Path(sysconfig.get_path("scripts")) / "briefcase.exe" |
| 638 | if not briefcase.exists(): |
| 639 | raise FileNotFoundError( |
| 640 | f"Dependency 'briefcase' does not seem to be installed.\nTried: {briefcase}" |
| 641 | ) |
| 642 | |
| 643 | # MSI installers always use conda-standalone for uninstallation. |
| 644 | # This ensures proper cleanup of conda init, environments, and shortcuts |
| 645 | # via the `conda constructor uninstall` command. |
| 646 | info["uninstall_with_conda_exe"] = True |
| 647 | |
| 648 | signing_tool = create_windows_signing_tool(info) |
| 649 | |
| 650 | payload = Payload(info) |
| 651 | try: |
| 652 | payload.prepare() |
| 653 | |
| 654 | logger.info("Building MSI installer") |
| 655 | run( |
| 656 | [briefcase, "package"] + (["-v"] if verbose else []), |
| 657 | cwd=payload.root, |
| 658 | check=True, |
| 659 | ) |
| 660 | |
| 661 | dist_dir = payload.root / "dist" |
| 662 | msi_paths = list(dist_dir.glob("*.msi")) |
| 663 | if len(msi_paths) != 1: |
| 664 | raise RuntimeError(f"Found {len(msi_paths)} MSI files in {dist_dir}, expected 1.") |
| 665 | |
| 666 | if signing_tool: |
| 667 | signing_tool.sign(msi_paths[0]) |
| 668 | signing_tool.verify_signature(msi_paths[0]) |
| 669 | |
| 670 | outpath = Path(info["_outpath"]) |
| 671 | outpath.unlink(missing_ok=True) |
| 672 | shutil.move(msi_paths[0], outpath) |
| 673 | finally: |
| 674 | if not info.get("_debug"): |
| 675 | payload.remove() |
nothing calls this directly
no test coverage detected