def extract(self): retval = subprocess.call(['tar', '-xzf', self.tarballname]) if retval != 0: utils.logerr(None, "Couldn't extract tarball for {}".format(self.name)) if os.path.exists(self.tarballname): os.remove(self.tarballname) self.srcdir = os.path.join(self.ctx.builddir, self.name)
def cleanup(self): if self.srcdir: try: shutil.rmtree( self.srcdir, onerror=lambda f, p, e: utils.delete_onerror(f, p, e)) except PermissionError: utils.logerr( None, "Cannot remove {}: Permission denied".format(self.srcdir)) self.srcdir = None # if we couldn't remove it, we can't next time, so we ignore the exception and continue
def get(self): if not self.downloaded: self.downloaded = True # download os.chdir(self.ctx.builddir) r = requests.get(self.tarballpath) with open(self.tarballname, 'wb') as tarball: tarball.write(r.content) # extract retval = subprocess.call(['tar', '-xzf', self.tarballname]) if retval != 0: utils.logerr( None, "Couldn't extract tarball for {}".format(self.name)) if os.path.exists(self.tarballname): os.remove(self.tarballname) self.srcdir = os.path.join(self.ctx.builddir, self.name)
def build(self, buildflags=['-Cdf'], recursive=False, dependency=False): if dependency and self.installed: # if this is a dependency and already installed, we do not bother, # upgrades are taken care of by -Syu, just as it is common with the official repos utils.logmsg( self.ctx.v, 3, "skipping build of installed dependency {}".format(self.name)) return True if not self.check_makedeps_installed(): msg = "Makedeps not installed for {}".format(self.name) utils.logerr(None, "{}, aborting this subtree".format(msg)) return False if recursive: for d in self.deps: succeeded = d.build(buildflags=buildflags, recursive=True, dependency=True) if not succeeded: return False # one dep fails, the entire branch fails immediately, software will not be runnable if self.in_repos or (self.installed and not self.in_aur): return True if self.installed and self.in_aur and self.version_installed == self.version_latest and not self.rebuild: return True pkgs = pkg_in_cache(self) if len(pkgs) > 0 and not self.rebuild: self.built_pkgs.append( pkgs[0] ) # we only need one of them, not all, if multiple ones with different extensions have been built return True utils.logmsg(self.ctx.v, 3, "building sources of {}".format(self.name)) succeeded = self.srcpkg.build(buildflags=buildflags) if not succeeded: utils.logerr( None, "Building sources of package {} failed, aborting this subtree". format(self.name)) utils.logerr(None, "├─stdout-log: {}".format(self.srcpkg.stdoutlogfile), primary=False) utils.logerr(None, "└─stderr-log: {}".format(self.srcpkg.stderrlogfile), primary=False) if self.ctx.printed_error_log_lines > 0: utils.logmsg(self.ctx.v, 0, "Tail of stderr:") with open(self.srcpkg.stderrlogfile, 'r') as logfile: errorlog = logfile.read().strip().split("\n") for line in errorlog[-self.ctx.printed_error_log_lines:]: print(" {}".format(line)) if self.ctx.printed_error_log_lines == -1: utils.logmsg(self.ctx.v, 0, "stderr:") with open(self.srcpkg.stderrlogfile, 'r') as logfile: errorlog = logfile.read().strip().split("\n") for line in errorlog: print(" {}".format(line)) return False pkgext_makepkgconf = subprocess.getoutput( "bash -c 'source {} && echo $PKGEXT'".format(self.ctx.makepkgconf)) pkgext_env = os.environ.get('PKGEXT') pkgext = pkgext_env or pkgext_makepkgconf or '.pkg.tar.xz' fullpkgnames = [] fullpkgname_x86_64_tmpl = "{}-{}-x86_64{}" fullpkgname_any_tmpl = "{}-{}-any{}" if fullpkgname_x86_64_tmpl.format(self.name, self.version_latest, pkgext) in os.listdir( self.srcpkg.srcdir): fullpkgnames.append( fullpkgname_x86_64_tmpl.format(self.name, self.version_latest, pkgext)) elif fullpkgname_any_tmpl.format(self.name, self.version_latest, pkgext) in os.listdir( self.srcpkg.srcdir): fullpkgnames.append( fullpkgname_any_tmpl.format(self.name, self.version_latest, pkgext)) else: fullpkgnames = [ p for p in os.listdir(self.srcpkg.srcdir) if p.endswith(pkgext) ] if fullpkgnames: for fpn in fullpkgnames: self.built_pkgs.append(fpn) if os.path.exists(os.path.join(self.ctx.cachedir, fpn)): if not os.path.isfile(os.path.join(self.ctx.cachedir, fpn)): utils.logerr( None, 0, "Something (that's not a file) is shadowing package {} in cache directory {}" .format((fpn), self.cachedir)) else: shutil.move(os.path.join(self.srcpkg.srcdir, fpn), self.ctx.cachedir) else: utils.logerr( None, "No package file found in builddir for {}, aborting this subtree" .format(self.name)) return False return True
def review_file(fname, via=None): ref_file = os.path.join(self.ctx.revieweddir, self.name, fname) # compare both reference PKGBUILD (if existent) and new PKGBUILD refhash = hash_file(ref_file) newhash = hash_file(fname) if refhash == newhash and not self.ctx.force_review: msg = "{} of srcpkg {} passed review: already positively reviewed previously" utils.logmsg(self.ctx.v, 0, msg.format(fname, self.name)) return True else: # we need review, first diff it if reference exists user_verdict = None if os.path.exists(ref_file): user_verdict = 'd' # diff else: user_verdict = 'e' # edit (display with direct editing option) while True: if user_verdict == 'p': # file passed review save_as_reviewed_file(fname) return True elif user_verdict in [ 'f', 's' ]: # file failed review or was skipped return False elif user_verdict == 'e': # user decides to edit subprocess.call( [os.environ.get('EDITOR') or 'nano', fname]) elif user_verdict == 'd': # user decides to diff if os.path.exists(ref_file): termsize = shutil.get_terminal_size() separator_width = termsize.columns - 2 # 1 whitespace padding on each side print() print( colored(' ' + '=' * separator_width, attrs=['bold'])) print() if self.ctx.difftool: try: subprocess.call( [self.ctx.difftool, fname, ref_file]) except Exception as e: utils.logerr( 4, "Error using {} for diff: {}".format( self.ctx.difftool, e)) else: with open(fname, 'r') as f: max_linelength = max([ len(line) for line in f.read().strip().split('\n') ]) diffwidth = min(2 * max_linelength, os.get_terminal_size().columns) diffcmd = [ "colordiff", "--side-by-side", "--left-column", "--width={}".format(diffwidth) ] subprocess.call(diffcmd + [fname, ref_file]) print() padding = " " * (int(diffwidth / 2) - 9) subscript = "{}new <== | ==> previously positively reviewed".format( padding) print(colored(subscript, attrs=['bold'])) else: utils.logmsg( 0, 0, "No reference available, cannot provide diff") if via: # if we get a source pkg calling the review we can deduct # a dependency chain leading to this srcpkg origin = "" if via.name != self.name: # if the SourcePkg and the Package are named identically, hide the SourcePkg-distinction origin += "via " + via.name while via.parents: origin += " → " + via.parents[0].name if len(via.parents) > 1: origin += " (among others)" via = via.parents[0] if origin == "": print("{} of package {}:".format(fname, self.name)) else: print("{} of package {} ({}):".format( fname, self.name, origin)) else: print("{} of package {}:".format(fname, self.name)) user_verdict = utils.getchar( "(P)ass review, (F)ail review, (E)dit, (D)iff, (S)kip?: [p/f/e/d/s] " ).lower()
def build(self, buildflags=['-Cdf'], recursive=False): if recursive: for d in self.deps: succeeded = d.build(buildflags=buildflags, recursive=True) if not succeeded: return False # one dep fails, the entire branch fails immediately, software will not be runnable if self.in_repos or (self.installed and not self.in_aur): return True if self.installed and self.in_aur and self.version_installed == self.version_latest and not self.rebuild: return True pkgs = pkg_in_cache(self) if len(pkgs) > 0 and not self.rebuild: self.built_pkgs.append( pkgs[0] ) # we only need one of them, not all, if multiple ones with different extensions have been built return True utils.logmsg(self.ctx.v, 3, "building sources of {}".format(self.name)) if self.srcpkg.built: return self.srcpkg.build_success succeeded = self.srcpkg.build(buildflags=buildflags) if not succeeded: utils.logerr( None, "Building sources of package {} failed, aborting this subtree". format(self.name)) return False pkgext = os.environ.get('PKGEXT') or 'tar.xz' fullpkgnames = [] fullpkgname_x86_64_tmpl = "{}-{}-x86_64.pkg.{}" fullpkgname_any_tmpl = "{}-{}-any.pkg.{}" if fullpkgname_x86_64_tmpl.format(self.name, self.version_latest, pkgext) in os.listdir( self.srcpkg.srcdir): fullpkgnames.append( fullpkgname_x86_64_tmpl.format(self.name, self.version_latest, pkgext)) elif fullpkgname_any_tmpl.format(self.name, self.version_latest, pkgext) in os.listdir( self.srcpkg.srcdir): fullpkgnames.append( fullpkgname_any_tmpl.format(self.name, self.version_latest, pkgext)) else: fullpkgnames = [ p for p in os.listdir(self.srcpkg.srcdir) if p.endswith('.pkg.{}'.format(pkgext)) ] if fullpkgnames: for fpn in fullpkgnames: self.built_pkgs.append(fpn) if os.path.exists(os.path.join(self.ctx.cachedir, fpn)): if not os.path.isfile(os.path.join(self.ctx.cachedir, fpn)): utils.logerr( None, 0, "Something (that's not a file) is shadowing package {} in cache directory {}" .format((fpn), self.cachedir)) else: shutil.move(os.path.join(self.srcpkg.srcdir, fpn), self.ctx.cachedir) else: utils.logerr( None, "No package file found in builddir for {}, aborting this subtree" .format(self.name)) return False return True