class SourceLoaderTest(RpgTestCase): # FileNotFound hash FNF_MD5 = "d41d8cd98f00b204e9800998ecf8427e" def setUp(self): self._source_loader = SourceLoader() self._tar = False self._tar_dir = self.test_project_dir self._tar_gz = self.test_project_dir / "archives" / "sample.tar.gz" self._tar_xz = self.test_project_dir / "archives" / "sample.tar.xz" self._tar_temp = "/var/tmp/rpg_test/" self._tar_extracted = self._tar_temp + "extracted" self._archive = self._tar_temp + "sample" self._hasher = None if path.isdir(self._tar_extracted): rmtree(self._tar_extracted) if path.isdir(self._tar_temp): rmtree(self._tar_temp) makedirs(self._tar_temp) makedirs(self._tar_extracted) def tearDown(self): if self._tar: remove(str(self._tar)) def md5TarXz(self, t): mdsum = Command( "tar -J -xOf " + str(t) + " 2>/dev/null | md5sum | cut -b-32" ).execute()[:-1] self.assertNotEqual(self.FNF_MD5, mdsum) return mdsum def md5TarGz(self, t): mdsum = Command( "tar -xOzf " + str(t) + " 2>/dev/null | md5sum | cut -b-32" ).execute()[:-1] self.assertNotEqual(self.FNF_MD5, mdsum) return mdsum def md5Dir(self, d): mdsum = md5( Command( "find " + d + r" -type f -exec cat {} \;" ).execute(True)).hexdigest() self.assertNotEqual(self.FNF_MD5, mdsum) return mdsum def test_tar_gz_method(self): self.assertEqual( self._source_loader.get_compression_method( str(self._tar_gz)), ("tar", "gz")) def test_tar_xz_method(self): self.assertEqual( self._source_loader.get_compression_method( str(self._tar_xz)), ("tar", "xz")) def test_tar_gz_extract(self): self._source_loader.load_sources( self._tar_gz, self._tar_extracted) self.assertTrue( path.isdir(str(self._tar_extracted))) self.assertEqual( self.md5TarGz(str(self._tar_gz)), self.md5Dir(str(self._tar_extracted))) def test_tar_xz_extract(self): self._source_loader.load_sources( self._tar_xz, self._tar_extracted) self.assertTrue( path.isdir(str(self._tar_extracted))) self.assertEqual( self.md5TarXz(str(self._tar_xz)), self.md5Dir(str(self._tar_extracted))) def test_dir_source_loader(self): self._source_loader.load_sources( str(self.test_project_dir), self._tar_extracted) self.assertEqual( self.md5Dir(self._tar_extracted), self.md5Dir(str(self.test_project_dir))) def test_create_archive(self): self._tar = self._source_loader.create_archive( str(self._archive), str(self._tar_dir)) self.assertEqual( self.md5TarGz(str(self._tar)), self.md5Dir(str(self._tar_dir))) @expectedFailure def test_tar_xz_method_fail(self): self._tar_xz = self._tar_gz self.test_tar_xz_method() @expectedFailure def test_tar_gz_method_fail(self): self._tar_gz = self._tar_xz self.test_tar_gz_method() @expectedFailure def test_tar_gz_extract_fail(self): self._tar_gz = "NotAnArchive" self.test_tar_gz_extract() @expectedFailure def test_tar_xz_extract_fail(self): self._tar_xz = "NotAnArchive" self.test_tar_xz_extract() @expectedFailure def test_create_archive_fail(self): self._tar_dir = "NonExistingDir" self.test_create_archive()
class Base(object): """Base class that is controlled by RPM GUI""" def __init__(self): self.conf = Conf() self._setup_logging() self._project_builder = ProjectBuilder() self.spec = Spec() self.sack = None # TODO dnf sack self._package_builder = PackageBuilder() self._plugin_engine = PluginEngine(self.spec, self.sack) self._source_loader = SourceLoader() self._copr_uploader = CoprUploader() def _setup_logging(self): logging.basicConfig(level=logging.DEBUG, format='[%(asctime)s] {%(pathname)s:%(lineno)d} ' '%(levelname)s - %(message)s', handlers=[logging.FileHandler("rpg.log"), logging.StreamHandler()], datefmt='%H:%M:%S') def load_plugins(self): self._plugin_engine.load_plugins( Path('rpg/plugins'), self.conf.exclude) for directory in self.conf.directories: self._plugin_engine.load_plugins( Path(directory), self.conf.exclude) @property def base_dir(self): try: return Path("/tmp/rpg-%s-%s" % (self._input_name, self._hash)) except AttributeError: msg = "`process_archive_or_dir` method needs to be called first" raise RuntimeError(msg) @property def extracted_dir(self): return self.base_dir / "extracted" @property def compiled_dir(self): return self.base_dir / "compiled" @property def installed_dir(self): return self.base_dir / "installed" @property def project_name(self): return self.spec.Name @property def spec_path(self): return self.base_dir / (self.project_name + ".spec") @property def tarball_path(self): return self.base_dir / (self.project_name + ".tar.gz") @property def rpm_path(self): return next(self.base_dir.glob(self.project_name + "*.rpm")) def process_archive_or_dir(self, path): """executed in background after dir/tarball/SRPM selection""" p = Path(path) self._hash = self.compute_checksum(p) self._input_name = p.name self.setup_workspace() self._source_loader.load_sources(p, self.extracted_dir) def run_raw_sources_analysis(self): """executed in background after dir/tarball/SRPM selection""" self._plugin_engine.execute_phase(phases[0], self.extracted_dir) def apply_patches(self, ordered_patches): """executed in background after patch selection and reordering""" self._project_builder.apply_patches(ordered_patches) def run_patched_sources_analysis(self): """executed in background after patches are applied""" self._plugin_engine.execute_phase(phases[1], self.extracted_dir) def build_project(self): """executed in background after filled requires screen""" self._project_builder.build(self.extracted_dir, self.compiled_dir, self.spec.build) def run_compiled_analysis(self): """executed in background after patches are applied""" self._plugin_engine.execute_phase(phases[2], self.extracted_dir) def install_project(self): """executed in background after filled requires screen""" self._project_builder.install(self.compiled_dir, self.installed_dir, self.spec.install) def run_installed_analysis(self): """executed in background after successful project build""" self._plugin_engine.execute_phase(phases[3], self.installed_dir) def create_spec_and_archive(self): self._source_loader.create_archive(self.base_dir, self.extracted_dir) with open(str(self.spec_path), 'w') as spec_file: spec_file.write(str(self.spec)) def build_packages(self, distros, archs=platform.machine()): """builds packages for desired distributions""" for arch in archs: for distro in distros: self._package_builder.build(self.spec_path, self.tarball_path, distro, arch) @staticmethod def compute_checksum(sources): if sources.is_dir(): cmd = "find %s -type f -print0 | sort -z | xargs " \ "-0 sha1sum | sha1sum" % sources.resolve() else: cmd = "sha1sum %s" % sources.resolve() return cmd_output([cmd])[:7] @property def all_dirs(self): return [ self.extracted_dir, self.compiled_dir, self.installed_dir ] def setup_workspace(self): """make sure all directories used later will exist""" try: shutil.rmtree(str(self.base_dir)) except FileNotFoundError: pass for d in self.all_dirs: d.mkdir(parents=True) # predictor methods are used for autocompletion of the field, # every guess_* method return list of strings matched ordered # by their rank def guess_name(self): name = str(self._input_name) if isdir(name): return name else: if name[-4:] == ".zip": return name[:-4] else: if "tar" in name: return name.split(".tar")[0] return "" def guess_provide(self): # returns list of all known provides provides = set() for pkg in self.sack.query(): provides.update(pkg.provides) return sorted(provides) def guess_changelog_data(self): # returns list of tuples (author, email) from git pass def guess_dependency(self): # returns guess_provide() + all package names from repos names = map(lambda pkg: pkg.name, self.sack.query()) return sorted(set(names).union(set(self.guess_provide()))) def guess_license(self): # returns list of all known licenses licenses = set() for pkg in self.sack.query(): licenses.update(pkg.license) return sorted(licenses)