def move_upstream_changes_to_patch( local_tree: WorkingTree, basis_tree: Tree, subpath: str, patch_name: str, description: str, dirty_tracker=None, timestamp: Optional[datetime] = None, ) -> Tuple[List[str], str]: """Move upstream changes to patch. Args: local_tree: local tree subpath: subpath patch_name: Suggested patch name description: Description dirty_tracker: Dirty tracker """ if timestamp is None: timestamp = datetime.now() diff = BytesIO() show_diff_trees(basis_tree, local_tree, diff) reset_tree(local_tree, basis_tree, subpath, dirty_tracker) header = Message() lines = description.splitlines() # See https://dep-team.pages.debian.net/deps/dep3/ for fields. header["Description"] = (lines[0] + "\n" + "\n".join([(" " + line) if line else " ." for line in lines[1:]])) header["Origin"] = "other" header["Last-Update"] = timestamp.strftime("%Y-%m-%d") patches_directory = tree_patches_directory(local_tree, subpath) patchname = add_patch( local_tree, os.path.join(subpath, patches_directory), patch_name, diff.getvalue(), header, ) specific_files = [ os.path.join(subpath, patches_directory), os.path.join(subpath, patches_directory, "series"), os.path.join(subpath, patches_directory, patchname), ] local_tree.add(specific_files) return specific_files, patchname
def modify_working_tree(self, tree): if 0: tree = WorkingTree() # RJLRJL: patched out renames as calls seem to be insoluble # and related to a problem with finding the id vs rel_path tree.merge_from_branch(self.branch_tree.branch, b'rev-b') self.build_tree_contents([ ('trunk/added', b''), ('trunk/addedmissing', b''), ('trunk/modified', b'new'), ('trunk/unversioned', b''), ]) tree.add(['added'], [b'added-id']) tree.add(['addedmissing'], [b'addedmissing-id']) # RJLRJL These are the problem omes # def rename_one(self, from_rel, to_rel, after=False): # """Rename one file. # This can change the directory or the filename or both. # Second, it can # only change the file_id without touching any physical file. # rename_one uses the second mode if 'after == True' and 'to_rel' is # either not versioned or newly added, and present in the working tree. # rename_one uses the second mode if 'after == False' and 'from_rel' is # versioned but no longer in the working tree, and 'to_rel' is not # versioned but present in the working tree. # rename_one uses the first mode if 'after == False' and 'from_rel' is # versioned and present in the working tree, and 'to_rel' is not # versioned and not present in the working tree. # Everything else results in an error. # """ print('\n***Performing rename_one', type(tree)) tree.rename_one('renamed', 'renamed1') print('\n*** doing move') tree.move(('moved', ), 'dir') print('\n and move and rename') tree.rename_one('movedandrenamed', 'movedandrenamed1') print('\n and last') tree.move(('movedandrenamed1', ), 'dir') # RJL tree.remove(('removed', )) os.remove('trunk/missing') os.remove('trunk/addedmissing') print('\n --- WARNING BYPASS ---') # RJLRJL Bypassed just now # # test for https://bugs.launchpad.net/qbrz/+bug/538753 # # must sort before trunk/dir # self.build_tree(['trunk/a-newdir/']) # self.build_tree_contents([('trunk/a-newdir/newdirchild', b'')]) # tree.add(['a-newdir'], [b'a-newdir-id']) # tree.add(['a-newdir/newdirchild'], [b'newdirchild-id']) # # manuly add conflicts for files that don't exist # # See https://bugs.launchpad.net/qbrz/+bug/528548 # tree.add_conflicts([TextConflict('nofileconflict')]) # RJLRJL print('modify_working_tree done')
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