33from .installs import get_matching_install_tags
44from .install_command import SHORTCUT_HANDLERS , update_all_shortcuts
55from .logging import LOGGER
6- from .pathutils import PurePath
6+ from .pathutils import Path , PurePath
77from .tagutils import tag_or_range
88
99
1010def _iterdir (p , only_files = False ):
1111 try :
1212 if only_files :
13- return [f for f in p .iterdir () if p .is_file ()]
14- return list (p .iterdir ())
13+ return [f for f in Path ( p ) .iterdir () if f .is_file ()]
14+ return list (Path ( p ) .iterdir ())
1515 except FileNotFoundError :
1616 LOGGER .debug ("Skipping %s because it does not exist" , p )
1717 return []
1818
1919
20+ def _do_purge_global_dir (global_dir , warn_msg , * , hive = None , subkey = "Environment" ):
21+ import os
22+ import winreg
23+
24+ if hive is None :
25+ hive = winreg .HKEY_CURRENT_USER
26+ try :
27+ with winreg .OpenKeyEx (hive , subkey ) as key :
28+ path , kind = winreg .QueryValueEx (key , "Path" )
29+ if kind not in (winreg .REG_SZ , winreg .REG_EXPAND_SZ ):
30+ raise ValueError ("Value kind is not a string" )
31+ except (OSError , ValueError ):
32+ LOGGER .debug ("Not removing global commands directory from PATH" , exc_info = True )
33+ else :
34+ LOGGER .debug ("Current PATH contains %s" , path )
35+ paths = path .split (";" )
36+ newpaths = []
37+ for p in paths :
38+ ep = os .path .expandvars (p ) if kind == winreg .REG_EXPAND_SZ else p
39+ if PurePath (ep ).match (global_dir ):
40+ LOGGER .debug ("Removing from PATH: %s" , p )
41+ else :
42+ newpaths .append (p )
43+ if len (newpaths ) < len (paths ):
44+ newpath = ";" .join (newpaths )
45+ with winreg .CreateKeyEx (hive , subkey , access = winreg .KEY_READ | winreg .KEY_WRITE ) as key :
46+ path2 , kind2 = winreg .QueryValueEx (key , "Path" )
47+ if path2 == path and kind2 == kind :
48+ LOGGER .info ("Removing global commands directory from PATH" )
49+ LOGGER .debug ("New PATH contains %s" , newpath )
50+ winreg .SetValueEx (key , "Path" , 0 , kind , newpath )
51+ else :
52+ LOGGER .debug ("Not removing global commands directory from PATH "
53+ "because the registry changed while processing." )
54+
55+ try :
56+ from _native import broadcast_settings_change
57+ broadcast_settings_change ()
58+ except (ImportError , OSError ):
59+ LOGGER .debug ("Did not broadcast settings change notification" ,
60+ exc_info = True )
61+
62+ if not global_dir .is_dir ():
63+ return
64+ LOGGER .info ("Purging global commands from %s" , global_dir )
65+ for f in _iterdir (global_dir ):
66+ LOGGER .debug ("Purging %s" , f )
67+ rmtree (f , after_5s_warning = warn_msg )
68+
69+
2070def execute (cmd ):
2171 LOGGER .debug ("BEGIN uninstall_command.execute: %r" , cmd .args )
2272
@@ -31,28 +81,28 @@ def execute(cmd):
3181 cmd .tags = []
3282
3383 if cmd .purge :
34- if cmd .ask_yn ("Uninstall all runtimes?" ):
35- for i in installed :
36- LOGGER . info ( "Purging %s from %s" , i [ "display-name" ], i [ "prefix" ])
37- try :
38- rmtree (
39- i [ "prefix" ],
40- after_5s_warning = warn_msg . format ( i [ "display-name" ]),
41- remove_ext_first = ( "exe" , "dll" , "json" )
42- )
43- except FilesInUseError :
44- LOGGER . warn ( "Unable to purge %s because it is still in use." ,
45- i [ "display-name" ])
46- continue
47- LOGGER . info ( "Purging saved downloads from %s" , cmd . download_dir )
48- rmtree ( cmd . download_dir , after_5s_warning = warn_msg . format ( "cached downloads" ))
49- LOGGER .info ("Purging global commands from %s" , cmd .global_dir )
50- for f in _iterdir (cmd .global_dir ):
51- LOGGER . debug ( "Purging %s" , f )
52- rmtree ( f , after_5s_warning = warn_msg .format ("global commands" ))
53- LOGGER .info ("Purging all shortcuts" )
54- for _ , cleanup in SHORTCUT_HANDLERS .values ():
55- cleanup (cmd , [])
84+ if not cmd .ask_yn ("Uninstall all runtimes?" ):
85+ LOGGER . debug ( "END uninstall_command.execute" )
86+ return
87+ for i in installed :
88+ LOGGER . info ( "Purging %s from %s" , i [ "display-name" ], i [ "prefix" ])
89+ try :
90+ rmtree (
91+ i [ "prefix" ],
92+ after_5s_warning = warn_msg . format ( i [ "display-name" ]),
93+ remove_ext_first = ( "exe" , "dll" , "json" )
94+ )
95+ except FilesInUseError :
96+ LOGGER . warn ( "Unable to purge %s because it is still in use." ,
97+ i [ "display-name" ] )
98+ continue
99+ LOGGER .info ("Purging saved downloads from %s" , cmd .download_dir )
100+ rmtree (cmd .download_dir , after_5s_warning = warn_msg . format ( "cached downloads" ))
101+ # Purge global commands directory
102+ _do_purge_global_dir ( cmd . global_dir , warn_msg .format ("global commands" ))
103+ LOGGER .info ("Purging all shortcuts" )
104+ for _ , cleanup in SHORTCUT_HANDLERS .values ():
105+ cleanup (cmd , [])
56106 LOGGER .debug ("END uninstall_command.execute" )
57107 return
58108
0 commit comments