2022-10-31 14:36:45 +00:00
import os
import sys
2023-05-15 17:57:11 +00:00
import threading
2022-10-31 14:36:45 +00:00
import traceback
import git
2023-03-27 07:02:30 +00:00
from modules import shared
2023-05-10 06:02:23 +00:00
from modules . paths_internal import extensions_dir , extensions_builtin_dir , script_path # noqa: F401
2022-10-31 14:36:45 +00:00
extensions = [ ]
2023-03-27 07:02:30 +00:00
if not os . path . exists ( extensions_dir ) :
os . makedirs ( extensions_dir )
2022-10-31 14:36:45 +00:00
def active ( ) :
2023-03-27 16:44:49 +00:00
if shared . opts . disable_all_extensions == " all " :
return [ ]
elif shared . opts . disable_all_extensions == " extra " :
return [ x for x in extensions if x . enabled and x . is_builtin ]
else :
return [ x for x in extensions if x . enabled ]
2022-10-31 14:36:45 +00:00
class Extension :
2023-05-15 17:57:11 +00:00
lock = threading . Lock ( )
2022-12-03 15:06:33 +00:00
def __init__ ( self , name , path , enabled = True , is_builtin = False ) :
2022-10-31 14:36:45 +00:00
self . name = name
self . path = path
self . enabled = enabled
self . status = ' '
self . can_update = False
2022-12-03 15:06:33 +00:00
self . is_builtin = is_builtin
2023-03-29 21:46:03 +00:00
self . commit_hash = ' '
self . commit_date = None
2023-02-13 16:04:34 +00:00
self . version = ' '
2023-03-29 21:46:03 +00:00
self . branch = None
2023-03-27 07:02:30 +00:00
self . remote = None
self . have_info_from_repo = False
def read_info_from_repo ( self ) :
2023-03-29 21:46:03 +00:00
if self . is_builtin or self . have_info_from_repo :
2023-03-27 07:02:30 +00:00
return
2023-05-15 17:57:11 +00:00
with self . lock :
if self . have_info_from_repo :
return
self . do_read_info_from_repo ( )
2022-10-31 14:36:45 +00:00
2023-05-15 17:57:11 +00:00
def do_read_info_from_repo ( self ) :
2022-10-31 14:36:45 +00:00
repo = None
try :
2023-03-27 07:02:30 +00:00
if os . path . exists ( os . path . join ( self . path , " .git " ) ) :
repo = git . Repo ( self . path )
2022-10-31 14:36:45 +00:00
except Exception :
2023-03-27 07:02:30 +00:00
print ( f " Error reading github repository info from { self . path } : " , file = sys . stderr )
2022-10-31 14:36:45 +00:00
print ( traceback . format_exc ( ) , file = sys . stderr )
if repo is None or repo . bare :
self . remote = None
else :
2022-11-05 12:04:48 +00:00
try :
self . status = ' unknown '
2023-03-27 07:02:30 +00:00
self . remote = next ( repo . remote ( ) . urls , None )
2023-03-29 21:46:03 +00:00
self . commit_date = repo . head . commit . committed_date
if repo . active_branch :
self . branch = repo . active_branch . name
2023-05-15 18:22:35 +00:00
self . commit_hash = repo . head . commit . hexsha
self . version = repo . git . describe ( " --always " , " --tags " ) # compared to `self.commit_hash[:8]` this takes about 30% more time total but since we run it in parallel we don't care
2023-03-29 21:46:03 +00:00
except Exception as ex :
print ( f " Failed reading extension data from Git repository ( { self . name } ): { ex } " , file = sys . stderr )
2022-11-05 12:04:48 +00:00
self . remote = None
2022-10-31 14:36:45 +00:00
2023-05-15 17:57:11 +00:00
self . have_info_from_repo = True
2022-10-31 14:36:45 +00:00
def list_files ( self , subdir , extension ) :
from modules import scripts
dirpath = os . path . join ( self . path , subdir )
if not os . path . isdir ( dirpath ) :
return [ ]
res = [ ]
for filename in sorted ( os . listdir ( dirpath ) ) :
2022-10-31 15:40:47 +00:00
res . append ( scripts . ScriptFile ( self . path , filename , os . path . join ( dirpath , filename ) ) )
2022-10-31 14:36:45 +00:00
res = [ x for x in res if os . path . splitext ( x . path ) [ 1 ] . lower ( ) == extension and os . path . isfile ( x . path ) ]
return res
def check_updates ( self ) :
repo = git . Repo ( self . path )
2023-02-25 19:15:06 +00:00
for fetch in repo . remote ( ) . fetch ( dry_run = True ) :
2022-10-31 14:36:45 +00:00
if fetch . flags != fetch . HEAD_UPTODATE :
self . can_update = True
2023-03-29 23:32:29 +00:00
self . status = " new commits "
2022-10-31 14:36:45 +00:00
return
2023-03-29 23:32:29 +00:00
try :
origin = repo . rev_parse ( ' origin ' )
if repo . head . commit != origin :
self . can_update = True
self . status = " behind HEAD "
return
except Exception :
self . can_update = False
self . status = " unknown (remote error) "
return
2022-10-31 14:36:45 +00:00
self . can_update = False
self . status = " latest "
2023-03-29 21:46:03 +00:00
def fetch_and_reset_hard ( self , commit = ' origin ' ) :
2022-10-31 14:36:45 +00:00
repo = git . Repo ( self . path )
2022-11-12 18:44:42 +00:00
# Fix: `error: Your local changes to the following files would be overwritten by merge`,
# because WSL2 Docker set 755 file permissions instead of 644, this results to the error.
2023-02-25 19:15:06 +00:00
repo . git . fetch ( all = True )
2023-03-29 21:46:03 +00:00
repo . git . reset ( commit , hard = True )
2023-03-29 23:32:29 +00:00
self . have_info_from_repo = False
2022-10-31 14:36:45 +00:00
def list_extensions ( ) :
extensions . clear ( )
2023-03-27 07:02:30 +00:00
if not os . path . isdir ( extensions_dir ) :
2022-10-31 14:36:45 +00:00
return
2023-03-27 16:44:49 +00:00
if shared . opts . disable_all_extensions == " all " :
2023-03-27 16:04:45 +00:00
print ( " *** \" Disable all extensions \" option was set, will not load any extensions *** " )
2023-03-27 16:44:49 +00:00
elif shared . opts . disable_all_extensions == " extra " :
print ( " *** \" Disable all extensions \" option was set, will only load built-in extensions *** " )
2023-03-27 16:04:45 +00:00
2023-03-25 13:05:12 +00:00
extension_paths = [ ]
2023-03-27 07:02:30 +00:00
for dirname in [ extensions_dir , extensions_builtin_dir ] :
2022-12-03 15:06:33 +00:00
if not os . path . isdir ( dirname ) :
return
2022-10-31 14:36:45 +00:00
2022-12-03 15:06:33 +00:00
for extension_dirname in sorted ( os . listdir ( dirname ) ) :
path = os . path . join ( dirname , extension_dirname )
if not os . path . isdir ( path ) :
continue
2023-03-27 07:02:30 +00:00
extension_paths . append ( ( extension_dirname , path , dirname == extensions_builtin_dir ) )
2022-12-03 15:06:33 +00:00
2023-03-25 13:05:12 +00:00
for dirname , path , is_builtin in extension_paths :
2022-12-03 15:06:33 +00:00
extension = Extension ( name = dirname , path = path , enabled = dirname not in shared . opts . disabled_extensions , is_builtin = is_builtin )
2022-10-31 14:36:45 +00:00
extensions . append ( extension )