def apply_single_patch(repo, patchfile, options): """Apply a single patch onto the pq branch""" current = repo.get_branch() if not is_pq_branch(current, options): switch_to_pq_branch(repo, current, options) patch = Patch(patchfile) apply_and_commit_patch(repo, patch, fallback_author=None)
def rebase_pq(repo, branch): if is_pq_branch(branch): base = pq_branch_base(branch) else: switch_to_pq_branch(repo, branch) base = branch GitCommand("rebase")([base])
def convert_package(repo, options): """Convert package to orphan-packaging model""" old_packaging = repo.get_branch() # Check if we're on pq branch, already err_msg_base = "Seems you're already using orphan-packaging model - " if is_pq_branch(old_packaging, options): raise GbpError(err_msg_base + "you're on patch-queue branch") # Check if a pq branch already exists spec = parse_spec(options, repo, treeish=old_packaging) pq_branch = pq_branch_name(old_packaging, options, spec.version) if repo.has_branch(pq_branch): pq_branch = pq_branch_name(old_packaging, options, spec.version) raise GbpError(err_msg_base + "pq branch %s already exists" % pq_branch) # Check that the current branch is based on upstream upstream_commit = find_upstream_commit(repo, spec, options.upstream_tag) if not is_ancestor(repo, upstream_commit, old_packaging): raise GbpError(err_msg_base + "%s is not based on upstream version %s" % (old_packaging, spec.upstreamversion)) # Check new branch new_branch = old_packaging + "-orphan" if repo.has_branch(new_branch): if not options.force: raise GbpError("Branch '%s' already exists!" % new_branch) else: gbp.log.info("Dropping branch '%s'" % new_branch) repo.delete_branch(new_branch) # Determine "history" if options.retain_history: # Find first commit that has the spec file and list commits from there try: repo.show('%s:%s' % (upstream_commit, spec.specpath)) history = repo.get_commits(upstream_commit, old_packaging) except GitRepositoryError: history_start = repo.get_commits(upstream_commit, old_packaging, spec.specpath)[-1] history = repo.get_commits('%s^' % history_start, old_packaging) else: history = [repo.rev_parse(old_packaging)] history.reverse() # Do import gbp.log.info("Importing packaging files from branch '%s' to '%s'" % (old_packaging, new_branch)) convert_with_history(repo, upstream_commit, history, new_branch, spec.specfile, options) # Copy extra files import_extra_files(repo, old_packaging, options.import_files, patch_ignore=False) gbp.log.info("Package successfully converted to orphan-packaging.") gbp.log.info("You're now on the new '%s' packaging branch (the old " "packaging branch '%s' was left intact)." % (new_branch, old_packaging)) gbp.log.info("Please check all files and test building the package!")
def switch_pq(repo, current): """Switch to patch-queue branch if on base branch and vice versa""" if is_pq_branch(current): base = pq_branch_base(current) gbp.log.info("Switching to %s" % base) repo.checkout(base) else: switch_to_pq_branch(repo, current)
def switch_pq(repo, branch, options): """Switch to patch-queue branch if on base branch and vice versa""" if is_pq_branch(branch): base = pq_branch_base(branch) gbp.log.info("Switching to %s" % base) repo.checkout(base) else: maybe_import_pq(repo, branch, options) switch_to_pq_branch(repo, branch)
def drop_pq_bb(cfg, repo, options): """Remove pq branch""" current = repo.get_branch() if is_pq_branch(current, options): base = pq_branch_base(current, options) bbfile = parse_bb(cfg, options, repo, base) else: bbfile = parse_bb(cfg, options, repo) drop_pq(repo, current, options, pkg_version(bbfile))
def switch_pq(repo, options): """Switch to patch-queue branch if on base branch and vice versa""" current = repo.get_branch() if is_pq_branch(current, options): base = pq_branch_base(current, options) gbp.log.info("Switching to branch '%s'" % base) repo.checkout(base) else: switch_to_pq_branch(repo, current, options)
def drop_pq_rpm(repo, options): """Remove pq branch""" current = repo.get_branch() if is_pq_branch(current, options): base = pq_branch_base(current, options) spec = parse_spec(options, repo, base) else: spec = parse_spec(options, repo) drop_pq(repo, current, options, spec.version)
def rebase_pq(repo, branch, pq_from, upstream_tag): if is_pq_branch(branch): base = pq_branch_base(branch) else: raise GbpError("Rebase must be run from the patch-queue branch. " "Try 'import' instead.") if pq_on_upstream_tag(pq_from): base = find_upstream_commit(repo, base, upstream_tag) GitCommand("rebase", cwd=repo.path)([base])
def import_bb_patches(cfg, repo, options): """Apply a series of patches in a recipe to branch onto a pq branch""" current = repo.get_branch() if is_pq_branch(current, options): base = pq_branch_base(current, options) raise GbpError("Already on a patch-queue branch '%s' - doing " "nothing." % current) else: bbfile = parse_bb(cfg, options, repo) base = current upstream_commit = find_upstream_commit(repo, bbfile, options.upstream_tag) pq_branch = pq_branch_name(base, options, pkg_version(bbfile)) # Create pq-branch if repo.has_branch(pq_branch) and not options.force: raise GbpError("Patch-queue branch '%s' already exists. " "Try 'rebase' instead." % pq_branch) try: if repo.get_branch() == pq_branch: repo.force_head(upstream_commit, hard=True) else: repo.create_branch(pq_branch, upstream_commit, force=True) except GitRepositoryError as err: raise GbpError("Cannot create patch-queue branch '%s': %s" % (pq_branch, err)) # Put patches in a safe place in_queue = bb_to_patch_series(bbfile) queue = safe_patches(in_queue, options.tmp_dir) # Do import try: gbp.log.info("Switching to branch '%s'" % pq_branch) repo.set_branch(pq_branch) import_extra_files(repo, base, options.import_files) if not queue: return gbp.log.info("Trying to apply patches from branch '%s' onto '%s'" % (base, upstream_commit)) for patch in queue: gbp.log.debug("Applying %s" % patch.path) apply_and_commit_patch(repo, patch, fallback_author=None) except (GbpError, GitRepositoryError) as err: gbp.log.err('Import failed: %s' % err) repo.force_head('HEAD', hard=True) repo.set_branch(base) repo.delete_branch(pq_branch) raise recipe_fn = os.path.basename(bbfile.getVar('FILE', True)) gbp.log.info("Patches listed in '%s' imported on '%s'" % (recipe_fn, pq_branch))
def rebase_pq(repo, options): """Rebase pq branch on the correct upstream version (from spec file).""" current = repo.get_branch() if is_pq_branch(current): base = pq_branch_base(current) spec = parse_spec(options, repo, base) else: base = current spec = parse_spec(options, repo) upstream_commit = find_upstream_commit(repo, spec, options.upstream_tag) switch_to_pq_branch(repo, base) GitCommand("rebase")([upstream_commit])
def rebase_pq(cfg, repo, options): """Rebase pq branch on the correct upstream version""" current = repo.get_branch() if is_pq_branch(current, options): base = pq_branch_base(current, options) bbfile = parse_bb(cfg, options, repo, base) else: base = current bbfile = parse_bb(cfg, options, repo) upstream_commit = find_upstream_commit(repo, bbfile, options.upstream_tag) switch_to_pq_branch(cfg, repo, base, options) GitCommand("rebase")([upstream_commit])
def rebase_pq(repo, branch, pq_from, upstream_tag): if is_pq_branch(branch): base = pq_branch_base(branch) else: switch_to_pq_branch(repo, branch) base = branch if pq_on_upstream_tag(pq_from): _from = find_upstream_commit(repo, base, upstream_tag) else: _from = base GitCommand("rebase", cwd=repo.path)([_from])
def export_patches(repo, branch, options): """Export patches from the pq branch into a patch series""" patch_dir = os.path.join(repo.path, PATCH_DIR) series_file = os.path.join(repo.path, SERIES_FILE) if is_pq_branch(branch): base = pq_branch_base(branch) gbp.log.info("On '%s', switching to '%s'" % (branch, base)) branch = base repo.set_branch(branch) pq_branch = pq_branch_name(branch) try: shutil.rmtree(patch_dir) except OSError as e: if e.errno != errno.ENOENT: raise GbpError("Failed to remove patch dir: %s" % e.strerror) else: gbp.log.debug("%s does not exist." % patch_dir) if pq_on_upstream_tag(options.pq_from): base = find_upstream_commit(repo, branch, options.upstream_tag) else: base = branch patches = generate_patches(repo, base, pq_branch, patch_dir, options) if patches: with open(series_file, 'w') as seriesfd: for patch in patches: seriesfd.write(os.path.relpath(patch, patch_dir) + '\n') else: gbp.log.info("No patches on '%s' - nothing to export." % pq_branch) if options.commit: added, removed = commit_patches(repo, branch, patches, options, patch_dir) if added: what = 'patches' if len(added) > 1 else 'patch' gbp.log.info("Added %s %s to patch series" % (what, ', '.join(added))) if removed: what = 'patches' if len(removed) > 1 else 'patch' gbp.log.info("Removed %s %s from patch series" % (what, ', '.join(removed))) else: gbp.log.info("Updated existing patches.") if options.drop: drop_pq(repo, branch)
def switch_to_pq_branch(repo, branch, options): """ Switch to patch-queue branch if not already there, create it if it doesn't exist yet """ if is_pq_branch(branch, options): return spec = parse_spec(options, repo, branch) pq_branch = pq_branch_name(branch, options, spec.version) if not repo.has_branch(pq_branch): raise GbpError("Branch '%s' does not exist" % pq_branch) gbp.log.info("Switching to branch '%s'" % pq_branch) repo.set_branch(pq_branch)
def export_patches(repo, branch, options): """Export patches from the pq branch into a patch series""" if is_pq_branch(branch): base = pq_branch_base(branch) gbp.log.info("On '%s', switching to '%s'" % (branch, base)) branch = base repo.set_branch(branch) pq_branch = pq_branch_name(branch) try: shutil.rmtree(PATCH_DIR) except OSError as (e, msg): if e != errno.ENOENT: raise GbpError("Failed to remove patch dir: %s" % msg) else: gbp.log.debug("%s does not exist." % PATCH_DIR)
def export_patches(repo, options): """Export patches from the pq branch into a packaging branch""" current = repo.get_branch() if is_pq_branch(current): base = pq_branch_base(current) gbp.log.info("On branch '%s', switching to '%s'" % (current, base)) repo.set_branch(base) pq_branch = current else: pq_branch = pq_branch_name(current) spec = parse_spec(options, repo) upstream_commit = find_upstream_commit(repo, spec, options.upstream_tag) export_treeish = pq_branch update_patch_series(repo, spec, upstream_commit, export_treeish, options) GitCommand('status')(['--', spec.specdir])
def guess_export_params(repo, options): """Get commit and tree from where to export packaging and patches""" tree = None branch = None if options.export in wc_names.keys() + [index_name, 'HEAD']: branch = get_current_branch(repo) elif options.export in repo.get_local_branches(): branch = options.export if branch: if is_pq_branch(branch, options): packaging_branch = pq_branch_base(branch, options) if repo.has_branch(packaging_branch): gbp.log.info("It seems you're building a development/patch-" "queue branch. Export target changed to '%s' and " "patch-export enabled!" % packaging_branch) options.patch_export = True if not options.patch_export_rev: options.patch_export_rev = options.export options.export = packaging_branch else: gbp.log.warn("It seems you're building a development/patch-" "queue branch. No corresponding packaging branch " "found. Build may fail!") if tree is None: tree = get_tree(repo, options.export) # Get recipe path bb_path = guess_bb_path(options, repo, tree, bbappend=True) # Adjust meta-dir accordingly options.meta_dir = os.path.dirname(bb_path) # Filter out changes in recipe directory if options.patch_export: relpath = os.path.relpath(os.path.abspath(options.meta_dir), repo.path) if relpath != '.': gbp.log.info("Auto-excluding changes under meta-dir (%s/)" % relpath) if options.patch_export_ignore_path: options.patch_export_ignore_path += '|' + relpath + '/*' else: options.patch_export_ignore_path = relpath + '/*' return tree
def export_patches(cfg, repo, options): """Export patches from the pq branch into a packaging branch""" current = repo.get_branch() if is_pq_branch(current, options): base = pq_branch_base(current, options) gbp.log.info("On branch '%s', switching to '%s'" % (current, base)) repo.set_branch(base) bbfile = parse_bb(cfg, options, repo) pq_branch = current else: bbfile = parse_bb(cfg, options, repo) pq_branch = pq_branch_name(current, options, pkg_version(bbfile)) upstream_commit = find_upstream_commit(repo, bbfile, options.upstream_tag) export_treeish = options.export_rev if options.export_rev else pq_branch update_patch_series(repo, bbfile, upstream_commit, export_treeish, options) bb_dir = os.path.dirname(bbfile.getVar('FILE', True)) GitCommand('status')(['--', bb_dir])
def export_patches(repo, options): """Export patches from the pq branch into a packaging branch""" current = repo.get_branch() if is_pq_branch(current, options): base = pq_branch_base(current, options) gbp.log.info("On branch '%s', switching to '%s'" % (current, base)) repo.set_branch(base) spec = parse_spec(options, repo) pq_branch = current else: spec = parse_spec(options, repo) pq_branch = pq_branch_name(current, options, spec.version) upstream_commit = find_upstream_commit(repo, spec, options.upstream_tag) export_treeish = options.export_rev if options.export_rev else pq_branch if not repo.has_treeish(export_treeish): raise GbpError('Invalid treeish object %s' % export_treeish) update_patch_series(repo, spec, upstream_commit, export_treeish, options) GitCommand('status')(['--', spec.specdir])
def perform_tagging(repo, source, options, hook_env=None): """ Perform the tagging Select brach to tag, create tag and run hooks """ branch = repo.branch if branch and is_pq_branch(branch): commit = repo.get_merge_base(branch, pq_branch_base(branch)) else: commit = repo.head tag = create_debian_tag(repo, source, commit, options) if options.posttag: sha = repo.rev_parse("%s^{}" % tag) Hook('Posttag', options.posttag, extra_env=Hook.md(hook_env or {}, {'GBP_TAG': tag, 'GBP_BRANCH': branch or '(no branch)', 'GBP_SHA1': sha}) )()
def export_patches(repo, branch, options): """Export patches from the pq branch into a patch series""" if is_pq_branch(branch): base = pq_branch_base(branch) gbp.log.info("On '%s', switching to '%s'" % (branch, base)) branch = base repo.set_branch(branch) pq_branch = pq_branch_name(branch) try: shutil.rmtree(PATCH_DIR) except OSError as e: if e.errno != errno.ENOENT: raise GbpError("Failed to remove patch dir: %s" % e.strerror) else: gbp.log.debug("%s does not exist." % PATCH_DIR) patches = generate_patches(repo, branch, pq_branch, PATCH_DIR, options) if patches: with open(SERIES_FILE, 'w') as seriesfd: for patch in patches: seriesfd.write(os.path.relpath(patch, PATCH_DIR) + '\n') if options.commit: added, removed = commit_patches(repo, branch, patches, options) if added: what = 'patches' if len(added) > 1 else 'patch' gbp.log.info("Added %s %s to patch series" % (what, ', '.join(added))) if removed: what = 'patches' if len(removed) > 1 else 'patch' gbp.log.info("Removed %s %s from patch series" % (what, ', '.join(removed))) else: GitCommand('status')(['--', PATCH_DIR]) else: gbp.log.info("No patches on '%s' - nothing to do." % pq_branch) if options.drop: drop_pq(repo, branch)
def perform_tagging(repo, source, options, hook_env=None): """ Perform the tagging Select brach to tag, create tag and run hooks """ branch = repo.branch if branch and is_pq_branch(branch): commit = repo.get_merge_base(branch, pq_branch_base(branch)) else: commit = repo.head tag = create_debian_tag(repo, source, commit, options) if options.posttag: sha = repo.rev_parse("%s^{}" % tag) Hook('Posttag', options.posttag, extra_env=Hook.md(hook_env or {}, { 'GBP_TAG': tag, 'GBP_BRANCH': branch or '(no branch)', 'GBP_SHA1': sha }))()
def guess_export_params(repo, options): """Get commit and tree from where to export packaging and patches""" tree = None branch = None if options.export in wc_names.keys() + [index_name, 'HEAD']: branch = get_current_branch(repo) elif options.export in repo.get_local_branches(): branch = options.export if branch: if is_pq_branch(branch, options): packaging_branch = pq_branch_base(branch, options) if repo.has_branch(packaging_branch): gbp.log.info("It seems you're building a development/patch-" "queue branch. Export target changed to '%s' and " "patch-export enabled!" % packaging_branch) options.patch_export = True if not options.patch_export_rev: options.patch_export_rev = options.export options.export = packaging_branch else: gbp.log.warn("It seems you're building a development/patch-" "queue branch. No corresponding packaging branch " "found. Build may fail!") elif options.patch_export and not options.patch_export_rev: tree = get_tree(repo, options.export) spec = parse_spec(options, repo, treeish=tree) pq_branch = pq_branch_name(branch, options, spec.version) if repo.has_branch(pq_branch): gbp.log.info("Exporting patches from development/patch-queue " "branch '%s'" % pq_branch) options.patch_export_rev = pq_branch if tree is None: tree = get_tree(repo, options.export) spec = parse_spec(options, repo, treeish=tree) # Return tree-ish object and relative spec path for for exporting packaging return tree, spec.specpath
def import_spec_patches(repo, options): """ apply a series of patches in a spec/packaging dir to branch the patch-queue branch for 'branch' @param repo: git repository to work on @param options: command options """ current = repo.get_branch() # Get spec and related information if is_pq_branch(current): base = pq_branch_base(current) if options.force: spec = parse_spec(options, repo, base) spec_treeish = base else: raise GbpError("Already on a patch-queue branch '%s' - doing " "nothing." % current) else: spec = parse_spec(options, repo) spec_treeish = None base = current upstream_commit = find_upstream_commit(repo, spec, options.upstream_tag) packager = get_packager(spec) pq_branch = pq_branch_name(base) # Create pq-branch if repo.has_branch(pq_branch) and not options.force: raise GbpError("Patch-queue branch '%s' already exists. " "Try 'switch' instead." % pq_branch) try: if repo.get_branch() == pq_branch: repo.force_head(upstream_commit, hard=True) else: repo.create_branch(pq_branch, upstream_commit, force=True) except GitRepositoryError as err: raise GbpError("Cannot create patch-queue branch '%s': %s" % (pq_branch, err)) # Put patches in a safe place if spec_treeish: packaging_tmp = tempfile.mkdtemp(prefix='dump_') packaging_tree = '%s:%s' % (spec_treeish, options.packaging_dir) dump_tree(repo, packaging_tmp, packaging_tree, with_submodules=False, recursive=False) spec.specdir = packaging_tmp in_queue = spec.patchseries() queue = safe_patches(in_queue) # Do import try: gbp.log.info("Switching to branch '%s'" % pq_branch) repo.set_branch(pq_branch) if not queue: return gbp.log.info("Trying to apply patches from branch '%s' onto '%s'" % (base, upstream_commit)) for patch in queue: gbp.log.debug("Applying %s" % patch.path) apply_and_commit_patch(repo, patch, packager) except (GbpError, GitRepositoryError) as err: repo.set_branch(base) repo.delete_branch(pq_branch) raise GbpError('Import failed: %s' % err) gbp.log.info("%d patches listed in '%s' imported on '%s'" % (len(queue), spec.specfile, pq_branch))
def import_quilt_patches(repo, branch, series, tries, force, pq_from, upstream_tag): """ apply a series of quilt patches in the series file 'series' to branch the patch-queue branch for 'branch' @param repo: git repository to work on @param branch: branch to base patch queue on @param series: series file to read patches from @param tries: try that many times to apply the patches going back one commit in the branches history after each failure. @param force: import the patch series even if the branch already exists @param pq_from: what to use as the starting point for the pq branch. DEBIAN indicates the current branch, TAG indicates that the corresponding upstream tag should be used. @param upstream_tag: upstream tag template to use """ tmpdir = None series = os.path.join(repo.path, series) if is_pq_branch(branch): if force: branch = pq_branch_base(branch) pq_branch = pq_branch_name(branch) repo.checkout(branch) else: raise GbpError( "Already on a patch-queue branch '%s' - doing nothing." % branch) else: pq_branch = pq_branch_name(branch) if repo.has_branch(pq_branch): if force: drop_pq(repo, branch) else: raise GbpError( "Patch queue branch '%s'. already exists. Try 'rebase' or 'switch' instead." % pq_branch) maintainer = get_maintainer_from_control(repo) if pq_on_upstream_tag(pq_from): commits = [find_upstream_commit(repo, branch, upstream_tag)] else: # pq_from == 'DEBIAN' commits = repo.get_commits(num=tries, first_parent=True) # If we go back in history we have to safe our pq so we always try to apply # the latest one # If we are using the upstream_tag, we always need a copy of the patches if len(commits) > 1 or pq_on_upstream_tag(pq_from): if os.path.exists(series): tmpdir, series = safe_patches(series, repo) queue = PatchSeries.read_series_file(series) i = len(commits) for commit in commits: if len(commits) > 1: gbp.log.info("%d %s left" % (i, 'tries' if i > 1 else 'try')) try: gbp.log.info("Trying to apply patches at '%s'" % commit) repo.create_branch(pq_branch, commit) except GitRepositoryError: raise GbpError("Cannot create patch-queue branch '%s'." % pq_branch) repo.set_branch(pq_branch) for patch in queue: gbp.log.debug("Applying %s" % patch.path) try: name = os.path.basename(patch.path) apply_and_commit_patch(repo, patch, maintainer, patch.topic, name) except (GbpError, GitRepositoryError) as e: gbp.log.err("Failed to apply '%s': %s" % (patch.path, e)) repo.force_head('HEAD', hard=True) repo.set_branch(branch) repo.delete_branch(pq_branch) break else: # All patches applied successfully break i -= 1 else: raise GbpError("Couldn't apply patches") if tmpdir: gbp.log.debug("Remove temporary patch safe '%s'" % tmpdir) shutil.rmtree(tmpdir) return len(queue)
def import_quilt_patches(repo, branch, series, tries, force): """ apply a series of quilt patches in the series file 'series' to branch the patch-queue branch for 'branch' @param repo: git repository to work on @param branch: branch to base pqtch queue on @param series; series file to read patches from @param tries: try that many times to apply the patches going back one commit in the branches history after each failure. @param force: import the patch series even if the branch already exists """ tmpdir = None if is_pq_branch(branch): if force: branch = pq_branch_base(branch) pq_branch = pq_branch_name(branch) repo.checkout(branch) else: gbp.log.err("Already on a patch-queue branch '%s' - doing nothing." % branch) raise GbpError else: pq_branch = pq_branch_name(branch) if repo.has_branch(pq_branch): if force: drop_pq(repo, branch) else: raise GbpError("Patch queue branch '%s'. already exists. Try 'rebase' instead." % pq_branch) maintainer = get_maintainer_from_control(repo) commits = repo.get_commits(num=tries, first_parent=True) # If we go back in history we have to safe our pq so we always try to apply # the latest one if len(commits) > 1: tmpdir, series = safe_patches(series) queue = PatchSeries.read_series_file(series) i = len(commits) for commit in commits: if len(commits) > 1: gbp.log.info("%d %s left" % (i, 'tries' if i > 1 else 'try')) try: gbp.log.info("Trying to apply patches at '%s'" % commit) repo.create_branch(pq_branch, commit) except GitRepositoryError: raise GbpError("Cannot create patch-queue branch '%s'." % pq_branch) repo.set_branch(pq_branch) for patch in queue: gbp.log.debug("Applying %s" % patch.path) try: apply_and_commit_patch(repo, patch, maintainer, patch.topic) except (GbpError, GitRepositoryError): gbp.log.err("Failed to apply '%s'" % patch.path) repo.set_branch(branch) repo.delete_branch(pq_branch) break else: # All patches applied successfully break i-=1 else: raise GbpError("Couldn't apply patches") if tmpdir: gbp.log.debug("Remove temporary patch safe '%s'" % tmpdir) shutil.rmtree(tmpdir)
def import_quilt_patches(repo, branch, series, tries, force, pq_from, upstream_tag): """ apply a series of quilt patches in the series file 'series' to branch the patch-queue branch for 'branch' @param repo: git repository to work on @param branch: branch to base patch queue on @param series: series file to read patches from @param tries: try that many times to apply the patches going back one commit in the branches history after each failure. @param force: import the patch series even if the branch already exists @param pq_from: what to use as the starting point for the pq branch. DEBIAN indicates the current branch, TAG indicates that the corresponding upstream tag should be used. @param upstream_tag: upstream tag template to use """ tmpdir = None series = os.path.join(repo.path, series) if is_pq_branch(branch): if force: branch = pq_branch_base(branch) pq_branch = pq_branch_name(branch) repo.checkout(branch) else: raise GbpError("Already on a patch-queue branch '%s' - doing nothing." % branch) else: pq_branch = pq_branch_name(branch) if repo.has_branch(pq_branch): if force: drop_pq(repo, branch) else: raise GbpError("Patch queue branch '%s'. already exists. Try 'rebase' or 'switch' instead." % pq_branch) maintainer = get_maintainer_from_control(repo) if pq_on_upstream_tag(pq_from): commits = [find_upstream_commit(repo, branch, upstream_tag)] else: # pq_from == 'DEBIAN' commits = repo.get_commits(num=tries, first_parent=True) # If we go back in history we have to safe our pq so we always try to apply # the latest one # If we are using the upstream_tag, we always need a copy of the patches if len(commits) > 1 or pq_on_upstream_tag(pq_from): if os.path.exists(series): tmpdir, series = safe_patches(series, repo) queue = PatchSeries.read_series_file(series) i = len(commits) for commit in commits: if len(commits) > 1: gbp.log.info("%d %s left" % (i, 'tries' if i > 1 else 'try')) try: gbp.log.info("Trying to apply patches at '%s'" % commit) repo.create_branch(pq_branch, commit) except GitRepositoryError: raise GbpError("Cannot create patch-queue branch '%s'." % pq_branch) repo.set_branch(pq_branch) for patch in queue: gbp.log.debug("Applying %s" % patch.path) try: name = os.path.basename(patch.path) apply_and_commit_patch(repo, patch, maintainer, patch.topic, name) except (GbpError, GitRepositoryError) as e: gbp.log.err("Failed to apply '%s': %s" % (patch.path, e)) repo.force_head('HEAD', hard=True) repo.set_branch(branch) repo.delete_branch(pq_branch) break else: # All patches applied successfully break i -= 1 else: raise GbpError("Couldn't apply patches") if tmpdir: gbp.log.debug("Remove temporary patch safe '%s'" % tmpdir) shutil.rmtree(tmpdir) return len(queue)
def main(argv): retval = 0 prefix = "git-" source = None branch = None hook_env = {} options, gbp_args, dpkg_args = parse_args(argv, prefix) if not options: return ExitCodes.parse_error try: repo = DebianGitRepository(os.path.curdir) except GitRepositoryError: gbp.log.err("%s is not a git repository" % (os.path.abspath('.'))) return 1 try: clean_working_tree(options, repo) try: branch = repo.get_branch() except GitRepositoryError: # Not being on any branch is o.k. with --git-ignore-branch if not options.ignore_branch: raise if not options.ignore_new and not options.ignore_branch: if branch != options.debian_branch: gbp.log.err("You are not on branch '%s' but on '%s'" % (options.debian_branch, branch)) raise GbpError( "Use --git-ignore-branch to ignore or --git-debian-branch to set the branch name." ) head = repo.head tree = write_tree(repo, options) source = source_vfs(repo, options, tree) check_tag(options, repo, source) if not options.tag_only: output_dir = prepare_output_dir(options.export_dir) tarball_dir = options.tarball_dir or output_dir # Get/build the upstream tarball if necessary. We delay this in # case of a postexport hook so the hook gets a chance to modify the # sources and create different tarballs (#640382) # We don't delay it in general since we want to fail early if the # tarball is missing. if not source.is_native(): if options.postexport: gbp.log.info( "Postexport hook set, delaying tarball creation") else: prepare_upstream_tarball(repo, source, options, tarball_dir, output_dir) build_env, hook_env = setup_pbuilder(options, repo, source.is_native()) # Export to another build dir if requested: if options.export_dir: tmp_dir = os.path.join(output_dir, "%s-tmp" % source.sourcepkg) export_source(repo, tree, source, options, tmp_dir, output_dir) # Run postexport hook if options.postexport: Hook('Postexport', options.postexport, extra_env=Hook.md(hook_env, { 'GBP_GIT_DIR': repo.git_dir, 'GBP_TMP_DIR': tmp_dir }))(dir=tmp_dir) major = (source.debian_version if source.is_native() else source.upstream_version) export_dir = os.path.join(output_dir, "%s-%s" % (source.sourcepkg, major)) gbp.log.info("Moving '%s' to '%s'" % (tmp_dir, export_dir)) move_old_export(export_dir) os.rename(tmp_dir, export_dir) # Delayed tarball creation in case a postexport hook is used: if not source.is_native() and options.postexport: prepare_upstream_tarball(repo, source, options, tarball_dir, output_dir) build_dir = export_dir else: build_dir = repo.path if options.prebuild: Hook('Prebuild', options.prebuild, extra_env=Hook.md(hook_env, { 'GBP_GIT_DIR': repo.git_dir, 'GBP_BUILD_DIR': build_dir }))(dir=build_dir) # Finally build the package: RunAtCommand( options.builder, [pipes.quote(arg) for arg in dpkg_args], shell=True, extra_env=Hook.md(build_env, {'GBP_BUILD_DIR': build_dir}))(dir=build_dir) if options.postbuild: changes = os.path.abspath( "%s/../%s_%s_%s.changes" % (build_dir, source.changelog.name, source.changelog.noepoch, changes_file_suffix(dpkg_args))) gbp.log.debug("Looking for changes file %s" % changes) Hook('Postbuild', options.postbuild, extra_env=Hook.md(hook_env, { 'GBP_CHANGES_FILE': changes, 'GBP_BUILD_DIR': build_dir }))() if options.tag or options.tag_only: if is_pq_branch(branch): commit = repo.get_merge_base(branch, pq_branch_base(branch)) else: commit = head tag = repo.version_to_tag(options.debian_tag, source.version) gbp.log.info("Tagging %s as %s" % (source.version, tag)) if options.retag and repo.has_tag(tag): repo.delete_tag(tag) tag_msg = format_str( options.debian_tag_msg, dict(pkg=source.sourcepkg, version=source.version)) repo.create_tag(name=tag, msg=tag_msg, sign=options.sign_tags, commit=commit, keyid=options.keyid) if options.posttag: sha = repo.rev_parse("%s^{}" % tag) Hook('Posttag', options.posttag, extra_env=Hook.md( hook_env, { 'GBP_TAG': tag, 'GBP_BRANCH': branch or '(no branch)', 'GBP_SHA1': sha }))() except KeyboardInterrupt: retval = 1 gbp.log.err("Interrupted. Aborting.") except CommandExecFailed: retval = 1 except (GbpError, GitRepositoryError) as err: if str(err): gbp.log.err(err) retval = 1 except DebianSourceError as err: gbp.log.err(err) source = None retval = 1 finally: drop_index(repo) if not options.tag_only: if options.export_dir and options.purge and not retval: RemoveTree(export_dir)() if source: summary, msg = gbp.notifications.build_msg(source.changelog, not retval) if not gbp.notifications.notify(summary, msg, options.notify): gbp.log.err("Failed to send notification") retval = 1 return retval
def import_spec_patches(repo, options): """ apply a series of patches in a spec/packaging dir to branch the patch-queue branch for 'branch' @param repo: git repository to work on @param options: command options """ current = repo.get_branch() # Get spec and related information if is_pq_branch(current): base = pq_branch_base(current) if options.force: spec = parse_spec(options, repo, base) spec_treeish = base else: raise GbpError("Already on a patch-queue branch '%s' - doing " "nothing." % current) else: spec = parse_spec(options, repo) spec_treeish = None base = current upstream_commit = find_upstream_commit(repo, spec, options.upstream_tag) packager = get_packager(spec) pq_branch = pq_branch_name(base) # Create pq-branch if repo.has_branch(pq_branch) and not options.force: raise GbpError("Patch-queue branch '%s' already exists. " "Try 'switch' instead." % pq_branch) try: if repo.get_branch() == pq_branch: repo.force_head(upstream_commit, hard=True) else: repo.create_branch(pq_branch, upstream_commit, force=True) except GitRepositoryError as err: raise GbpError("Cannot create patch-queue branch '%s': %s" % (pq_branch, err)) # Put patches in a safe place if spec_treeish: packaging_tmp = tempfile.mkdtemp(prefix='dump_', dir=options.tmp_dir) packaging_tree = '%s:%s' % (spec_treeish, options.packaging_dir) dump_tree(repo, packaging_tmp, packaging_tree, with_submodules=False, recursive=False) spec.specdir = packaging_tmp in_queue = spec.patchseries() queue = safe_patches(in_queue, options.tmp_dir) # Do import try: gbp.log.info("Switching to branch '%s'" % pq_branch) repo.set_branch(pq_branch) if not queue: return gbp.log.info("Trying to apply patches from branch '%s' onto '%s'" % (base, upstream_commit)) for patch in queue: gbp.log.debug("Applying %s" % patch.path) apply_and_commit_patch(repo, patch, packager) except (GbpError, GitRepositoryError) as err: repo.set_branch(base) repo.delete_branch(pq_branch) raise GbpError('Import failed: %s' % err) gbp.log.info("Patches listed in '%s' imported on '%s'" % (spec.specfile, pq_branch))