Skip to content

Commit df00805

Browse files
committed
fix(core): harden try_rmtree with retry and rename for Windows
On Windows, shutil.rmtree fails when files are locked by antivirus or git handles. The current fallback (reserve_script for lazy delete) is useless in cm-cli where there is no restart cycle, causing reinstall to fail with "Already exists". 3-tier deletion strategy: 1. Retry rmtree 3x with 1s delay (handles transient locks) 2. Rename to .trash_* then delete (moves out of scan path) 3. Lazy delete via reserve_script (ComfyUI GUI fallback) After rename, lazy-delete targets the .trash_* path (not original), so the original path is clear for subsequent clone/install.
1 parent 41ab628 commit df00805

2 files changed

Lines changed: 50 additions & 8 deletions

File tree

comfyui_manager/glob/manager_core.py

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1854,11 +1854,32 @@ def reserve_script(repo_path, install_cmds):
18541854

18551855

18561856
def try_rmtree(title, fullpath):
1857+
# Tier 1: retry with delay for transient Windows file locks
1858+
for attempt in range(3):
1859+
try:
1860+
shutil.rmtree(fullpath)
1861+
return
1862+
except OSError:
1863+
if attempt < 2:
1864+
time.sleep(1)
1865+
1866+
# Tier 2: rename out of scan path so clone/install can proceed
1867+
trash = fullpath + f'.trash_{uuid.uuid4().hex[:8]}'
18571868
try:
1858-
shutil.rmtree(fullpath)
1859-
except Exception as e:
1860-
logging.warning(f"[ComfyUI-Manager] An error occurred while deleting '{fullpath}', so it has been scheduled for deletion upon restart.\nEXCEPTION: {e}")
1861-
reserve_script(title, ["#LAZY-DELETE-NODEPACK", fullpath])
1869+
os.rename(fullpath, trash)
1870+
shutil.rmtree(trash, ignore_errors=True)
1871+
if not os.path.exists(trash):
1872+
return
1873+
# Rename succeeded but delete failed — schedule trash path for lazy delete
1874+
logging.warning(f"[ComfyUI-Manager] Renamed '{fullpath}' to '{trash}' but could not delete; scheduled for restart.")
1875+
reserve_script(title, ["#LAZY-DELETE-NODEPACK", trash])
1876+
return
1877+
except OSError:
1878+
pass
1879+
1880+
# Tier 3: lazy delete on restart (ComfyUI GUI fallback)
1881+
logging.warning(f"[ComfyUI-Manager] An error occurred while deleting '{fullpath}', so it has been scheduled for deletion upon restart.")
1882+
reserve_script(title, ["#LAZY-DELETE-NODEPACK", fullpath])
18621883

18631884

18641885
def try_install_script(url, repo_path, install_cmd, instant_execution=False):

comfyui_manager/legacy/manager_core.py

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1833,11 +1833,32 @@ def reserve_script(repo_path, install_cmds):
18331833

18341834

18351835
def try_rmtree(title, fullpath):
1836+
# Tier 1: retry with delay for transient Windows file locks
1837+
for attempt in range(3):
1838+
try:
1839+
shutil.rmtree(fullpath)
1840+
return
1841+
except OSError:
1842+
if attempt < 2:
1843+
time.sleep(1)
1844+
1845+
# Tier 2: rename out of scan path so clone/install can proceed
1846+
trash = fullpath + f'.trash_{uuid.uuid4().hex[:8]}'
18361847
try:
1837-
shutil.rmtree(fullpath)
1838-
except Exception as e:
1839-
logging.warning(f"[ComfyUI-Manager] An error occurred while deleting '{fullpath}', so it has been scheduled for deletion upon restart.\nEXCEPTION: {e}")
1840-
reserve_script(title, ["#LAZY-DELETE-NODEPACK", fullpath])
1848+
os.rename(fullpath, trash)
1849+
shutil.rmtree(trash, ignore_errors=True)
1850+
if not os.path.exists(trash):
1851+
return
1852+
# Rename succeeded but delete failed — schedule trash path for lazy delete
1853+
logging.warning(f"[ComfyUI-Manager] Renamed '{fullpath}' to '{trash}' but could not delete; scheduled for restart.")
1854+
reserve_script(title, ["#LAZY-DELETE-NODEPACK", trash])
1855+
return
1856+
except OSError:
1857+
pass
1858+
1859+
# Tier 3: lazy delete on restart (ComfyUI GUI fallback)
1860+
logging.warning(f"[ComfyUI-Manager] An error occurred while deleting '{fullpath}', so it has been scheduled for deletion upon restart.")
1861+
reserve_script(title, ["#LAZY-DELETE-NODEPACK", fullpath])
18411862

18421863

18431864
def try_install_script(url, repo_path, install_cmd, instant_execution=False):

0 commit comments

Comments
 (0)