def committer_from_author(author, options): """Get committer info based on options""" committer = GitModifier() if options.author_is_committer: committer.name = author.name committer.email = author.email return committer
def get_packager(spec): """Get packager information from spec""" if spec.packager: match = re.match(r'(?P<name>.*[^ ])\s*<(?P<email>\S*)>', spec.packager.strip()) if match: return GitModifier(match.group('name'), match.group('email')) return GitModifier()
def get_maintainer_from_control(repo): """Get the maintainer from the control file""" control = os.path.join(repo.path, 'debian', 'control') maint_re = re.compile('Maintainer: +(?P<name>.*[^ ]) *<(?P<email>.*)>') with open(control, encoding='utf-8') as f: for line in f: m = maint_re.match(line) if m: return GitModifier(m.group('name'), m.group('email')) return GitModifier()
def get_committer_from_author(author, options): """ Based on the options fill in the committer """ committer = GitModifier() if options.author_committer: committer.name = author.name committer.email = author.email if options.author_committer_date: committer.date = author.date return committer
def get_maintainer_from_control(repo): """Get the maintainer from the control file""" control = os.path.join(repo.path, 'debian', 'control') maint_re = re.compile('Maintainer: +(?P<name>.*[^ ]) *<(?P<email>.*)>') try: with open(control, encoding='utf-8') as f: for line in f: m = maint_re.match(line) if m: return GitModifier(m.group('name'), m.group('email')) except FileNotFoundError: raise GbpError("Debian control file {} not found".format(control)) return GitModifier()
def get_maintainer_from_control(repo): """Get the maintainer from the control file""" control = os.path.join(repo.path, 'debian', 'control') cmd = 'sed -n -e \"s/Maintainer: \\+\\(.*\\)/\\1/p\" %s' % control cmdout = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE).stdout.readlines() if len(cmdout) > 0: maintainer = cmdout[0].strip() m = re.match('(?P<name>.*[^ ]) *<(?P<email>.*)>', maintainer) if m: return GitModifier(m.group('name'), m.group('email')) return GitModifier()
def update_changelog(changelog, entries, repo, spec, options): """Update the changelog with a range of commits""" # Get info for section header now = datetime.now() name, email = get_author(repo, options.git_author) rev_str_fields = dict(spec.version, version=RpmPkgPolicy.compose_full_version( spec.version), vendor=options.vendor) if options.commit: # Get fake information for the to-be-created git commit commit_info = { 'author': GitModifier(date=now), 'committer': GitModifier(date=now) } tag = packaging_tag_name(repo, spec, commit_info, options) else: commit_info = {'author': None, 'committer': None} tag = repo.describe('HEAD', longfmt=True, always=True) rev_str_fields['tagname'] = tag try: revision = options.changelog_revision % rev_str_fields except KeyError as err: raise GbpError("Unable to construct revision field: unknown key " "%s, only %s are accepted" % (err, rev_str_fields.keys())) # Add a new changelog section if new release or an empty changelog if options.release or not changelog.sections: top_section = changelog.add_section(time=now, name=name, email=email, revision=revision) else: # Re-use already parsed top section top_section = changelog.sections[0] top_section.set_header(time=now, name=name, email=email, revision=revision) # Add new entries to the topmost section for entry in entries: top_section.append_entry(entry) return (tag, commit_info['author'], commit_info['committer'])
def get_author_from_changelog(dir): """ Get author from debian/changelog """ dch = ChangeLog(filename=os.path.join(dir, 'debian/changelog')) date = rfc822_date_to_git(dch.date, fuzzy=True) if not (dch.author or dch.email): gbp.log.warn("Failed to parse maintainer") return GitModifier(dch.author, dch.email, date)
def get_author(repo): """Determine author name and email""" author = GitModifier() if repo: author = repo.get_author_info() passwd_data = pwd.getpwuid(os.getuid()) if not author.name: # On some distros (Ubuntu, at least) the gecos field has it's own # internal structure of comma-separated fields author.name = passwd_data.pw_gecos.split(',')[0].strip() if not author.name: author.name = passwd_data.pw_name if not author.email: if 'EMAIL' in os.environ: author.email = os.environ['EMAIL'] else: author.email = "%s@%s" % (passwd_data.pw_name, socket.getfqdn()) return author
def main(argv): """Main function of the git-import-srpm script""" dirs = dict(top=os.path.abspath(os.curdir)) ret = 0 skipped = False options, args = parse_args(argv) if len(args) != 1: gbp.log.err("Need to give exactly one package to import. Try --help.") return 1 try: dirs['tmp_base'] = tempfile.mkdtemp(dir=options.tmp_dir, prefix='import-srpm') except GbpError as err: gbp.log.err(err) return 1 try: srpm = args[0] if options.download: srpm = download_source(srpm, dirs) # Real srpm, we need to unpack, first true_srcrpm = False if not os.path.isdir(srpm) and not srpm.endswith(".spec"): src = parse_srpm(srpm) true_srcrpm = True dirs['pkgextract'] = tempfile.mkdtemp(dir=dirs['tmp_base'], prefix='pkgextract_') gbp.log.info("Extracting src rpm to '%s'" % dirs['pkgextract']) src.unpack(dirs['pkgextract']) preferred_spec = src.name + '.spec' srpm = dirs['pkgextract'] elif os.path.isdir(srpm): preferred_spec = os.path.basename(srpm.rstrip('/')) + '.spec' else: preferred_spec = None # Find and parse spec file if os.path.isdir(srpm): gbp.log.debug("Trying to import an unpacked srpm from '%s'" % srpm) dirs['src'] = os.path.abspath(srpm) spec = guess_spec(srpm, True, preferred_spec) else: gbp.log.debug("Trying to import an srpm from '%s' with spec "\ "file '%s'" % (os.path.dirname(srpm), srpm)) dirs['src'] = os.path.abspath(os.path.dirname(srpm)) spec = SpecFile(srpm) # Check the repository state try: repo = RpmGitRepository('.') is_empty = repo.is_empty() (clean, out) = repo.is_clean() if not clean and not is_empty: gbp.log.err("Repository has uncommitted changes, commit " "these first: ") raise GbpError, out except GitRepositoryError: gbp.log.info("No git repository found, creating one.") is_empty = True repo = RpmGitRepository.create(spec.name) os.chdir(repo.path) if repo.bare: set_bare_repo_options(options) # Create more tempdirs dirs['origsrc'] = tempfile.mkdtemp(dir=dirs['tmp_base'], prefix='origsrc_') dirs['packaging_base'] = tempfile.mkdtemp(dir=dirs['tmp_base'], prefix='packaging_') dirs['packaging'] = os.path.join(dirs['packaging_base'], options.packaging_dir) try: os.mkdir(dirs['packaging']) except OSError as err: if err.errno != errno.EEXIST: raise if true_srcrpm: # For true src.rpm we just take everything files = os.listdir(dirs['src']) else: # Need to copy files to the packaging directory given by caller files = [os.path.basename(patch.path) \ for patch in spec.patchseries(unapplied=True, ignored=True)] for filename in spec.sources().values(): files.append(os.path.basename(filename)) files.append(os.path.join(spec.specdir, spec.specfile)) # Don't copy orig source archive, though if spec.orig_src and spec.orig_src['filename'] in files: files.remove(spec.orig_src['filename']) for fname in files: fpath = os.path.join(dirs['src'], fname) if os.path.exists(fpath): shutil.copy2(fpath, dirs['packaging']) else: gbp.log.err("File '%s' listed in spec not found" % fname) raise GbpError # Unpack orig source archive if spec.orig_src: orig_tarball = os.path.join(dirs['src'], spec.orig_src['filename']) sources = RpmUpstreamSource(orig_tarball) sources.unpack(dirs['origsrc'], options.filters) else: sources = None src_tag_format = options.packaging_tag if options.native \ else options.upstream_tag tag_str_fields = dict(spec.version, vendor=options.vendor.lower()) src_tag = repo.version_to_tag(src_tag_format, tag_str_fields) ver_str = compose_version_str(spec.version) if repo.find_version(options.packaging_tag, tag_str_fields): gbp.log.warn("Version %s already imported." % ver_str) if options.allow_same_version: gbp.log.info("Moving tag of version '%s' since import forced" % ver_str) move_tag_stamp(repo, options.packaging_tag, tag_str_fields) else: raise SkipImport if is_empty: options.create_missing_branches = True # Determine author and committer info, currently same info is used # for both sources and packaging files author = None if spec.packager: match = re.match(r'(?P<name>.*[^ ])\s*<(?P<email>\S*)>', spec.packager.strip()) if match: author = GitModifier(match.group('name'), match.group('email')) if not author: author = GitModifier() gbp.log.debug("Couldn't determine packager info") committer = committer_from_author(author, options) # Import sources if sources: src_commit = repo.find_version(src_tag_format, tag_str_fields) if not src_commit: gbp.log.info("Tag %s not found, importing sources" % src_tag) branch = [options.upstream_branch, options.packaging_branch][options.native] if not repo.has_branch(branch): if options.create_missing_branches: gbp.log.info("Will create missing branch '%s'" % branch) else: gbp.log.err( no_upstream_branch_msg % branch + "\n" "Also check the --create-missing-branches option.") raise GbpError src_vendor = "Native" if options.native else "Upstream" msg = "%s version %s" % (src_vendor, spec.upstreamversion) src_commit = repo.commit_dir( sources.unpacked, "Imported %s" % msg, branch, author=author, committer=committer, create_missing_branch=options.create_missing_branches) repo.create_tag(name=src_tag, msg=msg, commit=src_commit, sign=options.sign_tags, keyid=options.keyid) if not options.native: if options.pristine_tar: archive_fmt = parse_archive_filename(orig_tarball)[1] if archive_fmt == 'tar': repo.pristine_tar.commit( orig_tarball, 'refs/heads/%s' % options.upstream_branch) else: gbp.log.warn('Ignoring pristine-tar, %s archives ' 'not supported' % archive_fmt) else: gbp.log.info("No orig source archive imported") # Import packaging files. For native packages we assume that also # packaging files are found in the source tarball if not options.native or not sources: gbp.log.info("Importing packaging files") branch = options.packaging_branch if not repo.has_branch(branch): if options.create_missing_branches: gbp.log.info("Will create missing branch '%s'" % branch) else: gbp.log.err(no_packaging_branch_msg % branch + "\n" "Also check the --create-missing-branches " "option.") raise GbpError tag = repo.version_to_tag(options.packaging_tag, tag_str_fields) msg = "%s release %s" % (options.vendor, ver_str) if options.orphan_packaging or not sources: commit = repo.commit_dir( dirs['packaging_base'], "Imported %s" % msg, branch, author=author, committer=committer, create_missing_branch=options.create_missing_branches) else: # Copy packaging files to the unpacked sources dir try: pkgsubdir = os.path.join(sources.unpacked, options.packaging_dir) os.mkdir(pkgsubdir) except OSError as err: if err.errno != errno.EEXIST: raise for fname in os.listdir(dirs['packaging']): shutil.copy2(os.path.join(dirs['packaging'], fname), pkgsubdir) commit = repo.commit_dir( sources.unpacked, "Imported %s" % msg, branch, other_parents=[src_commit], author=author, committer=committer, create_missing_branch=options.create_missing_branches) # Import patches on top of the source tree # (only for non-native packages with non-orphan packaging) force_to_branch_head(repo, options.packaging_branch) # Create packaging tag repo.create_tag(name=tag, msg=msg, commit=commit, sign=options.sign_tags, keyid=options.keyid) force_to_branch_head(repo, options.packaging_branch) except KeyboardInterrupt: ret = 1 gbp.log.err("Interrupted. Aborting.") except gbpc.CommandExecFailed: ret = 1 except GitRepositoryError as err: gbp.log.err("Git command failed: %s" % err) ret = 1 except GbpError as err: if str(err): gbp.log.err(err) ret = 1 except NoSpecError as err: gbp.log.err("Failed determine spec file: %s" % err) ret = 1 except SkipImport: skipped = True finally: os.chdir(dirs['top']) gbpc.RemoveTree(dirs['tmp_base'])() if not ret and not skipped: gbp.log.info("Version '%s' imported under '%s'" % (ver_str, spec.name)) return ret