def _extract_update(self): with ChDir(self.update_folder): if not os.path.exists(self.filename): log.debug('File does not exists') raise ClientError('File does not exists', expected=True) verified = self._verify_file_hash() if verified: log.debug('Extracting Update') archive_ext = os.path.splitext(self.filename)[1].lower() if archive_ext == '.gz': try: with tarfile.open(self.filename, 'r:gz') as tfile: # Extract file update to current # directory. tfile.extractall() except Exception as err: # pragma: no cover log.debug(err, exc_info=True) raise ClientError('Error reading gzip file') elif archive_ext == '.zip': try: with zipfile.ZipFile(self.filename, 'r') as zfile: # Extract update file to current # directory. zfile.extractall() except Exception as err: # pragma: no cover log.debug(err, exc_info=True) raise ClientError('Error reading zip file') else: raise ClientError('Unknown filetype') else: raise ClientError('Update archive is corrupt')
def _extract_update(self): with jms_utils.paths.ChDir(self.update_folder): if not os.path.exists(self.filename): log.error('File does not exists') raise ClientError('File does not exists', expected=True) log.info('Extracting Update') archive_ext = os.path.splitext(self.filename)[1].lower() # Handles extracting gzip or zip archives if archive_ext == '.gz': try: with tarfile.open(self.filename, 'r:gz') as tfile: # Extract file update to current # directory. tfile.extractall() except Exception as err: # pragma: no cover log.error(err) log.debug(err, exc_info=True) raise ClientError('Error reading gzip file') elif archive_ext == '.zip': try: with zipfile.ZipFile(self.filename, 'r') as zfile: # Extract update file to current # directory. zfile.extractall() except Exception as err: # pragma: no cover log.error(err) log.debug(err, exc_info=True) raise ClientError('Error reading zip file') else: raise ClientError('Unknown filetype')
def _extract_update(self): with jms_utils.paths.ChDir(self.update_folder): platform_name = self.name # Ensuring we only add .exe when applicable if sys.platform == 'win32' and \ self.name == self.app_name: # pragma: no cover # We only add .exe to app executable. Not libs or dll log.debug('Adding .exe to filename for windows main ' 'app udpate.') platform_name += '.exe' # Ensuring we extract the latest version latest = get_highest_version(self.name, self.platform, self.easy_data) # Get full filename of latest update archive filename = get_filename(self.name, latest, self.platform, self.easy_data) if not os.path.exists(filename): log.error('File does not exists') raise ClientError('File does not exists') log.info('Extracting Update') archive_ext = os.path.splitext(filename)[1].lower() # Handles extracting gzip or zip archives if archive_ext == '.gz': try: with tarfile.open(filename, 'r:gz') as tfile: # Extract file update to current # directory. tfile.extractall() except Exception as err: # pragma: no cover log.error(err) log.debug(str(err), exc_info=True) raise ClientError('Error reading gzip file') elif archive_ext == '.zip': try: with zipfile.ZipFile(filename, 'r') as zfile: # Extract update file to current # directory. zfile.extractall() except Exception as err: # pragma: no cover log.error(str(err)) log.debug(str(err), exc_info=True) raise ClientError('Error reading zip file') else: raise ClientError('Unknown filetype')
def __init__(self, obj, **kwargs): refresh = kwargs.get('refresh') progress_hooks = kwargs.get('progress_hooks') test = kwargs.get('test') data_dir = kwargs.get('data_dir') headers = kwargs.get('headers') if headers is not None: if not isinstance(headers, dict): raise ClientError('headers argument must be a dict', expected=True) # String: Name of binary to update self.name = None # String: Version of the binary to update self.version = None # String: Update manifest as json string - set in _get_update_manifest self.json_data = None # Boolean: Version file verification self.verified = False # Boolean: Json being loaded to dict self.ready = False # LIst: Progress hooks to be called self.progress_hooks = [] if progress_hooks is not None: if not isinstance(progress_hooks, list): raise SyntaxError('progress_hooks must be provided as a list.') self.progress_hooks += progress_hooks # Client config obj with settings to find & verify updates if obj is not None: obj.URLLIB3_HEADERS = headers self.init_app(obj, refresh, test, data_dir)
def _win_rename(self): exe_name = self.name + ".exe" current_app = os.path.join(self._current_app_dir, exe_name) old_exe_name = exe_name + ".old" old_app = os.path.join(self._current_app_dir, old_exe_name) updated_app = os.path.join(self.update_folder, exe_name) # detect if is a folder if os.path.exists(os.path.join(self.update_folder, self.name)): raise ClientError( "The rename strategy is only supported for one file bundled executables" ) # Remove the old app from previous updates if os.path.exists(old_app): os.unlink(old_app) # On Windows, it's possible to rename a currently running exe file os.rename(current_app, old_app) # Any operation from here forward will require rollback on failure try: os.rename(updated_app, current_app) except OSError as e: log.error("Failed to move updated app into position, rolling back") # Rollback strategy: move current app back into position if os.path.exists(current_app): os.unlink(current_app) os.rename(old_app, current_app) raise e try: # Hide the old app win_hide_file(old_app) except WindowsError as e: # Failed to hide file, which is fine - we can still continue log.error("Failed to hide file") return old_app, current_app, updated_app
def _extract_update(self): with ChDir(self.update_folder): if not os.path.exists(self.filename): log.debug("File does not exists") raise ClientError("File does not exists", expected=True) if not os.access(self.filename, os.R_OK): raise ClientError("Permissions Error", expected=True) if self._verify_file_hash(): log.debug("Extracting Update") archive_ext = os.path.splitext(self.filename)[1].lower() if archive_ext in [".gz", ".bz2"]: try: mode = "r:{}".format(archive_ext[1:]) with tarfile.open(self.filename, mode) as tfile: # Extract file update to current # directory. tfile.extractall() except Exception as err: # pragma: no cover log.debug(err, exc_info=True) raise ClientError("Error reading gzip file", expected=True) elif archive_ext == ".zip": try: with zipfile.ZipFile(self.filename, "r") as zfile: # Extract update file to current # directory. zfile.extractall() except Exception as err: # pragma: no cover log.debug(err, exc_info=True) raise ClientError("Error reading zip file", expected=True) else: raise ClientError("Unknown file type") else: raise ClientError("Update archive is corrupt")
def _extract_update(self): with ChDir(self.update_folder): if not os.path.exists(self.filename): log.debug('File does not exists') raise ClientError('File does not exists', expected=True) if not os.access(self.filename, os.R_OK): raise ClientError('Permissions Error', expected=True) if self._verify_file_hash(): log.debug('Extracting Update') archive_ext = os.path.splitext(self.filename)[1].lower() if archive_ext in ['.gz', '.bz2']: try: mode = 'r:{}'.format(archive_ext[1:]) with tarfile.open(self.filename, mode) as tfile: # Extract file update to current # directory. tfile.extractall() except Exception as err: # pragma: no cover log.debug(err, exc_info=True) raise ClientError('Error reading gzip file', expected=True) elif archive_ext == '.zip': try: with zipfile.ZipFile(self.filename, 'r') as zfile: # Extract update file to current # directory. zfile.extractall() except Exception as err: # pragma: no cover log.debug(err, exc_info=True) raise ClientError('Error reading zip file', expected=True) else: raise ClientError('Unknown file type') else: raise ClientError('Update archive is corrupt')
def __init__(self, obj, **kwargs): if obj is None: obj = DefaultClientConfig() refresh = kwargs.get("refresh", False) progress_hooks = kwargs.get("progress_hooks") test = kwargs.get("test", False) data_dir = kwargs.get("data_dir") headers = kwargs.get("headers") # 3rd Party downloader self.downloader = kwargs.get("downloader") if headers is not None: if not isinstance(headers, dict): raise ClientError("headers argument must be a dict", expected=True) # String: Name of binary to update self.name = None # String: Version of the binary to update self.version = None # String: Update manifest as json string - set in _get_update_manifest self.json_data = None # Boolean: Version file verification self.verified = False # Boolean: Json being loaded to dict self.ready = False # LIst: Progress hooks to be called self.progress_hooks = [] if progress_hooks is not None: if not isinstance(progress_hooks, list): raise SyntaxError("progress_hooks must be provided as a list.") self.progress_hooks += progress_hooks obj.URLLIB3_HEADERS = headers # A super dict used to save config info & be dot accessed config = _Config() config.from_object(obj) # Boolean: If executing frozen self.FROZEN = FROZEN # Grabbing config information update_urls = config.get("UPDATE_URLS", []) # List of URL to check for update data self.update_urls = Client._sanitize_update_url(update_urls) # Name of the running application self.app_name = config.get("APP_NAME", "PyUpdater") # Name of the app author self.company_name = config.get("COMPANY_NAME", "Digital Sapphire") # Used in testing to force use of the mac archive if test: # Making platform deterministic for tests. self.data_dir = obj.DATA_DIR self.platform = "mac" else: # pragma: no cover if data_dir is None: # Getting platform specific user data directory self.data_dir = appdirs.user_data_dir(self.app_name, self.company_name) else: self.data_dir = data_dir # Used when parsing the update manifest self.platform = _get_system() if six.PY2: self.data_dir = self.data_dir.decode("utf-8") # Folder to house update archives self.update_folder = os.path.join(self.data_dir, settings.UPDATE_FOLDER) # The root public key to verify the app signing private key self.root_key = config.get("PUBLIC_KEY", "") # We'll get the app_key later in _get_signing_key # That's if we verify the keys manifest self.app_key = None # Used to disable TLS cert verification self.verify = config.get("VERIFY_SERVER_CERT", True) # Max number of download retries self.max_download_retries = config.get("MAX_DOWNLOAD_RETRIES", 3) # HTTP Timeout self.http_timeout = config.get("HTTP_TIMEOUT", 30) # The name of the version file to download self.version_file = settings.VERSION_FILE_FILENAME # The name of the original version of the version file. # Basically the version.gz vs vesion-<platform>.gz self.version_file_compat = settings.VERSION_FILE_FILENAME_COMPAT # The name of the key file to download self.key_file = settings.KEY_FILE_FILENAME # urllib3 headers self.urllib3_headers = obj.URLLIB3_HEADERS # Creating data & update directories self._setup() if refresh is True: self.refresh()