diff options
Diffstat (limited to 'ur_upgrade.py')
-rwxr-xr-x | ur_upgrade.py | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/ur_upgrade.py b/ur_upgrade.py new file mode 100755 index 0000000..eada7ea --- /dev/null +++ b/ur_upgrade.py @@ -0,0 +1,171 @@ +#!/usr/bin/env python +from __future__ import division +import os +import shutil +import sys +import stat +import subprocess +import tempfile +import urllib2 +import signal +import tarfile +from collections import namedtuple + +def which(cmd, mode=os.F_OK | os.X_OK, path=None): + """Given a command, mode, and a PATH string, return the path which + conforms to the given mode on the PATH, or None if there is no such + file. + + `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result + of os.environ.get("PATH"), or can be overridden with a custom search + path. + + """ + # Check that a given file can be accessed with the correct mode. + # Additionally check that `file` is not a directory, as on Windows + # directories pass the os.access check. + def _access_check(fn, mode): + return (os.path.exists(fn) and os.access(fn, mode) + and not os.path.isdir(fn)) + + # If we're given a path with a directory part, look it up directly rather + # than referring to PATH directories. This includes checking relative to the + # current directory, e.g. ./script + if os.path.dirname(cmd): + if _access_check(cmd, mode): + return cmd + return None + + if path is None: + path = os.environ.get("PATH", os.defpath) + if not path: + return None + path = path.split(os.pathsep) + + if sys.platform == "win32": + # The current directory takes precedence on Windows. + if not os.curdir in path: + path.insert(0, os.curdir) + + # PATHEXT is necessary to check on Windows. + pathext = os.environ.get("PATHEXT", "").split(os.pathsep) + # See if the given file matches any of the expected path extensions. + # This will allow us to short circuit when given "python.exe". + # If it does match, only test that one, otherwise we have to try + # others. + if any(cmd.lower().endswith(ext.lower()) for ext in pathext): + files = [cmd] + else: + files = [cmd + ext for ext in pathext] + else: + # On other platforms you don't have things like PATHEXT to tell you + # what file suffixes are executable, so just pass on cmd as-is. + files = [cmd] + + seen = set() + for di in path: + normdir = os.path.normcase(di) + if not normdir in seen: + seen.add(normdir) + for thefile in files: + name = os.path.join(di, thefile) + if _access_check(name, mode): + return name + return None + +class Ureka(object): + def __init__(self, basepath): + self.path = basepath + self.path_data = os.path.abspath(os.path.join(self.path, 'misc')) + self._files = ['os', 'bits', 'version', 'name'] + if os.path.exists(self.path_data): + self.info = self._info() + else: + self.info = {} + + + def _info(self): + data = [] + for key in self._files: + path = os.path.join(self.path_data, key) + item = open(path, 'r').readline().strip() + data.append(item) + + + ureka_info = namedtuple('ureka_info', self._files) + return ureka_info._make(data) + + def __getitem__(self, key): + info = self.info._asdict() + if key not in info: + return None + return info[key] + + def __iter__(self): + for item in self.info._asdict().iteritems(): + yield item + +UPGRADE_TEMP = tempfile.mkdtemp(prefix="upgrade") +ORIGINAL = os.path.abspath('/home/jhunk/Ureka') + +def cleanup(): + print('cleaning up') + +if __name__ == "__main__": + + + signal.signal(signal.SIGINT, cleanup) + #signal.signal(signal.SIGKILL, cleanup) + signal.signal(signal.SIGTERM, cleanup) + + if not which('rsync'): + print('rsync not found in PATH. Please install it.') + exit(1) + + u = Ureka(ORIGINAL) + INSTALL_PATH = os.path.join(UPGRADE_TEMP, '1.4.1') + UREKA_TARBALL = "Ureka_{}_{}_{}.tar.gz".format(u['os'], u['bits'], '1.4.1') + ''' http://ssb.stsci.edu/ureka/1.0/Ureka_linux-rhe5_64_1.4.1.tar.gz ''' + + #url = "http://ssb.stsci.edu/ureka/{}/Ureka_{}_{}_{}.tar.gz".format('1.4.1', u['os'], u['bits'], '1.4.1') + url = "http://localhost/ureka/{}/{}".format('1.4.1', UREKA_TARBALL) + + print("Downloading update... {}".format(url)) + req_data = urllib2.urlopen(url) + remote_size = float(req_data.headers['content-length']) + total = 0 + with open(os.path.join(UPGRADE_TEMP, UREKA_TARBALL), 'wb') as installer: + for chunk in iter(lambda: req_data.read(16*1024), ''): + print("\r{:.2f}% [{:.2f}/{:.2f} MB]".format((total / remote_size * 100), (total / 1024 ** 2), (remote_size / 1024 ** 2))), + total += float(len(chunk)) + installer.write(chunk) + print("") + + os.mkdir(INSTALL_PATH) + tarball = tarfile.open(os.path.join(UPGRADE_TEMP, UREKA_TARBALL), 'r') + print("Preparing to unpack...") + files_total = 74690 #len(tarball.getmembers()) + print("Unpacking update...") + for index, member in enumerate(tarball, start=0): + print("\r{:.2f}% [{}/{}]".format((index / files_total * 100), index, files_total)), + tarball.extract(member, path=INSTALL_PATH) + print("") + + open(os.path.join(INSTALL_PATH, 'Ureka', 'misc', 'name'), 'w+').write(u['name'] + os.linesep) + n = Ureka(os.path.join(INSTALL_PATH, 'Ureka')) + + print("Updating distribution from {} to {}...".format(u['version'], n['version'])) + proc = subprocess.Popen('rsync -a -u {} {}'.format(n.path, os.path.dirname(u.path)).split()) + proc.wait() + + # Regenerate Ureka object + u = Ureka(ORIGINAL) + + print("Normalizing...") + proc = subprocess.Popen('{}/bin/ur-setup-real -sh'.format(u.path).split()) + proc = subprocess.Popen('ur_normalize'.split()) + + + + shutil.rmtree(UPGRADE_TEMP) + |