1#!/usr/local/bin/python3.8 2"""Script to create a source/binary RPM. 3""" 4# $Id: make_rpm.py 509841 2016-08-09 16:23:05Z boratyng $ 5 6from __future__ import print_function 7import sys, os, shutil 8from optparse import OptionParser 9import subprocess 10import tarfile 11SCRIPT_DIR = os.path.dirname(os.path.abspath(sys.argv[0])) 12sys.path.append(os.path.join(SCRIPT_DIR, "..")) 13from blast_utils import * #IGNORE:W0401 14 15VERBOSE = False 16 17# Name of the temporary rpmbuild directory 18RPMBUILD_HOME = "rpmbuild" 19PACKAGE_NAME = "" 20# Name of the source TARBALL to create 21TARBALL = "" 22# Local RPM configuration file 23RPMMACROS = os.path.join(os.path.expanduser("~"), ".rpmmacros") 24 25def setup_rpmbuild(): 26 """ Prepare local rpmbuild directory. """ 27 cleanup_rpm() 28 os.mkdir(RPMBUILD_HOME) 29 for directory in [ 'BUILD', 'SOURCES', 'SPECS', 'SRPMS', 'tmp', 'RPMS' ]: 30 os.mkdir(os.path.join(RPMBUILD_HOME, directory)) 31 cwd = os.getcwd() 32 os.chdir(os.path.join(RPMBUILD_HOME, 'RPMS')) 33 for subdir in [ 'i386', 'i586', 'i686', 'noarch', 'x86_64' ]: 34 os.mkdir(subdir) 35 os.chdir(cwd) 36 37 # Create ~/.rpmmacros 38 with open(RPMMACROS, "w") as out: 39 print("%_topdir %( echo", os.path.join(cwd, RPMBUILD_HOME), ")", file=out) 40 print("%_tmppath %( echo", end=' ', file=out) 41 print(os.path.join(cwd, RPMBUILD_HOME, "tmp"), ")", file=out) 42 print(file=out) 43 print("%packager Christiam E. Camacho (camacho@ncbi.nlm.nih.gov)", file=out) 44 print("%debug_package %{nil}", file=out) 45 if VERBOSE: 46 print("Created", RPMMACROS) 47 48def cleanup_rpm(): 49 """ Delete rpm files """ 50 if os.path.exists(RPMBUILD_HOME): 51 shutil.rmtree(RPMBUILD_HOME) 52 53 if os.path.exists(RPMMACROS): 54 os.remove(RPMMACROS) 55 56def cleanup_srctarball_contents(): 57 """ Remove unnecessary directories/files from svn checkout """ 58 import fnmatch 59 60 cmd = "find " + PACKAGE_NAME + " -type d -name .svn | xargs rm -fr " 61 safe_exec(cmd) 62 63 os.remove(os.path.join(PACKAGE_NAME, "Makefile")) 64 for path in ["builds", "scripts"]: 65 path = os.path.join(PACKAGE_NAME, path) 66 if os.path.exists(path): 67 shutil.rmtree(path) 68 if VERBOSE: 69 print("Deleting", path) 70 71 projects_path = os.path.join(PACKAGE_NAME, "c++", "scripts", "projects") 72 for root, dirs, files in os.walk(projects_path): 73 for name in files: 74 name = os.path.join(root, name) 75 if fnmatch.fnmatch(name, "*blast/*"): 76 continue 77 if VERBOSE: 78 print("Deleting file", name) 79 os.remove(name) 80 81 for name in dirs: 82 name = os.path.join(root, name) 83 if fnmatch.fnmatch(name, "*blast*"): 84 continue 85 if VERBOSE: 86 print("Deleting directory", name) 87 shutil.rmtree(name) 88 89 90def decompress_src_tarball(srctarball): 91 """Decompreses the source tarball provided""" 92 tar = tarfile.open(srctarball) 93 os.mkdir(PACKAGE_NAME) 94 cwd = os.getcwd() 95 os.chdir(os.path.join(cwd, PACKAGE_NAME)) 96 tar.list() 97 tar.extractall() 98 os.chdir(cwd) 99 cleanup_srctarball_contents() 100 101def compress_sources(): 102 """Compress sources to be included in source RPM""" 103 tar = tarfile.open(TARBALL, "w:bz2") 104 tar.add(PACKAGE_NAME) 105 tar.close() 106 107def cleanup(): 108 """ Remove all files created. """ 109 if os.path.exists(TARBALL): 110 os.remove(TARBALL) 111 if os.path.exists(PACKAGE_NAME): 112 shutil.rmtree(PACKAGE_NAME) 113 114def run_rpm(blast_version): 115 """Run the rpmbuild command""" 116 shutil.rmtree(PACKAGE_NAME) 117 shutil.move(TARBALL, os.path.join(RPMBUILD_HOME, "SOURCES")) 118 rpm_spec = "ncbi-magicblast.spec" 119 src = os.path.join(SCRIPT_DIR, rpm_spec) 120 dest = os.path.join(RPMBUILD_HOME, "SPECS", rpm_spec) 121 shutil.copyfile(src, dest) 122 update_blast_version(dest, blast_version) 123 cmd = "/usr/bin/rpmbuild -ba " + dest 124 safe_exec(cmd) 125 126def move_rpms_to_installdir(installdir): 127 """Copy the resulting RPM files into the installation directory""" 128 installer_dir = os.path.join(installdir, "installer") 129 if not os.path.exists(installer_dir): 130 os.makedirs(installer_dir) 131 132 args = [ "find", RPMBUILD_HOME, "-name", "*.rpm" ] 133 output = subprocess.Popen(args, stdout=subprocess.PIPE).communicate()[0] 134 for rpm in output.split(): 135 rpm = rpm.decode('ascii') 136 if VERBOSE: 137 print("mv", rpm, installer_dir) 138 shutil.move(rpm, installer_dir) 139 140 141def main(): 142 """ Creates RPMs for linux. """ 143 parser = OptionParser("%prog <blast_version> <installation directory> \ 144 \"<srctarball>\"") 145 parser.add_option("-v", "--verbose", action="store_true", default=False, 146 help="Show verbose output", dest="VERBOSE") 147 options, args = parser.parse_args() 148 if len(args) != 3: 149 parser.error("Incorrect number of arguments") 150 return 1 151 152 # N.B.: srctarball may be an empty argument (i.e.: "") in case of local 153 # builds, but this script shouldn't be invoked in that case 154 blast_version, installdir, srctarball = args 155 global VERBOSE, PACKAGE_NAME, TARBALL #IGNORE:W0603 156 VERBOSE = options.VERBOSE 157 if VERBOSE: 158 print("Installing RPM to", installdir) 159 160 PACKAGE_NAME = "ncbi-magicblast-" + blast_version 161 TARBALL = PACKAGE_NAME + ".tgz" 162 163 setup_rpmbuild() 164 cleanup() 165 decompress_src_tarball(srctarball) 166 compress_sources() 167 run_rpm(blast_version) 168 move_rpms_to_installdir(installdir) 169 cleanup_rpm() 170 cleanup() 171 172if __name__ == "__main__": 173 sys.exit(main()) 174