123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278 |
- #!/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
|