def tree_set_changelog_version(tree: WorkingTree, build_version: Version, subpath: str) -> None: cl_path = osutils.pathjoin(subpath, "debian/changelog") with tree.get_file(cl_path) as f: cl = Changelog(f) if Version(str(cl.version) + "~") > build_version: return cl.version = build_version with open(tree.abspath(cl_path), "w") as f: cl.write_to_open_file(f)
def guess_update_changelog( tree: WorkingTree, debian_path: str, cl: Optional[Changelog] = None ) -> Optional[ChangelogBehaviour]: """Guess whether the changelog should be updated. Args: tree: Tree to edit debian_path: Path to packaging in tree Returns: best guess at whether we should update changelog (bool) """ if debian_path != "debian": return ChangelogBehaviour( True, "assuming changelog needs to be updated since " "gbp dch only suppors a debian directory in the root of the " "repository") changelog_path = osutils.pathjoin(debian_path, "changelog") if cl is None: try: with tree.get_file(changelog_path) as f: cl = Changelog(f) except NoSuchFile: cl = None if cl and is_unreleased_inaugural(cl): return ChangelogBehaviour( False, "assuming changelog does not need to be updated " "since it is the inaugural unreleased entry") ret = _guess_update_changelog_from_tree(tree, debian_path, cl) if ret is not None: return ret ret = _guess_update_changelog_from_branch(tree.branch, debian_path) if ret is not None: return ret return None
def run_lintian_fixer( # noqa: C901 local_tree: WorkingTree, fixer: Fixer, committer: Optional[str] = None, update_changelog: Union[bool, Callable[[], bool]] = True, compat_release: Optional[str] = None, minimum_certainty: Optional[str] = None, trust_package: bool = False, allow_reformatting: bool = False, dirty_tracker=None, subpath: str = "", net_access: bool = True, opinionated: Optional[bool] = None, diligence: int = 0, timestamp: Optional[datetime] = None, basis_tree: Optional[Tree] = None, changes_by: str = "lintian-brush", ): """Run a lintian fixer on a tree. Args: local_tree: WorkingTree object basis_tree: Tree fixer: Fixer object to apply committer: Optional committer (name and email) update_changelog: Whether to add a new entry to the changelog compat_release: Minimum release that the package should be usable on (e.g. 'stable' or 'unstable') minimum_certainty: How certain the fixer should be about its changes. trust_package: Whether to run code from the package if necessary allow_reformatting: Whether to allow reformatting of changed files dirty_tracker: Optional object that can be used to tell if the tree has been changed. subpath: Path in tree to operate on net_access: Whether to allow accessing external services opinionated: Whether to be opinionated diligence: Level of diligence Returns: tuple with set of FixerResult, summary of the changes """ if basis_tree is None: basis_tree = local_tree.basis_tree() changelog_path = os.path.join(subpath, "debian/changelog") try: with local_tree.get_file(changelog_path) as f: cl = Changelog(f, max_blocks=1) except NoSuchFile: raise NotDebianPackage(local_tree, subpath) package = cl.package if cl.distributions == "UNRELEASED": current_version = cl.version else: current_version = cl.version increment_version(current_version) if compat_release is None: compat_release = "sid" if minimum_certainty is None: minimum_certainty = DEFAULT_MINIMUM_CERTAINTY logger.debug('Running fixer %r', fixer) try: result = fixer.run( local_tree.abspath(subpath), package=package, current_version=current_version, compat_release=compat_release, minimum_certainty=minimum_certainty, trust_package=trust_package, allow_reformatting=allow_reformatting, net_access=net_access, opinionated=opinionated, diligence=diligence, ) except BaseException: reset_tree(local_tree, basis_tree, subpath, dirty_tracker=dirty_tracker) raise if not certainty_sufficient(result.certainty, minimum_certainty): reset_tree(local_tree, basis_tree, subpath, dirty_tracker=dirty_tracker) raise NotCertainEnough( fixer, result.certainty, minimum_certainty, overridden_lintian_issues=result.overridden_lintian_issues) specific_files: Optional[List[str]] if dirty_tracker: relpaths = dirty_tracker.relpaths() # Sort paths so that directories get added before the files they # contain (on VCSes where it matters) local_tree.add( [ p for p in sorted(relpaths) if local_tree.has_filename(p) and not local_tree.is_ignored(p) ] ) specific_files = [p for p in relpaths if local_tree.is_versioned(p)] if not specific_files: raise NoChanges( fixer, "Script didn't make any changes", result.overridden_lintian_issues) else: local_tree.smart_add([local_tree.abspath(subpath)]) specific_files = [subpath] if subpath else None if local_tree.supports_setting_file_ids(): RenameMap.guess_renames(basis_tree, local_tree, dry_run=False) changes = list( local_tree.iter_changes( basis_tree, specific_files=specific_files, want_unversioned=False, require_versioned=True, ) ) if len(local_tree.get_parent_ids()) <= 1 and not changes: raise NoChanges( fixer, "Script didn't make any changes", result.overridden_lintian_issues) if not result.description: raise DescriptionMissing(fixer) lines = result.description.splitlines() summary = lines[0] details = list(itertools.takewhile(lambda line: line, lines[1:])) # If there are upstream changes in a non-native package, perhaps # export them to debian/patches if has_non_debian_changes(changes, subpath) and current_version.debian_revision: try: patch_name, specific_files = _upstream_changes_to_patch( local_tree, basis_tree, dirty_tracker, subpath, result.patch_name or fixer.name, result.description, timestamp=timestamp, ) except BaseException: reset_tree(local_tree, basis_tree, subpath, dirty_tracker=dirty_tracker) raise summary = "Add patch %s: %s" % (patch_name, summary) if only_changes_last_changelog_block( local_tree, basis_tree, changelog_path, changes ): # If the script only changed the last entry in the changelog, # don't update the changelog update_changelog = False if callable(update_changelog): update_changelog = update_changelog() if update_changelog: from .changelog import add_changelog_entry add_changelog_entry(local_tree, changelog_path, [summary] + details) if specific_files: specific_files.append(changelog_path) description = result.description + "\n" description += "\n" description += "Changes-By: %s\n" % changes_by for tag in result.fixed_lintian_tags: description += "Fixes: lintian: %s\n" % tag description += "See-also: https://lintian.debian.org/tags/%s.html\n" % tag if committer is None: committer = get_committer(local_tree) revid = local_tree.commit( description, allow_pointless=False, reporter=NullCommitReporter(), committer=committer, specific_files=specific_files, ) result.revision_id = revid # TODO(jelmer): Support running sbuild & verify lintian warning is gone? return result, summary
def scrub_obsolete(wt: WorkingTree, subpath: str, compat_release: str, upgrade_release: str, update_changelog=None, allow_reformatting: bool = False) -> ScrubObsoleteResult: """Scrub obsolete entries. """ if control_files_in_root(wt, subpath): debian_path = subpath else: debian_path = os.path.join(subpath, 'debian') result = _scrub_obsolete(wt, debian_path, compat_release, upgrade_release, allow_reformatting) if not result: return result specific_files = list(result.specific_files) summary = result.itemized() changelog_path = os.path.join(debian_path, "changelog") if update_changelog is None: from .detect_gbp_dch import guess_update_changelog from debian.changelog import Changelog with wt.get_file(changelog_path) as f: cl = Changelog(f, max_blocks=1) dch_guess = guess_update_changelog(wt, debian_path, cl) if dch_guess: update_changelog = dch_guess.update_changelog _note_changelog_policy(update_changelog, dch_guess.explanation) result.changelog_behaviour = dch_guess else: # Assume we should update changelog update_changelog = True result.changelog_behaviour = None if update_changelog: lines = [] for release, entries in summary.items(): lines.append("Remove constraints unnecessary since %s:" % release) lines.extend(["+ " + line for line in entries]) add_changelog_entry(wt, changelog_path, lines) specific_files.append(changelog_path) lines = [] for release, entries in summary.items(): lines.extend(["Remove constraints unnecessary since %s" % release, ""]) lines.extend(["* " + line for line in entries]) lines.extend(["", "Changes-By: deb-scrub-obsolete"]) committer = get_committer(wt) try: wt.commit( specific_files=specific_files, message="\n".join(lines), allow_pointless=False, reporter=NullCommitReporter(), committer=committer, ) except PointlessCommit: pass return result