mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-13 08:42:59 -07:00
Remove Windows exe auto updater
This commit is contained in:
parent
2cc5bf812f
commit
6e160bb8f8
10 changed files with 14 additions and 280 deletions
5
.github/workflows/publish-installers.yml
vendored
5
.github/workflows/publish-installers.yml
vendored
|
@ -71,11 +71,6 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
pyinstaller -y ./package/Tautulli-${{ matrix.os }}.spec
|
pyinstaller -y ./package/Tautulli-${{ matrix.os }}.spec
|
||||||
|
|
||||||
- name: Move Windows Updater Files
|
|
||||||
if: matrix.os == 'windows'
|
|
||||||
run: |
|
|
||||||
Move-Item dist\updater\* dist\Tautulli\ -Force
|
|
||||||
|
|
||||||
- name: Create Windows Installer
|
- name: Create Windows Installer
|
||||||
uses: joncloud/makensis-action@v3.4
|
uses: joncloud/makensis-action@v3.4
|
||||||
if: matrix.os == 'windows'
|
if: matrix.os == 'windows'
|
||||||
|
|
|
@ -61,7 +61,7 @@
|
||||||
Update your Docker container or <a href="#" id="updateDismiss">Dismiss</a>
|
Update your Docker container or <a href="#" id="updateDismiss">Dismiss</a>
|
||||||
% elif plexpy.INSTALL_TYPE == 'snap':
|
% elif plexpy.INSTALL_TYPE == 'snap':
|
||||||
Update your Snap package or <a href="#" id="updateDismiss">Dismiss</a>
|
Update your Snap package or <a href="#" id="updateDismiss">Dismiss</a>
|
||||||
% elif plexpy.INSTALL_TYPE == 'macos':
|
% elif plexpy.INSTALL_TYPE in ('windows', 'macos'):
|
||||||
<a href="${anon_url('https://github.com/%s/%s/releases/tag/%s' % (plexpy.CONFIG.GIT_USER, plexpy.CONFIG.GIT_REPO, plexpy.LATEST_RELEASE))}" target="_blank" rel="noreferrer">Download</a> and install the latest version or <a href="#" id="updateDismiss">Dismiss</a>
|
<a href="${anon_url('https://github.com/%s/%s/releases/tag/%s' % (plexpy.CONFIG.GIT_USER, plexpy.CONFIG.GIT_REPO, plexpy.LATEST_RELEASE))}" target="_blank" rel="noreferrer">Download</a> and install the latest version or <a href="#" id="updateDismiss">Dismiss</a>
|
||||||
% else:
|
% else:
|
||||||
<a href="update">Update</a> or <a href="#" id="updateDismiss">Dismiss</a>
|
<a href="update">Update</a> or <a href="#" id="updateDismiss">Dismiss</a>
|
||||||
|
@ -350,7 +350,7 @@ ${next.modalIncludes()}
|
||||||
msg += 'Update your Docker container or <a href="#" id="updateDismiss">Dismiss</a>';
|
msg += 'Update your Docker container or <a href="#" id="updateDismiss">Dismiss</a>';
|
||||||
} else if (result.install_type === 'snap') {
|
} else if (result.install_type === 'snap') {
|
||||||
msg += 'Update your Snap package or <a href="#" id="updateDismiss">Dismiss</a>';
|
msg += 'Update your Snap package or <a href="#" id="updateDismiss">Dismiss</a>';
|
||||||
} else if (result.install_type === 'macos') {
|
} else if (result.install_type === 'windows' || result.install_type === 'macos') {
|
||||||
msg += '<a href="' + result.release_url + '" target="_blank" rel="noreferrer">Download</a> and install the latest version or <a href="#" id="updateDismiss">Dismiss</a>'
|
msg += '<a href="' + result.release_url + '" target="_blank" rel="noreferrer">Download</a> and install the latest version or <a href="#" id="updateDismiss">Dismiss</a>'
|
||||||
} else {
|
} else {
|
||||||
msg += '<a href="update">Update</a> or <a href="#" id="updateDismiss">Dismiss</a>';
|
msg += '<a href="update">Update</a> or <a href="#" id="updateDismiss">Dismiss</a>';
|
||||||
|
|
|
@ -220,7 +220,7 @@
|
||||||
<p class="help-block">Check for Tautulli updates periodically.</p>
|
<p class="help-block">Check for Tautulli updates periodically.</p>
|
||||||
</div>
|
</div>
|
||||||
<div id="git_update_options">
|
<div id="git_update_options">
|
||||||
% if not plexpy.SNAP and not (plexpy.FROZEN and common.PLATFORM == 'Darwin'):
|
% if not plexpy.SNAP and not plexpy.FROZEN:
|
||||||
<div class="checkbox">
|
<div class="checkbox">
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" id="plexpy_auto_update" name="plexpy_auto_update" value="1" ${config['plexpy_auto_update']} ${docker_setting}> Update Automatically ${docker_msg | n}
|
<input type="checkbox" id="plexpy_auto_update" name="plexpy_auto_update" value="1" ${config['plexpy_auto_update']} ${docker_setting}> Update Automatically ${docker_msg | n}
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
import sys
|
import sys
|
||||||
sys.modules['FixTk'] = None
|
sys.modules['FixTk'] = None
|
||||||
|
|
||||||
excludes = ['FixTk', 'tcl', 'tk', '_tkinter', 'tkinter', 'Tkinter']
|
|
||||||
block_cipher = None
|
block_cipher = None
|
||||||
|
|
||||||
analysis = Analysis(
|
analysis = Analysis(
|
||||||
|
@ -13,27 +12,13 @@ analysis = Analysis(
|
||||||
('..\\data', 'data'),
|
('..\\data', 'data'),
|
||||||
('..\\CHANGELOG.md', '.'),
|
('..\\CHANGELOG.md', '.'),
|
||||||
('..\\LICENSE', '.'),
|
('..\\LICENSE', '.'),
|
||||||
('..\\branch.txt', '.'),
|
|
||||||
('..\\version.txt', '.'),
|
('..\\version.txt', '.'),
|
||||||
('..\\lib\\ipwhois\\data', 'data'),
|
('..\\lib\\ipwhois\\data', 'data')
|
||||||
('TautulliUpdateTask.xml', '.')
|
|
||||||
],
|
],
|
||||||
excludes=excludes,
|
excludes=['FixTk', 'tcl', 'tk', '_tkinter', 'tkinter', 'Tkinter'],
|
||||||
hiddenimports=['pkg_resources.py2_warn', 'cheroot.ssl', 'cheroot.ssl.builtin'],
|
hiddenimports=['pkg_resources.py2_warn', 'cheroot.ssl', 'cheroot.ssl.builtin'],
|
||||||
cipher=block_cipher
|
cipher=block_cipher
|
||||||
)
|
)
|
||||||
updater_analysis = Analysis(
|
|
||||||
['updater-windows.py'],
|
|
||||||
pathex=['lib'],
|
|
||||||
excludes=excludes,
|
|
||||||
cipher=block_cipher
|
|
||||||
)
|
|
||||||
|
|
||||||
MERGE(
|
|
||||||
(analysis, 'Tautulli', 'Tautulli'),
|
|
||||||
(updater_analysis, 'updater', 'updater')
|
|
||||||
)
|
|
||||||
|
|
||||||
pyz = PYZ(
|
pyz = PYZ(
|
||||||
analysis.pure,
|
analysis.pure,
|
||||||
analysis.zipped_data,
|
analysis.zipped_data,
|
||||||
|
@ -54,24 +39,3 @@ coll = COLLECT(
|
||||||
analysis.datas,
|
analysis.datas,
|
||||||
name='Tautulli'
|
name='Tautulli'
|
||||||
)
|
)
|
||||||
|
|
||||||
updater_pyz = PYZ(
|
|
||||||
updater_analysis.pure,
|
|
||||||
updater_analysis.zipped_data,
|
|
||||||
cipher=block_cipher
|
|
||||||
)
|
|
||||||
updater_exe = EXE(
|
|
||||||
updater_pyz,
|
|
||||||
updater_analysis.scripts,
|
|
||||||
exclude_binaries=True,
|
|
||||||
name='updater',
|
|
||||||
console=False,
|
|
||||||
icon='..\\data\\interfaces\\default\\images\\logo-circle.ico'
|
|
||||||
)
|
|
||||||
coll = COLLECT(
|
|
||||||
updater_exe,
|
|
||||||
updater_analysis.binaries,
|
|
||||||
updater_analysis.zipfiles,
|
|
||||||
updater_analysis.datas,
|
|
||||||
name='updater'
|
|
||||||
)
|
|
||||||
|
|
|
@ -77,13 +77,9 @@ InstallDir "$PROGRAMFILES64\${APP_NAME}"
|
||||||
|
|
||||||
!include Sections.nsh
|
!include Sections.nsh
|
||||||
|
|
||||||
Var /GLOBAL norun
|
|
||||||
Var /GLOBAL nolaunch
|
Var /GLOBAL nolaunch
|
||||||
|
|
||||||
!include "MUI.nsh"
|
!include "MUI.nsh"
|
||||||
!include "FileFunc.nsh"
|
|
||||||
!insertmacro GetParameters
|
|
||||||
!insertmacro GetOptions
|
|
||||||
|
|
||||||
!define MUI_ABORTWARNING
|
!define MUI_ABORTWARNING
|
||||||
!define MUI_UNABORTWARNING
|
!define MUI_UNABORTWARNING
|
||||||
|
@ -129,10 +125,6 @@ SetOverwrite on
|
||||||
SetOutPath "$INSTDIR"
|
SetOutPath "$INSTDIR"
|
||||||
File /nonfatal /a /r "..\dist\${APP_NAME}\"
|
File /nonfatal /a /r "..\dist\${APP_NAME}\"
|
||||||
|
|
||||||
nsExec::Exec "$INSTDIR\updater.exe --xml"
|
|
||||||
nsExec::Exec '$SYSDIR\SCHTASKS /Create /TN TautulliUpdateTask /XML "$INSTDIR\TautulliUpdateTask.xml" /F'
|
|
||||||
|
|
||||||
StrCmp $norun 1 +3 0
|
|
||||||
IfSilent 0 +2
|
IfSilent 0 +2
|
||||||
ExecShell "" "$INSTDIR\${MAIN_APP_EXE}" $nolaunch
|
ExecShell "" "$INSTDIR\${MAIN_APP_EXE}" $nolaunch
|
||||||
SectionEnd
|
SectionEnd
|
||||||
|
@ -218,20 +210,11 @@ RmDir "$SMPROGRAMS\${APP_NAME}"
|
||||||
|
|
||||||
DeleteRegKey ${REG_ROOT} "${REG_APP_PATH}"
|
DeleteRegKey ${REG_ROOT} "${REG_APP_PATH}"
|
||||||
DeleteRegKey ${REG_ROOT} "${UNINSTALL_PATH}"
|
DeleteRegKey ${REG_ROOT} "${UNINSTALL_PATH}"
|
||||||
|
|
||||||
nsExec::Exec "$SYSDIR\SCHTASKS /Delete /TN TautulliUpdateTask /F"
|
|
||||||
|
|
||||||
SectionEnd
|
SectionEnd
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
Function .onInit
|
Function .onInit
|
||||||
StrCpy $norun 0
|
|
||||||
${GetParameters} $CMDLINE
|
|
||||||
${GetOptions} "$CMDLINE" "/NORUN" $R0
|
|
||||||
IfErrors +2 0
|
|
||||||
StrCpy $norun 1
|
|
||||||
|
|
||||||
IfSilent 0 +2
|
IfSilent 0 +2
|
||||||
StrCpy $nolaunch "--nolaunch"
|
StrCpy $nolaunch "--nolaunch"
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -1,5 +1,4 @@
|
||||||
apscheduler==3.6.3
|
apscheduler==3.6.3
|
||||||
psutil==5.8.0
|
|
||||||
pyinstaller==4.2
|
pyinstaller==4.2
|
||||||
pyopenssl==20.0.1
|
pyopenssl==20.0.1
|
||||||
pycryptodomex==3.9.9
|
pycryptodomex==3.9.9
|
||||||
|
|
|
@ -1,194 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# This file is part of Tautulli.
|
|
||||||
#
|
|
||||||
# Tautulli is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# Tautulli is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with Tautulli. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
from logging import handlers
|
|
||||||
import argparse
|
|
||||||
import logging
|
|
||||||
import os
|
|
||||||
import psutil
|
|
||||||
import re
|
|
||||||
import requests
|
|
||||||
import shutil
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
import tempfile
|
|
||||||
import xml.etree.ElementTree as ET
|
|
||||||
|
|
||||||
|
|
||||||
SCRIPT_PATH = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
CREATE_NO_WINDOW = 0x08000000
|
|
||||||
REPO_URL = 'https://api.github.com/repos/Tautulli/Tautulli'
|
|
||||||
|
|
||||||
LOGFILE = 'updater.log'
|
|
||||||
LOGPATH = os.path.join(SCRIPT_PATH, LOGFILE)
|
|
||||||
MAX_SIZE = 1000000 # 1MB
|
|
||||||
MAX_FILES = 1
|
|
||||||
|
|
||||||
|
|
||||||
def init_logger():
|
|
||||||
log = logging.getLogger('updater')
|
|
||||||
log.setLevel(logging.DEBUG)
|
|
||||||
file_formatter = logging.Formatter(
|
|
||||||
'%(asctime)s - %(levelname)-7s :: %(threadName)s : Tautulli Updater :: %(message)s',
|
|
||||||
'%Y-%m-%d %H:%M:%S')
|
|
||||||
file_handler = handlers.RotatingFileHandler(
|
|
||||||
LOGPATH, maxBytes=MAX_SIZE, backupCount=MAX_FILES, encoding='utf-8')
|
|
||||||
file_handler.setFormatter(file_formatter)
|
|
||||||
log.addHandler(file_handler)
|
|
||||||
return log
|
|
||||||
|
|
||||||
|
|
||||||
def read_file(file_path):
|
|
||||||
try:
|
|
||||||
with open(file_path, 'r') as f:
|
|
||||||
return f.read().strip(' \n\r')
|
|
||||||
except Exception as e:
|
|
||||||
logger.error('Read file error: %s', e)
|
|
||||||
raise Exception(1)
|
|
||||||
|
|
||||||
|
|
||||||
def request_json(url):
|
|
||||||
try:
|
|
||||||
response = requests.get(url)
|
|
||||||
response.raise_for_status()
|
|
||||||
return response.json()
|
|
||||||
except Exception as e:
|
|
||||||
logger.error('Request error: %s', e)
|
|
||||||
raise Exception(2)
|
|
||||||
|
|
||||||
|
|
||||||
def kill_and_get_processes(process_name):
|
|
||||||
processes = []
|
|
||||||
for process in psutil.process_iter():
|
|
||||||
if process.name() == process_name:
|
|
||||||
processes.append(process.cmdline())
|
|
||||||
logger.info('Sending SIGTERM to %s (PID=%d)', process.name(), process.pid)
|
|
||||||
process.terminate()
|
|
||||||
return processes
|
|
||||||
|
|
||||||
|
|
||||||
def update_tautulli():
|
|
||||||
logger.info('Starting Tautulli update check')
|
|
||||||
|
|
||||||
branch = read_file(os.path.join(SCRIPT_PATH, 'branch.txt'))
|
|
||||||
logger.info('Branch: %s', branch)
|
|
||||||
|
|
||||||
current_version = read_file(os.path.join(SCRIPT_PATH, 'version.txt'))
|
|
||||||
logger.info('Current version: %s', current_version)
|
|
||||||
|
|
||||||
logger.info('Retrieving latest version from GitHub')
|
|
||||||
commits = request_json('{}/commits/{}'.format(REPO_URL, branch))
|
|
||||||
latest_version = commits['sha']
|
|
||||||
logger.info('Latest version: %s', latest_version)
|
|
||||||
|
|
||||||
if current_version == latest_version:
|
|
||||||
logger.info('Tautulli is already up to date')
|
|
||||||
return 0
|
|
||||||
|
|
||||||
logger.info('Comparing version on GitHub')
|
|
||||||
compare = request_json('{}/compare/{}...{}'.format(REPO_URL, latest_version, current_version))
|
|
||||||
commits_behind = compare['behind_by']
|
|
||||||
logger.info('Commits behind: %s', commits_behind)
|
|
||||||
|
|
||||||
if commits_behind <= 0:
|
|
||||||
logger.info('Tautulli is already up to date')
|
|
||||||
return 0
|
|
||||||
|
|
||||||
logger.info('Retrieving releases on GitHub')
|
|
||||||
releases = request_json('{}/releases'.format(REPO_URL))
|
|
||||||
|
|
||||||
if branch == 'master':
|
|
||||||
release = next((r for r in releases if not r['prerelease']), releases[0])
|
|
||||||
else:
|
|
||||||
release = next((r for r in releases), releases[0])
|
|
||||||
|
|
||||||
version = release['tag_name']
|
|
||||||
logger.info('Release: %s', version)
|
|
||||||
|
|
||||||
win_exe = 'application/vnd.microsoft.portable-executable'
|
|
||||||
asset = next((a for a in release['assets'] if a['content_type'] == win_exe), None)
|
|
||||||
download_url = asset['browser_download_url']
|
|
||||||
download_file = asset['name']
|
|
||||||
|
|
||||||
file_path = os.path.join(tempfile.gettempdir(), download_file)
|
|
||||||
logger.info('Downloading installer to temporary directory: %s', file_path)
|
|
||||||
try:
|
|
||||||
with requests.get(download_url, stream=True) as r:
|
|
||||||
with open(file_path, 'wb') as f:
|
|
||||||
shutil.copyfileobj(r.raw, f)
|
|
||||||
except Exception as e:
|
|
||||||
logger.error('Failed to download %s: %s', download_file, e)
|
|
||||||
return 2
|
|
||||||
|
|
||||||
logger.info('Stopping Tautulli processes')
|
|
||||||
try:
|
|
||||||
processes = kill_and_get_processes('Tautulli.exe')
|
|
||||||
except Exception as e:
|
|
||||||
logger.error('Failed to stop Tautulli: %s', e)
|
|
||||||
return 1
|
|
||||||
|
|
||||||
logger.info('Running %s', download_file)
|
|
||||||
try:
|
|
||||||
subprocess.call([file_path, '/S', '/NORUN', '/D=' + SCRIPT_PATH], creationflags=CREATE_NO_WINDOW)
|
|
||||||
status = 0
|
|
||||||
except Exception as e:
|
|
||||||
logger.exception('Failed to install Tautulli: %s', e)
|
|
||||||
status = -1
|
|
||||||
|
|
||||||
if status == 0:
|
|
||||||
logger.info('Tautulli updated to %s', version)
|
|
||||||
|
|
||||||
logger.info('Restarting Tautulli processes')
|
|
||||||
for process in processes:
|
|
||||||
logger.info('Starting process: %s', process)
|
|
||||||
subprocess.Popen(process, creationflags=CREATE_NO_WINDOW)
|
|
||||||
|
|
||||||
return status
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument('--xml', action='store_true')
|
|
||||||
opts = parser.parse_args()
|
|
||||||
|
|
||||||
if opts.xml:
|
|
||||||
xml_path = os.path.join(SCRIPT_PATH, 'TautulliUpdateTask.xml')
|
|
||||||
tree = ET.parse(xml_path)
|
|
||||||
task = tree.getroot()
|
|
||||||
|
|
||||||
match = re.match(r'{(.*)}', task.tag)
|
|
||||||
namespace = match.group(1)
|
|
||||||
namespaces = {'': namespace}
|
|
||||||
ET.register_namespace('', namespace)
|
|
||||||
|
|
||||||
for elem in task.iterfind('./Actions/Exec/Command', namespaces=namespaces):
|
|
||||||
elem.text = os.path.join(SCRIPT_PATH, 'updater.exe')
|
|
||||||
for elem in task.iterfind('./Actions/Exec/WorkingDirectory', namespaces=namespaces):
|
|
||||||
elem.text = SCRIPT_PATH
|
|
||||||
|
|
||||||
tree.write(xml_path, encoding='UTF-16')
|
|
||||||
|
|
||||||
else:
|
|
||||||
logger = init_logger()
|
|
||||||
|
|
||||||
try:
|
|
||||||
status_code = update_tautulli()
|
|
||||||
except Exception as exc:
|
|
||||||
status_code = exc
|
|
||||||
logger.debug('Update function returned status code %s', status_code)
|
|
||||||
|
|
||||||
sys.exit(status_code)
|
|
|
@ -2295,12 +2295,7 @@ def upgrade():
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
def shutdown(restart=False, update=False, checkout=False, reset=False,
|
def shutdown(restart=False, update=False, checkout=False, reset=False):
|
||||||
_shutdown=True):
|
|
||||||
if FROZEN and common.PLATFORM == 'Windows' and update:
|
|
||||||
restart = False
|
|
||||||
_shutdown = False
|
|
||||||
|
|
||||||
webstart.stop()
|
webstart.stop()
|
||||||
|
|
||||||
# Shutdown the websocket connection
|
# Shutdown the websocket connection
|
||||||
|
@ -2373,7 +2368,6 @@ def shutdown(restart=False, update=False, checkout=False, reset=False,
|
||||||
else:
|
else:
|
||||||
logger.info("Tautulli is shutting down...")
|
logger.info("Tautulli is shutting down...")
|
||||||
|
|
||||||
if _shutdown:
|
|
||||||
logger.shutdown()
|
logger.shutdown()
|
||||||
|
|
||||||
if WIN_SYS_TRAY_ICON:
|
if WIN_SYS_TRAY_ICON:
|
||||||
|
|
|
@ -278,8 +278,7 @@ def check_github(scheduler=False, notify=False, use_cache=False):
|
||||||
logger.warn('Tautulli is running using Python 2. Unable to run automatic update.')
|
logger.warn('Tautulli is running using Python 2. Unable to run automatic update.')
|
||||||
|
|
||||||
elif scheduler and plexpy.CONFIG.PLEXPY_AUTO_UPDATE and \
|
elif scheduler and plexpy.CONFIG.PLEXPY_AUTO_UPDATE and \
|
||||||
not plexpy.DOCKER and not plexpy.SNAP and \
|
not plexpy.DOCKER and not plexpy.SNAP and not plexpy.FROZEN:
|
||||||
not (plexpy.FROZEN and common.PLATFORM == 'Darwin'):
|
|
||||||
logger.info('Running automatic update.')
|
logger.info('Running automatic update.')
|
||||||
plexpy.shutdown(restart=True, update=True)
|
plexpy.shutdown(restart=True, update=True)
|
||||||
|
|
||||||
|
@ -297,15 +296,9 @@ def update():
|
||||||
if not plexpy.UPDATE_AVAILABLE:
|
if not plexpy.UPDATE_AVAILABLE:
|
||||||
return
|
return
|
||||||
|
|
||||||
if plexpy.INSTALL_TYPE in ('docker', 'snap', 'macos'):
|
if plexpy.INSTALL_TYPE in ('docker', 'snap', 'windows', 'macos'):
|
||||||
return
|
return
|
||||||
|
|
||||||
elif plexpy.INSTALL_TYPE == 'windows':
|
|
||||||
logger.info('Calling Windows scheduled task to update Tautulli')
|
|
||||||
CREATE_NO_WINDOW = 0x08000000
|
|
||||||
subprocess.Popen(['SCHTASKS', '/Run', '/TN', 'TautulliUpdateTask'],
|
|
||||||
creationflags=CREATE_NO_WINDOW)
|
|
||||||
|
|
||||||
elif plexpy.INSTALL_TYPE == 'git':
|
elif plexpy.INSTALL_TYPE == 'git':
|
||||||
output, err = runGit('pull --ff-only {} {}'.format(plexpy.CONFIG.GIT_REMOTE,
|
output, err = runGit('pull --ff-only {} {}'.format(plexpy.CONFIG.GIT_REMOTE,
|
||||||
plexpy.CONFIG.GIT_BRANCH))
|
plexpy.CONFIG.GIT_BRANCH))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue