diff --git a/.github/scripts/build_packages.py b/.github/scripts/build_packages.py index 5e32861..e503b14 100644 --- a/.github/scripts/build_packages.py +++ b/.github/scripts/build_packages.py @@ -83,17 +83,37 @@ def how_to_start(package, feed): - """The paragraph that differs by feed: what the package gives and how to start it.""" + """The paragraph that differs by feed: what the package gives and how to start it. + + The WinGet sentences about upgrading are measured, not assumed, with WinGet + 1.29.380 on 2026-09-25: on Windows Server 2025 in machine scope and on + Windows 11 in user scope, upgrading the window while it was open failed + with "Access is denied" and left the package folder half removed until the + upgrade ran again with the window closed. On Windows 11 the command line + did the same while a tfg command was running. A portable package can carry + no script to warn at that moment, so the description is the only place a + person can read it first. + """ other = next(p for p in PACKAGES if p is not package) other_id = other.winget_id if feed == "winget" else other.choco_id if package.kind == "cli": - return ("This package is the command line, for scripts and pipelines. The desktop " + text = ("This package is the command line, for scripts and pipelines. The desktop " "window is the package %s. Type tfg help to see the commands." % other_id) + if feed == "winget": + # "when tfg is not running" rather than naming a command: any tfg + # command holds the program file while it runs, and "a tfg run" read + # as a command that does not exist (outside review of #144). + text += (" Upgrade it when tfg is not running. WinGet cannot replace tfg while " + "it runs, so it stops half way, and the package works again once the " + "upgrade runs after tfg has finished.") + return text if feed == "winget": return ("This package is the desktop window. The command line is the package %s. " "WinGet adds no Start menu shortcut for it. Open a new terminal and type " "tfg-gui. The window offers a tfg-out folder in the directory it was started " - "from." % other_id) + "from. Close the window before you upgrade. WinGet cannot replace a running " + "program, so it stops half way, and the package works again once the " + "upgrade runs with the window closed." % other_id) return ("This package is the desktop window. The command line is the package %s. It " "adds a Start menu shortcut and the tfg-gui command. Started from the shortcut, " "the window offers a tfg-out folder in your user profile." % other_id) diff --git a/packaging/README.md b/packaging/README.md index cc7acb4..d6cb146 100644 --- a/packaging/README.md +++ b/packaging/README.md @@ -35,7 +35,13 @@ the real file. With it, WinGet makes no link and puts the package's folder on `PATH`. The command line would work either way, but without the field its shape depends on the machine - a link where symbolic links are allowed, the folder on `PATH` where they are not. WinGet adds no Start menu shortcut for a portable -package, and the window's description says so. +package, and the window's description says so. One cost of the field is not +ours to fix. WinGet 1.29.380 left the package's folder on `PATH` after an +uninstall, for both of these packages, in machine scope on Windows Server 2025 +and in user scope on Windows 11 - measured on 2026-09-25, the entry stays and +points at a folder that no longer exists. +[microsoft/winget-cli#6160](https://github.com/microsoft/winget-cli/issues/6160), +open, reports the same for another package that sets the field. **Chocolatey.** The package downloads the release archive rather than carrying it, so it holds no binaries and owes no `VERIFICATION.txt`, and the archive is the @@ -50,10 +56,23 @@ into the package. The icon is a jsDelivr address pinned to the release tag: moderation refuses `raw.githubusercontent.com` and `github.com/.../raw` alike, and an icon on a branch would keep changing under an approved package. -**Neither package ends a running program.** `chocolateybeforemodify.ps1` says when -the program is still running from the package, and leaves closing it to the -person - a run in progress may be halfway through a set of files, and cutting it -would leave files with no manifest to say what they are. +**Neither package ends a running program** - a run in progress may be halfway +through a set of files, and cutting it would leave files with no manifest to say +what they are. What each feed does instead was measured on 2026-09-25, with the +program running - Chocolatey on Windows Server 2025, WinGet there in machine +scope and on Windows 11 in user scope: + +- **Chocolatey goes ahead**, an upgrade and an uninstall alike, and reports + success. It moves the package folder aside to `lib-bkp`, and the running copy + keeps working from there - but it cannot delete that copy, so the copy stays: + after an upgrade until the next Chocolatey operation on the package, after an + uninstall for good. `chocolateybeforemodify.ps1` says so at that moment and + names the folder to delete once the program is closed. +- **WinGet stops half way.** An upgrade fails with "Access is denied" on the + program, having already deleted some of the other files, and the package works + again once the upgrade runs with the program closed. Measured for the window + and, on Windows 11, for the command line while a tfg command was running. A portable + package carries no script, so the description is where this is said. ## Submitting diff --git a/packaging/chocolatey/tools/chocolateybeforemodify.ps1.in b/packaging/chocolatey/tools/chocolateybeforemodify.ps1.in index 88b79ba..3d2a8c5 100644 --- a/packaging/chocolatey/tools/chocolateybeforemodify.ps1.in +++ b/packaging/chocolatey/tools/chocolateybeforemodify.ps1.in @@ -2,8 +2,15 @@ # # Chocolatey runs this from the INSTALLED package before an upgrade or an # uninstall. It says so when the program is still running from this package, -# because Windows does not let the files of a running program be replaced, and -# a person should hear why before the operation that follows complains. +# and it says what will really happen, which was measured rather than assumed +# (Windows Server 2025, docs/PACKAGING-2026-09-25.md section 10). It does not +# fail: Chocolatey moves the package folder aside to lib-bkp, goes ahead and +# reports success, and the running copy keeps working from there. What it +# cannot do is delete that copy while it runs, so the copy stays in lib-bkp - +# after an upgrade until the next Chocolatey operation on this package, and +# after an uninstall for good, because there may be no next operation. The +# first version of this message said the operation would fail, which it did +# not. # # It never ends the program. That is the owner's decision of 2026-09-25: a run # in progress may be halfway through writing a set of files, and cutting it @@ -28,5 +35,7 @@ try { } if ($running.Count -gt 0) { - Write-Warning '{{TITLE}} is running from this package. Close it before you upgrade or remove the package. Windows does not let the files of a running program be replaced.' + $leftover = Join-Path $env:ChocolateyInstall 'lib-bkp\{{CHOCO_ID}}' + Write-Warning '{{TITLE}} is running from this package. Chocolatey goes ahead, but it cannot delete the running copy, so that copy stays behind.' + Write-Warning "It is left in $leftover. Close the program, then delete that folder." }