Skip to content

Commit 162a5cd

Browse files
authored
Fix regression that placed the pre-uninstall script in the package cache. (#1205)
* Fix location of pre-uninstall script for EXE installers * Move options parsing before pre-uninstall scripts * Use global variable for uninstallation options * Update tests * Add news
1 parent ad51ed4 commit 162a5cd

3 files changed

Lines changed: 66 additions & 36 deletions

File tree

constructor/nsis/main.nsi.tmpl

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1823,47 +1823,51 @@ Section "Uninstall"
18231823
System::Call 'kernel32::SetEnvironmentVariable(t,t)i("INSTALLER_UNATTENDED", "0")'
18241824
${EndIf}
18251825

1826-
${If} ${FileExists} "$INSTDIR\pkgs\pre_uninstall.bat"
1827-
${Print} "Running pre-uninstall script..."
1828-
# `type` is used to simulate a `tee`-like output in cmd.exe
1829-
push '"$INSTDIR\pkgs\pre_uninstall.bat" > "${STEP_LOG}" 2>&1 & SET ERR=!ERRORLEVEL! & type "${STEP_LOG}" & EXIT /B !ERR!'
1830-
push "Failed to run pre-uninstall scripts."
1831-
push 'WithLog'
1832-
call un.AbortRetryNSExecWait
1833-
${EndIf}
1834-
${If} ${FileExists} "$INSTDIR\.nonadmin"
1835-
!insertmacro AddRemovePath "remove" "un."
1836-
${EndIf}
1837-
18381826
{%- if uninstall_with_conda_exe %}
1839-
# Parse arguments
1840-
StrCpy $R0 ""
1827+
# Parse uninstall options
1828+
var /global UninstOptions
1829+
StrCpy $UninstOptions ""
18411830

18421831
${If} $UninstRemoveConfigFiles_User_State == ${BST_CHECKED}
18431832
${If} $UninstRemoveConfigFiles_System_State == ${BST_CHECKED}
1844-
StrCpy $R0 "$R0 --remove-config-files=all"
1833+
StrCpy $UninstOptions "$UninstOptions --remove-config-files=all"
18451834
System::Call 'kernel32::SetEnvironmentVariable(t,t)i("UNINSTALLER_REMOVE_CONFIG_FILES", "all")'
18461835
${Else}
1847-
StrCpy $R0 "$R0 --remove-config-files=user"
1836+
StrCpy $UninstOptions "$UninstOptions --remove-config-files=user"
18481837
System::Call 'kernel32::SetEnvironmentVariable(t,t)i("UNINSTALLER_REMOVE_CONFIG_FILES", "user")'
18491838
${EndIf}
18501839
${ElseIf} $UninstRemoveConfigFiles_System_State == ${BST_CHECKED}
1851-
StrCpy $R0 "$R0 --remove-config-files=system"
1840+
StrCpy $UninstOptions "$UninstOptions --remove-config-files=system"
18521841
System::Call 'kernel32::SetEnvironmentVariable(t,t)i("UNINSTALLER_REMOVE_CONFIG_FILES", "system")'
18531842
${EndIf}
18541843

18551844
${If} $UninstRemoveUserData_State == ${BST_CHECKED}
1856-
StrCpy $R0 "$R0 --remove-user-data"
1845+
StrCpy $UninstOptions "$UninstOptions --remove-user-data"
18571846
System::Call 'kernel32::SetEnvironmentVariable(t,t)i("UNINSTALLER_REMOVE_USER_DATA", "1")'
18581847
${EndIf}
18591848

18601849
${If} $UninstRemoveCaches_State == ${BST_CHECKED}
1861-
StrCpy $R0 "$R0 --remove-caches"
1850+
StrCpy $UninstOptions "$UninstOptions --remove-caches"
18621851
System::Call 'kernel32::SetEnvironmentVariable(t,t)i("UNINSTALLER_REMOVE_CACHES", "1")'
18631852
${EndIf}
1853+
{%- endif %}
1854+
1855+
${If} ${FileExists} "$INSTDIR\pre_uninstall.bat"
1856+
${Print} "Running pre-uninstall script..."
1857+
# `type` is used to simulate a `tee`-like output in cmd.exe
1858+
push '"$INSTDIR\pre_uninstall.bat" > "${STEP_LOG}" 2>&1 & SET ERR=!ERRORLEVEL! & type "${STEP_LOG}" & EXIT /B !ERR!'
1859+
push "Failed to run pre-uninstall scripts."
1860+
push 'WithLog'
1861+
call un.AbortRetryNSExecWait
1862+
${EndIf}
1863+
${If} ${FileExists} "$INSTDIR\.nonadmin"
1864+
!insertmacro AddRemovePath "remove" "un."
1865+
${EndIf}
1866+
1867+
{%- if uninstall_with_conda_exe %}
18641868

18651869
${Print} "Removing files and folders..."
1866-
push '"$INSTDIR\_conda.exe" constructor uninstall $R0 --prefix "$INSTDIR" {{ CONDA_LOG_ARG }}'
1870+
push '"$INSTDIR\_conda.exe" constructor uninstall $UninstOptions --prefix "$INSTDIR" {{ CONDA_LOG_ARG }}'
18671871
push 'Failed to remove files and folders. Please see the log for more information.'
18681872
push 'WithLog'
18691873
SetDetailsPrint listonly

news/1205-pre-uninstall-location

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
### Enhancements
2+
3+
* <news item>
4+
5+
### Bug fixes
6+
7+
* Fix regression that placed the pre-uninstall script in the package cache. (#1205)
8+
9+
### Deprecations
10+
11+
* <news item>
12+
13+
### Docs
14+
15+
* <news item>
16+
17+
### Other
18+
19+
* <news item>

tests/test_examples.py

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1352,18 +1352,6 @@ def test_uninstallation_standalone(
13521352
input_path = tmp_path / "input"
13531353
shutil.copytree(str(recipe_path), str(input_path))
13541354

1355-
# Create extra files to delete in pre-uninstall script
1356-
user_files_dir = tmp_path / "user_files"
1357-
for file in ("cache", "data", "config_user", "config_system"):
1358-
(user_files_dir / file).touch()
1359-
1360-
construct_yaml_file = input_path / "construct.yaml"
1361-
with construct_yaml_file.open() as file:
1362-
construct_yaml = yaml.load(file)
1363-
construct_yaml["script_env_variables"] = {"USER_FILES": str(user_files_dir)}
1364-
with construct_yaml_file.open(mode="w") as file:
1365-
yaml.dump(construct_yaml, file)
1366-
13671355
installer, install_dir = next(create_installer(input_path, tmp_path))
13681356
monkeypatch.setenv("USERPROFILE", str(tmp_path))
13691357
_run_installer(
@@ -1404,16 +1392,35 @@ def test_uninstallation_standalone(
14041392
if remove_caches:
14051393
uninstall_options.append("/RemoveCaches=1")
14061394

1395+
# Create extra files to delete in pre-uninstall script
1396+
user_files_dir = tmp_path / "user_files"
1397+
user_files_dir.mkdir()
1398+
user_files: dict[str, bool] = {
1399+
"cache": remove_caches,
1400+
"data": remove_user_data,
1401+
"config_user": remove_user_rcs,
1402+
"config_system": remove_system_rcs,
1403+
}
1404+
for file in user_files:
1405+
(user_files_dir / file).touch()
1406+
assert (user_files_dir / file).exists()
1407+
construct_yaml_file = input_path / "construct.yaml"
1408+
with construct_yaml_file.open() as file:
1409+
construct_yaml = yaml.load(file)
1410+
construct_yaml["script_env_variables"] = {"USER_FILES": str(user_files_dir)}
1411+
with construct_yaml_file.open(mode="w") as file:
1412+
yaml.dump(construct_yaml, file)
1413+
14071414
try:
14081415
_run_uninstaller_exe(install_dir, check=True, options=uninstall_options)
14091416
assert dot_conda_dir.exists() != remove_user_data
14101417
assert pkg_cache.exists() != remove_caches
14111418
assert system_rc.exists() != remove_system_rcs
14121419
assert user_rc.exists() != remove_user_rcs
1413-
assert (user_files_dir / "data").exists() != remove_user_data
1414-
assert (user_files_dir / "cache").exists() != remove_caches
1415-
assert (user_files_dir / "config_system").exists() != remove_system_rcs
1416-
assert (user_files_dir / "config_user").exists() != remove_user_rcs
1420+
# The post-install script only touches the files inside user_files_dir
1421+
assert user_files_dir.exists()
1422+
for file, removed in user_files.items():
1423+
assert (user_files_dir / file).exists() != removed
14171424
finally:
14181425
if system_rc.parent.exists():
14191426
shutil.rmtree(system_rc.parent)

0 commit comments

Comments
 (0)