def load_from_archive(repository_archive, namespace=None, installed=True): repo_tarfile = repository_archive.tar_file archive_path = repository_archive.info.archive_path manifest_filename = os.path.join( collection_artifact_manifest.COLLECTION_MANIFEST_FILENAME) manifest_data = None log.debug('Trying to extract %s from %s', manifest_filename, archive_path) try: mfd = repo_tarfile.extractfile(manifest_filename) if mfd: manifest_data = collection_artifact_manifest.load(mfd) log.debug('md: %s', manifest_data) log.debug('md.collection_info: %s', manifest_data.collection_info) log.debug('manifest_data.collection_info.name: %s', manifest_data.collection_info.name) except KeyError as e: log.warning('No %s found in archive: %s (Error: %s)', manifest_filename, archive_path, e) if not manifest_data: raise exceptions.GalaxyArchiveError( 'No collection manifest (%s) found in %s' % (collection_artifact_manifest.COLLECTION_MANIFEST_FILENAME, archive_path), archive_path=archive_path) col_info = manifest_data.collection_info log.debug('col_info: %s', col_info) # if we specify a namespace, use it otherwise use the info from the manifest col_info repo_spec = RepositorySpec( namespace=namespace or col_info.namespace, name=col_info.name, version=col_info.version, spec_string=archive_path, # fetch_method=None, src=archive_path) log.debug('repo spec from %s: %r', archive_path, repo_spec) requirements_list = requirements.from_dependencies_dict( col_info.dependencies, repository_spec=repo_spec) repository = Repository( repository_spec=repo_spec, path=None, installed=installed, requirements=requirements_list, ) log.debug('repository: %s', repository) return repository
def extract_file(tar_file, file_to_extract): # TODO: should just be a object? ContentArchiveMember? ContentArchiveExtractData ? archive_member = file_to_extract['archive_member'] dest_dir = file_to_extract['dest_dir'] dest_filename = file_to_extract['dest_filename'] force_overwrite = file_to_extract['force_overwrite'] orig_name = archive_member.name if not archive_member.isreg() and not archive_member.issym(): return None # TODO: raise from up a level in the stack? dest_path = os.path.join(dest_dir, dest_filename) # log.debug('dest_dir: %s, dest_filename: %s, dest_path: %s orig_name: %s', # dest_dir, dest_filename, dest_path, orig_name) if os.path.exists(dest_path): if not force_overwrite: message = "The Galaxy content %s appears to already exist." % dest_path raise exceptions.GalaxyClientError(message) try: tar_file.getmember(archive_member.name) except KeyError: raise exceptions.GalaxyArchiveError( 'The archive "%s" has no file "%s"' % (tar_file.name, archive_member.name), archive_path=tar_file.name) # TODO: set a default owner/group # MAYBE TODO: pick a 'install time' and make sure all the mtime/ctime values of extracted files # match the 'install time' used in .galaxy_install_info ? # change the tar file member name in place to just the filename ('myfoo.py') so that extract places that file in # dest_dir directly instead of using adding the archive path as well # like '$dest_dir/archive-roles/library/myfoo.py' archive_member.name = dest_filename # log.debug('tar member: %s dest_dir: %s', archive_member, dest_dir) tar_file.extract(archive_member, dest_dir) installed_path = os.path.join(dest_dir, dest_filename) # reset the tar info object's name attr to the origin value in # case something else references this archive_member.name = orig_name return installed_path
def load_from_archive(repository_archive, namespace=None, installed=True): repo_tarfile = repository_archive.tar_file archive_path = repository_archive.info.archive_path # path_name = os.path.join(content_dir, namespace, name) path_name = repository_archive.info.top_dir manifest_filename = os.path.join( path_name, collection_artifact_manifest.COLLECTION_MANIFEST_FILENAME) manifest_data = None log.debug('Trying to extract %s from %s', manifest_filename, archive_path) try: mfd = repo_tarfile.extractfile(manifest_filename) if mfd: manifest_data = collection_artifact_manifest.load(mfd) log.debug('md: %s', manifest_data) log.debug('md.collection_info: %s', manifest_data.collection_info) log.debug('manifest_data.collection_info.name: %s', manifest_data.collection_info.name) except KeyError as e: log.warning('No %s found in archive: %s (Error: %s)', manifest_filename, archive_path, e) # load galaxy.yml galaxy_filename = os.path.join(path_name, collection_info.COLLECTION_INFO_FILENAME) collection_info_data = None try: gfd = repo_tarfile.extractfile(galaxy_filename) if gfd: collection_info_data = collection_info.load(gfd) except KeyError as e: log.warning('No %s found in archive: %s - %s', galaxy_filename, archive_path, e) # log.debug('No galaxy.yml collection info found for collection %s.%s: %s', namespace, name, e) # TODO/FIXME: what takes precedence? # - the dir name in the archive that a collection lives in ~/.ansible/content/my_ns/my_name # - Or the namespace/name from galaxy.yml? # log.debug('collection_info_data: %s', collection_info_data) col_info = None if manifest_data: col_info = manifest_data.collection_info log.debug('md.col_info: %s', col_info) elif collection_info_data: col_info = collection_info_data else: raise exceptions.GalaxyArchiveError( 'No galaxy collection info or manifest found in %s', archive_path) log.debug('col_info: %s', col_info) # FIXME: change collectionInfo to have separate name/namespace so we dont have to 'parse' the name # repo_spec = repository_spec.repository_spec_from_string(col_info.name, namespace_override=namespace) # spec_data = repository_spec_parse.parse_string(col_info.name) # log.debug('spec_data: %s', spec_data) # log.debug('repo_spec: %s', repo_spec) # Build a repository_spec of the repo now so we can pass it things like requirements.load() # that need to know what requires something # if we specify a namespace, use it otherwise use the info from galaxy.yml repo_spec = RepositorySpec( namespace=namespace or col_info.namespace, name=col_info.name, version=col_info.version, spec_string=archive_path, # fetch_method=None, src=archive_path) log.debug('repo spec from %s: %r', archive_path, repo_spec) requirements_list = [] requirements_list = requirements.from_requirement_spec_strings( col_info.dependencies, repository_spec=repo_spec) repository = Repository( repository_spec=repo_spec, path=None, installed=installed, requirements=requirements_list, # Assuming this is a collection artifact, FIXME if we support role artifacts dependencies=[]) log.debug('repository: %s', repository) return repository