@ -1,137 +1,57 @@
# coding=utf-8
# coding=utf-8
import os
import os
import platform
import re
import subprocess
import tarfile
import logging
import logging
import requests
import sqlite3
import sqlite3
import json
import json
import requests
import tarfile
from get_args import args
from get_args import args
from config import settings , bazarr_url
from config import settings , bazarr_url
from queueconfig import notifications
from queueconfig import notifications
if not args . no_update :
import git
def check_releases ( ) :
current_working_directory = os . path . dirname ( os . path . dirname ( __file__ ) )
releases = [ ]
url_releases = ' https://api.github.com/repos/morpheus65535/Bazarr/releases '
try :
r = requests . get ( url_releases , timeout = 15 )
r . raise_for_status ( )
except requests . exceptions . HTTPError as errh :
logging . exception ( " Error trying to get releases from Github. Http error. " )
except requests . exceptions . ConnectionError as errc :
logging . exception ( " Error trying to get releases from Github. Connection Error. " )
except requests . exceptions . Timeout as errt :
logging . exception ( " Error trying to get releases from Github. Timeout Error. " )
except requests . exceptions . RequestException as err :
logging . exception ( " Error trying to get releases from Github. " )
else :
for release in r . json ( ) :
releases . append ( [ release [ ' name ' ] , release [ ' body ' ] ] )
with open ( os . path . join ( args . config_dir , ' config ' , ' releases.txt ' ) , ' w ' ) as f :
json . dump ( releases , f )
def run_git ( args ) :
def gitconfig ( ) :
git_locations = [ ' git ' ]
g = git . Repo . init ( current_working_directory )
config_read = g . config_reader ( )
config_write = g . config_writer ( )
if platform . system ( ) . lower ( ) == ' darwin ' :
try :
git_locations . append ( ' /usr/local/git/bin/git ' )
username = config_read . get_value ( " user " , " name " )
except :
logging . debug ( ' BAZARR Settings git username ' )
config_write . set_value ( " user " , " name " , " Bazarr " )
output = err = None
try :
email = config_read . get_value ( " user " , " email " )
except :
logging . debug ( ' BAZARR Settings git email ' )
config_write . set_value ( " user " , " email " , " bazarr@fake.email " )
for cur_git in git_locations :
cmd = cur_git + ' ' + args
try :
def check_and_apply_update ( ) :
logging . debug ( ' BAZARR Trying to execute: " ' + cmd + ' " ' )
p = subprocess . Popen ( cmd , stdout = subprocess . PIPE , stderr = subprocess . STDOUT , shell = True )
output , err = p . communicate ( )
output = output . strip ( )
logging . debug ( ' BAZARR Git output: ' + output )
except OSError :
logging . debug ( ' BAZARR Command failed: %s ' , cmd )
continue
if ' not found ' in output or " not recognized as an internal or external command " in output :
logging . debug ( ' BAZARR Unable to find git with command ' + cmd )
output = None
elif ' fatal: ' in output or err :
logging . error ( ' BAZARR Git returned bad info. Are you sure this is a git installation? ' )
output = None
elif output :
break
return output , err
def check_updates ( ) :
commits_behind = 0
current_version , source = get_version ( )
check_releases ( )
check_releases ( )
if not args . release_update :
if source == ' git ' :
gitconfig ( )
# Get the latest version available from github
branch = settings . general . branch
logging . debug ( ' BAZARR Retrieving latest version information from GitHub ' )
g = git . cmd . Git ( current_working_directory )
url = ' https://api.github.com/repos/morpheus65535/bazarr/commits/ %s ' % settings . general . branch
g . fetch ( ' origin ' )
version = request_json ( url , timeout = 20 , validator = lambda x : type ( x ) == dict )
result = g . diff ( ' --shortstat ' , ' origin/ ' + branch )
if len ( result ) == 0 :
if version is None :
notifications . write ( msg = ' BAZARR No new version of Bazarr available. ' , queue = ' check_update ' )
notifications . write (
logging . info ( ' BAZARR No new version of Bazarr available. ' )
msg = ' BAZARR Could not get the latest version from GitHub. ' ,
else :
queue = ' check_update ' , type = ' warning ' )
g . reset ( ' --hard ' , ' HEAD ' )
logging . warn (
g . checkout ( branch )
' BAZARR Could not get the latest version from GitHub. ' )
g . reset ( ' --hard ' , ' origin/ ' + branch )
return
g . pull ( )
logging . info ( ' BAZARR Updated to latest version. Restart required. ' + result )
latest_version = version [ ' sha ' ]
updated ( )
logging . debug ( " BAZARR Latest version is %s " , latest_version )
# See how many commits behind we are
if not current_version :
notifications . write ( msg = ' BAZARR You are running an unknown version of Bazarr. Run the updater to identify your version ' ,
queue = ' check_update ' , type = ' warning ' )
logging . warn (
' BAZARR You are running an unknown version of Bazarr. Run the updater to identify your version ' )
return
if latest_version == current_version :
notifications . write ( msg = ' BAZARR is up to date ' , queue = ' check_update ' )
logging . info ( ' BAZARR is up to date ' )
return
logging . debug ( ' Comparing currently installed version with latest GitHub version ' )
url = ' https://api.github.com/repos/morpheus65535/bazarr/compare/ %s ... %s ' % ( latest_version ,
current_version )
commits = request_json ( url , timeout = 20 , whitelist_status_code = 404 , validator = lambda x : type ( x ) == dict )
if commits is None :
notifications . write ( msg = ' BAZARR Could not get commits behind from GitHub. ' ,
queue = ' check_update ' , type = ' warning ' )
logging . warn ( ' BAZARR Could not get commits behind from GitHub. ' )
return
try :
commits_behind = int ( commits [ ' behind_by ' ] )
logging . debug ( " BAZARR In total, %d commits behind " , commits_behind )
except KeyError :
notifications . write ( msg = ' BAZARR Cannot compare versions. Are you running a local development version? ' , queue = ' check_update ' )
logging . info ( ' BAZARR Cannot compare versions. Are you running a local development version? ' )
return
if commits_behind > 0 :
logging . info ( ' BAZARR New version is available. You are %s commits behind ' % commits_behind )
notifications . write ( msg = ' BAZARR New version is available. You are %s commits behind ' % commits_behind ,
queue = ' check_update ' )
update ( source , restart = True if settings . general . getboolean ( ' update_restart ' ) else False )
elif commits_behind is 0 :
notifications . write ( msg = ' BAZARR is up to date ' , queue = ' check_update ' )
logging . info ( ' BAZARR is up to date ' )
else :
else :
url = ' https://api.github.com/repos/morpheus65535/bazarr/releases '
url = ' https://api.github.com/repos/morpheus65535/bazarr/releases '
releases = request_json ( url , timeout = 20 , whitelist_status_code = 404 , validator = lambda x : type ( x ) == list )
releases = request_json ( url , timeout = 20 , whitelist_status_code = 404 , validator = lambda x : type ( x ) == list )
@ -145,8 +65,8 @@ def check_updates():
release = releases [ 0 ]
release = releases [ 0 ]
latest_release = release [ ' tag_name ' ]
latest_release = release [ ' tag_name ' ]
if ( ' v ' + current_version ) != latest_release and settings . general . branch == ' master ' :
if ( ' v ' + os. environ [ " BAZARR_VERSION " ] ) != latest_release and settings . general . branch == ' master ' :
update ( source , restart = True if settings . general . getboolean ( ' update_restart ' ) else False )
update _from_source( )
elif settings . general . branch != ' master ' :
elif settings . general . branch != ' master ' :
notifications . write ( msg = " BAZARR Can ' t update development branch from source " , queue = ' check_update ' ) # fixme
notifications . write ( msg = " BAZARR Can ' t update development branch from source " , queue = ' check_update ' ) # fixme
logging . info ( " BAZARR Can ' t update development branch from source " ) # fixme
logging . info ( " BAZARR Can ' t update development branch from source " ) # fixme
@ -155,116 +75,81 @@ def check_updates():
logging . info ( ' BAZARR is up to date ' )
logging . info ( ' BAZARR is up to date ' )
def get_version ( ) :
def update_from_source ( ) :
if os . path . isdir ( os . path . join ( os . path . dirname ( __file__ ) , ' .. ' , ' .git ' ) ) and not args . release_update :
tar_download_url = ' https://github.com/morpheus65535/bazarr/tarball/ {} ' . format ( settings . general . branch )
update_dir = os . path . join ( os . path . dirname ( __file__ ) , ' .. ' , ' update ' )
output , err = run_git ( ' rev-parse HEAD ' )
if not output :
logging . info ( ' BAZARR Downloading update from: ' + tar_download_url )
logging . error ( ' BAZARR Could not find latest installed version. ' )
notifications . write ( msg = ' BAZARR Downloading update from: ' + tar_download_url , queue = ' check_update ' )
cur_commit_hash = None
data = request_content ( tar_download_url )
else :
cur_commit_hash = str ( output )
if not re . match ( ' ^[a-z0-9]+$ ' , cur_commit_hash ) :
if not data :
logging . error ( ' BAZARR Output does not look like a hash, not using it. ' )
logging . error ( " BAZARR Unable to retrieve new version from ' %s ' , can ' t update " , tar_download_url )
cur_commit_hash = None
notifications . write ( msg = ( " BAZARR Unable to retrieve new version from ' %s ' , can ' t update " , tar_download_url ) ,
type = ' error ' , queue = ' check_update ' )
return cur_commit_hash , ' git '
return
else :
download_name = settings . general . branch + ' -github '
return os . environ [ " BAZARR_VERSION " ] , ' source '
tar_download_path = os . path . join ( os . path . dirname ( __file__ ) , ' .. ' , download_name )
# Save tar to disk
with open ( tar_download_path , ' wb ' ) as f :
f . write ( data )
# Extract the tar to update folder
logging . info ( ' BAZARR Extracting file: ' + tar_download_path )
notifications . write ( msg = ' BAZARR Extracting file: ' + tar_download_path , queue = ' check_update ' )
tar = tarfile . open ( tar_download_path )
tar . extractall ( update_dir )
tar . close ( )
# Delete the tar.gz
logging . info ( ' BAZARR Deleting file: ' + tar_download_path )
notifications . write ( msg = ' BAZARR Deleting file: ' + tar_download_path , queue = ' check_update ' )
os . remove ( tar_download_path )
# Find update dir name
update_dir_contents = [ x for x in os . listdir ( update_dir ) if os . path . isdir ( os . path . join ( update_dir , x ) ) ]
if len ( update_dir_contents ) != 1 :
logging . error ( " BAZARR Invalid update data, update failed: " + str ( update_dir_contents ) )
notifications . write ( msg = " BAZARR Invalid update data, update failed: " + str ( update_dir_contents ) ,
type = ' error ' , queue = ' check_update ' )
return
content_dir = os . path . join ( update_dir , update_dir_contents [ 0 ] )
def update ( source , restart = True ) :
# walk temp folder and move files to main folder
if source == ' git ' :
for dirname , dirnames , filenames in os . walk ( content_dir ) :
output , err = run_git ( ' pull ' + ' origin ' + ' ' + settings . general . branch )
dirname = dirname [ len ( content_dir ) + 1 : ]
for curfile in filenames :
old_path = os . path . join ( content_dir , dirname , curfile )
new_path = os . path . join ( os . path . dirname ( __file__ ) , ' .. ' , dirname , curfile )
if not output :
if os . path . isfile ( new_path ) :
notifications . write ( msg = ' Unable to download latest version ' ,
os . remove ( new_path )
queue = ' check_update ' , type = ' error ' )
os . renames ( old_path , new_path )
logging . error ( ' BAZARR Unable to download latest version ' )
updated ( )
return
for line in output . split ( ' \n ' ) :
if ' Already up-to-date. ' in line :
def check_releases ( ) :
logging . info ( ' BAZARR No update available, not updating ' )
releases = [ ]
logging . info ( ' BAZARR Output: ' + str ( output ) )
url_releases = ' https://api.github.com/repos/morpheus65535/Bazarr/releases '
elif line . endswith ( ( ' Aborting ' , ' Aborting. ' ) ) :
try :
logging . error ( ' BAZARR Unable to update from git: ' + line )
r = requests . get ( url_releases , timeout = 15 )
logging . info ( ' BAZARR Output: ' + str ( output ) )
r . raise_for_status ( )
updated ( restart )
except requests . exceptions . HTTPError as errh :
logging . exception ( " Error trying to get releases from Github. Http error. " )
except requests . exceptions . ConnectionError as errc :
logging . exception ( " Error trying to get releases from Github. Connection Error. " )
except requests . exceptions . Timeout as errt :
logging . exception ( " Error trying to get releases from Github. Timeout Error. " )
except requests . exceptions . RequestException as err :
logging . exception ( " Error trying to get releases from Github. " )
else :
else :
tar_download_url = ' https://github.com/morpheus65535/bazarr/tarball/ {} ' . format ( settings . general . branch )
for release in r . json ( ) :
update_dir = os . path . join ( os . path . dirname ( __file__ ) , ' .. ' , ' update ' )
releases . append ( [ release [ ' name ' ] , release [ ' body ' ] ] )
with open ( os . path . join ( args . config_dir , ' config ' , ' releases.txt ' ) , ' w ' ) as f :
logging . info ( ' BAZARR Downloading update from: ' + tar_download_url )
json . dump ( releases , f )
notifications . write ( msg = ' BAZARR Downloading update from: ' + tar_download_url )
data = request_content ( tar_download_url )
if not data :
logging . error ( " BAZARR Unable to retrieve new version from ' %s ' , can ' t update " , tar_download_url )
notifications . write ( msg = ( " BAZARR Unable to retrieve new version from ' %s ' , can ' t update " , tar_download_url ) ,
type = ' error ' )
return
download_name = settings . general . branch + ' -github '
tar_download_path = os . path . join ( os . path . dirname ( __file__ ) , ' .. ' , download_name )
# Save tar to disk
with open ( tar_download_path , ' wb ' ) as f :
f . write ( data )
# Extract the tar to update folder
logging . info ( ' BAZARR Extracting file: ' + tar_download_path )
notifications . write ( msg = ' BAZARR Extracting file: ' + tar_download_path )
tar = tarfile . open ( tar_download_path )
tar . extractall ( update_dir )
tar . close ( )
# Delete the tar.gz
logging . info ( ' BAZARR Deleting file: ' + tar_download_path )
notifications . write ( msg = ' BAZARR Deleting file: ' + tar_download_path )
os . remove ( tar_download_path )
# Find update dir name
update_dir_contents = [ x for x in os . listdir ( update_dir ) if os . path . isdir ( os . path . join ( update_dir , x ) ) ]
if len ( update_dir_contents ) != 1 :
logging . error ( " BAZARR Invalid update data, update failed: " + str ( update_dir_contents ) )
notifications . write ( msg = " BAZARR Invalid update data, update failed: " + str ( update_dir_contents ) ,
type = ' error ' )
return
content_dir = os . path . join ( update_dir , update_dir_contents [ 0 ] )
# walk temp folder and move files to main folder
for dirname , dirnames , filenames in os . walk ( content_dir ) :
dirname = dirname [ len ( content_dir ) + 1 : ]
for curfile in filenames :
old_path = os . path . join ( content_dir , dirname , curfile )
new_path = os . path . join ( os . path . dirname ( __file__ ) , ' .. ' , dirname , curfile )
if os . path . isfile ( new_path ) :
os . remove ( new_path )
os . renames ( old_path , new_path )
updated ( restart )
def checkout_git_branch ( ) :
output , err = run_git ( ' fetch origin ' )
output , err = run_git ( ' checkout %s ' % settings . general . branch )
if not output :
logging . error ( ' Unable to change git branch. ' )
return
for line in output . split ( ' \n ' ) :
if line . endswith ( ( ' Aborting ' , ' Aborting. ' ) ) :
logging . error ( ' Unable to checkout from git: ' + line )
logging . info ( ' Output: ' + str ( output ) )
output , err = run_git ( ' pull %s %s ' % ( ' origin ' , settings . general . branch ) )
class FakeLock ( object ) :
class FakeLock ( object ) :
@ -409,8 +294,8 @@ def request_json(url, **kwargs):
logging . error ( " BAZARR Response returned invalid JSON data " )
logging . error ( " BAZARR Response returned invalid JSON data " )
def updated ( restart = Fals e) :
def updated ( restart = Tru e) :
if restart:
if settings. general . getboolean ( ' update_restart ' ) and restart:
try :
try :
requests . get ( bazarr_url + ' restart ' )
requests . get ( bazarr_url + ' restart ' )
except requests . ConnectionError :
except requests . ConnectionError :