mirror of
https://github.com/jellyfin/jellyfin-desktop.git
synced 2026-10-29 01:56:01 +00:00
279 lines
11 KiB
Python
Executable File
279 lines
11 KiB
Python
Executable File
#!/usr/bin/env python
|
|
# Sample CI usage: scripts\common\fetch-binaries.py -p windows -b release -t abc123 -n 33
|
|
# Sample desktop usage: scripts\common\fetch-binaries.py -i ..\plex-dependency-builder\output\Packages\pms-depends-windows-i386-debug-dev.bz2
|
|
|
|
import hashlib
|
|
import optparse
|
|
import ConfigParser
|
|
import os, re
|
|
import platform
|
|
import subprocess
|
|
import sys
|
|
import shutil
|
|
import urllib2
|
|
import base64
|
|
import glob
|
|
|
|
# Edit these to set a new default dependencies build
|
|
default_tag = "auto"
|
|
default_release_build_number = "109"
|
|
default_release_dir = "plexmediaplayer-dependencies"
|
|
default_branch = "master"
|
|
|
|
def sha1_for_file(path):
|
|
hash=hashlib.sha1()
|
|
fp=file(path, "rb")
|
|
while True:
|
|
data=fp.read(4096)
|
|
if not data:
|
|
break
|
|
hash.update(data)
|
|
return hash.hexdigest()
|
|
|
|
def exec_cmd(args, env={}, supress_output=False):
|
|
""" main exec_cmd function """
|
|
|
|
# forward SSH_AUTH_SOCK, so that ssh-agent works
|
|
if os.name != "nt" and "SSH_AUTH_SOCK" in os.environ:
|
|
env = os.environ
|
|
extra_env={"SSH_AUTH_SOCK":os.environ["SSH_AUTH_SOCK"]}
|
|
env.update(extra_env)
|
|
else:
|
|
env = os.environ
|
|
|
|
cmd = subprocess.Popen(args, stdout = subprocess.PIPE, stderr = subprocess.STDOUT, env = env)
|
|
output = ''
|
|
while True:
|
|
out = cmd.stdout.read(1)
|
|
if out == '' and cmd.poll() != None:
|
|
break
|
|
if out != '':
|
|
if not supress_output:
|
|
sys.stdout.write(out)
|
|
output += out
|
|
if cmd.wait() != 0:
|
|
raise Exception("Command failed: \"%s\"" % " ".join(args), output)
|
|
return output
|
|
|
|
|
|
platform_map={"linux-synology-i386":"synology-i686",
|
|
"linux-readynas-arm":"ubuntu-arm",
|
|
"linux-debian-4-i386":"debian-i686",
|
|
"linux-control4-arm":"control4-arm",
|
|
"linux-apm-ppc":"apm-ppc",
|
|
"linux-armada-arm7":"armada-arm7",
|
|
"linux-synology-arm":"synology-arm"}
|
|
|
|
def platform_str():
|
|
if "BUILD_TAG" in os.environ:
|
|
for (k, v) in platform_map.iteritems():
|
|
if k in os.environ["BUILD_TAG"]:
|
|
return "linux-"+v
|
|
|
|
return "linux-%s-%s"%(platform.linux_distribution()[0].strip().lower(), platform.machine())
|
|
|
|
def merge_directories(src, dest, move = False):
|
|
for src_dir, dirs, files in os.walk(src):
|
|
dst_dir = src_dir.replace(src, dest)
|
|
if not os.path.exists(dst_dir):
|
|
os.mkdir(dst_dir)
|
|
for file_ in files:
|
|
src_file = os.path.join(src_dir, file_)
|
|
dst_file = os.path.join(dst_dir, file_)
|
|
if os.path.exists(dst_file):
|
|
os.remove(dst_file)
|
|
if move:
|
|
shutil.move(src_file, dst_dir)
|
|
else:
|
|
shutil.copy(src_file, dst_dir)
|
|
if move and os.path.exists(src):
|
|
shutil.rmtree(src)
|
|
|
|
def unpack_and_install(download, inputfile, installed_filepath):
|
|
# Make paths absolute before changing directories
|
|
inputfile = os.path.abspath(inputfile)
|
|
if not os.path.exists(inputfile):
|
|
print "Input file %s does not exist" % inputfile
|
|
sys.exit(1)
|
|
shafile = "%s.sha.txt" % inputfile
|
|
|
|
installed_filepath = os.path.abspath(installed_filepath)
|
|
|
|
# Go to directory.
|
|
old_cwd = os.getcwd()
|
|
os.chdir(options.output)
|
|
|
|
# Check the SHA
|
|
if options.nochecksha:
|
|
print "-- Skipping SHA verification"
|
|
elif os.path.exists(shafile):
|
|
f = open(shafile, "r")
|
|
sha = f.readline().strip()
|
|
computed = sha1_for_file(inputfile)
|
|
if not computed == sha:
|
|
print "-- SHA didn't match: %s != %s" % (sha, computed)
|
|
sys.exit(1)
|
|
else:
|
|
print "-- SHA %s matches" % sha
|
|
|
|
f.close()
|
|
else:
|
|
print "-- ERROR - No SHA file is available to verify the file's integrity"
|
|
sys.exit(1)
|
|
|
|
# Untar the package file
|
|
inputfile_tarfriendly = inputfile
|
|
if os.name == "nt":
|
|
pattern = re.compile(r'([a-z]):\\', re.IGNORECASE)
|
|
inputfile_tarfriendly = pattern.sub('/\\1/', inputfile).replace('\\','/')
|
|
|
|
# The final destination directory is the filename without a version number
|
|
# The version number is the last element in the filename (by convention)
|
|
packagename = os.path.splitext(os.path.basename(inputfile))[0]
|
|
packagename_elements = packagename.split("-")
|
|
del packagename_elements[-1]
|
|
packagename_noversion = "-".join(packagename_elements)
|
|
|
|
if os.path.exists(packagename_noversion):
|
|
shutil.rmtree(packagename_noversion, ignore_errors=True)
|
|
|
|
os.makedirs(packagename_noversion)
|
|
|
|
print "-- Unpacking %s... to %s" % (os.path.basename(inputfile), packagename_noversion)
|
|
if os.name == "nt":
|
|
# Touch files from the package, which often arrive from the future when freshly built on our Windows build machine
|
|
exec_cmd(["tar", "xjf", inputfile_tarfriendly, "-C", packagename_noversion, "--touch", "--strip-components", "1", "--no-same-owner"])
|
|
else:
|
|
exec_cmd(["tar", "xjf", inputfile_tarfriendly, "-C", packagename_noversion, "--strip-components", "1", "--no-same-owner"])
|
|
|
|
if download and installed_filepath:
|
|
# Create the installed stamp file to note our success
|
|
open(installed_filepath, "wb")
|
|
|
|
# Restore directory.
|
|
os.chdir(old_cwd)
|
|
|
|
return packagename
|
|
|
|
if __name__=='__main__':
|
|
parser=optparse.OptionParser()
|
|
|
|
parser.add_option("-p", "--platform", action="store", type="string",
|
|
dest="platform", help="Platform identifier (e.g. windows-i386)", default=None)
|
|
|
|
parser.add_option("-b", "--buildconfig", action="store", type="string",
|
|
dest="buildconfig", help="Build configuration (release or debug). Default is release", default="release")
|
|
|
|
parser.add_option("-t", "--tag", action="store", type="string",
|
|
dest="tag", help="Build tag. Default is %s" % default_tag, default=default_tag)
|
|
|
|
parser.add_option("-n", "--buildnumber", action="store", type="string",
|
|
dest="buildnumber", help="Build number. Default is %s for release builds" % (default_release_build_number), default=None)
|
|
|
|
parser.add_option("-d", "--dir", action="store", type="string",
|
|
dest="dir", help="CI build dir. Default is %s for release builds" % (default_release_dir), default=None)
|
|
|
|
parser.add_option("-i", "--inputfile", action="store", type="string",
|
|
dest="inputfile", help="Dependencies package filename, can be supplied instead of platform, buildconfig, tag and buildnumber", default=None)
|
|
|
|
parser.add_option("-o", "--output", action="store", type="string",
|
|
dest="output", help="Output directory. Default is Dependencies",
|
|
default="Dependencies")
|
|
|
|
parser.add_option("-x", "--nochecksha", action="store_true",
|
|
dest="nochecksha", help="Don't check the SHA. Default is false",
|
|
default=False)
|
|
|
|
parser.add_option("-r", "--branch", action="store", type="string",
|
|
dest="branch", help="Git branch", default=None)
|
|
|
|
(options, args)=parser.parse_args(sys.argv)
|
|
|
|
if not os.path.exists(options.output):
|
|
os.makedirs(options.output)
|
|
|
|
# Fail early if platform is not known
|
|
download = not options.inputfile
|
|
if download and not options.platform:
|
|
print "ERROR - A platform must be specified"
|
|
sys.exit(1)
|
|
|
|
installed_filepath = None
|
|
if download:
|
|
|
|
if not options.buildnumber:
|
|
if options.buildconfig == "release":
|
|
options.buildnumber = default_release_build_number
|
|
else:
|
|
options.buildnumber = default_debug_build_number
|
|
|
|
if not options.dir:
|
|
if options.buildconfig == "release":
|
|
options.dir = default_release_dir
|
|
else:
|
|
options.dir = default_debug_dir
|
|
|
|
installed_filepath = os.path.join(options.output, "konvergo-depends-%s-%s-%s.installed" % (options.platform, options.buildconfig, options.buildnumber))
|
|
if os.path.exists(installed_filepath) and options.buildnumber != "latest":
|
|
print "The required deps bundle was already downloaded and installed."
|
|
print "You can delete %s to force a reinstall." % installed_filepath
|
|
sys.exit(0)
|
|
|
|
# Delete previous installed stamps
|
|
cont = ["-c"]
|
|
for path in glob.iglob(os.path.join(options.output, "konvergo-depends-%s-%s-*.installed") % (options.platform, options.buildconfig)):
|
|
match = re.search("-(\d+)\.installed", path, re.DOTALL)
|
|
if match:
|
|
if not match.group(1) == options.buildnumber:
|
|
cont = []
|
|
os.remove(path)
|
|
|
|
if options.tag == "auto":
|
|
req = urllib2.Request("https://nightlies.plex.tv/directdl/plex-dependencies/%s/%s/hash.txt" % (options.dir, options.buildnumber))
|
|
try:
|
|
match = urllib2.urlopen(req).read().rstrip()
|
|
except urllib2.URLError, err:
|
|
print err
|
|
print "ERROR - Download failed"
|
|
sys.exit(1)
|
|
|
|
options.tag = match
|
|
|
|
base_filename = "konvergo-depends-%s-%s-%s" % (options.platform, options.buildconfig, options.tag)
|
|
filename = "%s.tbz2" % base_filename
|
|
|
|
installed_filepath = os.path.join(options.output, "konvergo-depends-%s-%s-%s.installed" % (options.platform, options.buildconfig, options.buildnumber))
|
|
if os.path.exists(installed_filepath):
|
|
print "%s was already downloaded and installed." % filename
|
|
print "You can delete %s to force a reinstall." % installed_filepath
|
|
sys.exit(0)
|
|
|
|
url = "https://nightlies.plex.tv/directdl/plex-dependencies/%s/%s/%s" % (options.dir, options.buildnumber, filename)
|
|
inputfile = os.path.join(options.output, filename)
|
|
|
|
print "-- Downloading %s ..." % url
|
|
exec_cmd(["wget", "--no-check-certificate"] + cont + ["-O", inputfile, url])
|
|
|
|
shaurl = "%s.sha.txt" % url
|
|
shafile = "%s.sha.txt" % inputfile
|
|
|
|
print "-- Downloading %s ..." % shaurl
|
|
exec_cmd(["wget", "--no-check-certificate"] + ["-O", shafile, shaurl])
|
|
|
|
else:
|
|
inputfile = options.inputfile
|
|
|
|
# Unpack and install
|
|
packagename = unpack_and_install(download, inputfile, installed_filepath)
|
|
|
|
# On OS X, we need to postprocess the dependencies.
|
|
if platform.system() == 'Darwin':
|
|
root = os.path.realpath(os.path.join(os.getcwd()))
|
|
script = os.path.join(root, "scripts", "fix-install-names.py")
|
|
for p in ("lib", "bin", "update_installer"):
|
|
path = os.path.join(root, "Dependencies", "konvergo-depends-" + options.platform + "-" + options.buildconfig, p)
|
|
exec_cmd([script, path])
|
|
|
|
# Done!
|
|
print "-- Done with %s" % packagename
|