bzr branch
http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
| 2245.3.2
by John Arbash Meinel Cleanup according to Wouter's suggestions. | 1 | # Copyright (C) 2004, 2005, 2006, 2007 Canonical Ltd
 | 
| 2052.3.1
by John Arbash Meinel Add tests to cleanup the copyright of all source files | 2 | #
 | 
| 1385
by Martin Pool - simple weave-based annotate code (not complete) | 3 | # This program is free software; you can redistribute it and/or modify
 | 
| 4 | # it under the terms of the GNU General Public License as published by
 | |
| 5 | # the Free Software Foundation; either version 2 of the License, or
 | |
| 6 | # (at your option) any later version.
 | |
| 2052.3.1
by John Arbash Meinel Add tests to cleanup the copyright of all source files | 7 | #
 | 
| 1385
by Martin Pool - simple weave-based annotate code (not complete) | 8 | # This program is distributed in the hope that it will be useful,
 | 
| 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
| 11 | # GNU General Public License for more details.
 | |
| 2052.3.1
by John Arbash Meinel Add tests to cleanup the copyright of all source files | 12 | #
 | 
| 1385
by Martin Pool - simple weave-based annotate code (not complete) | 13 | # You should have received a copy of the GNU General Public License
 | 
| 14 | # along with this program; if not, write to the Free Software
 | |
| 15 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | |
| 16 | ||
| 17 | """File annotate based on weave storage"""
 | |
| 18 | ||
| 1185.16.8
by Martin Pool doc | 19 | # TODO: Choice of more or less verbose formats:
 | 
| 20 | # 
 | |
| 21 | # interposed: show more details between blocks of modified lines
 | |
| 22 | ||
| 23 | # TODO: Show which revision caused a line to merge into the parent
 | |
| 24 | ||
| 1185.16.57
by Martin Pool [merge] from aaron | 25 | # TODO: perhaps abbreviate timescales depending on how recent they are
 | 
| 26 | # e.g. "3:12 Tue", "13 Oct", "Oct 2005", etc.  
 | |
| 27 | ||
| 1385
by Martin Pool - simple weave-based annotate code (not complete) | 28 | import sys | 
| 1185.16.1
by Martin Pool - update annotate for new branch api | 29 | import time | 
| 1385
by Martin Pool - simple weave-based annotate code (not complete) | 30 | |
| 2182.3.1
by John Arbash Meinel Annotate now shows dotted revnos instead of plain revnos. | 31 | from bzrlib import ( | 
| 32 | errors, | |
| 2593.1.3
by Adeodato Simó Cope with to_file.encoding being None or not present. | 33 | osutils, | 
| 1551.9.19
by Aaron Bentley Merge from bzr.dev | 34 | patiencediff, | 
| 2182.3.1
by John Arbash Meinel Annotate now shows dotted revnos instead of plain revnos. | 35 | tsort, | 
| 36 |     )
 | |
| 1185.16.53
by Martin Pool - annotate improvements from Goffreddo, with extra bug fixes and tests | 37 | from bzrlib.config import extract_email_address | 
| 38 | ||
| 39 | ||
| 40 | def annotate_file(branch, rev_id, file_id, verbose=False, full=False, | |
| 2182.3.1
by John Arbash Meinel Annotate now shows dotted revnos instead of plain revnos. | 41 | to_file=None, show_ids=False): | 
| 3010.1.1
by Robert Collins Lock the tree's used to test annotate_file, and add a docstring for annotate_file explaining its needs. | 42 | """Annotate file_id at revision rev_id in branch. | 
| 43 | ||
| 44 |     The branch should already be read_locked() when annotate_file is called.
 | |
| 45 | ||
| 46 |     :param branch: The branch to look for revision numbers and history from.
 | |
| 47 |     :param rev_id: The revision id to annotate.
 | |
| 48 |     :param file_id: The file_id to annotate.
 | |
| 49 |     :param verbose: Show all details rather than truncating to ensure
 | |
| 50 |         reasonable text width.
 | |
| 51 |     :param full: XXXX Not sure what this does.
 | |
| 52 |     :param to_file: The file to output the annotation to; if None stdout is
 | |
| 53 |         used.
 | |
| 54 |     :param show_ids: Show revision ids in the annotation output.
 | |
| 55 |     """
 | |
| 1385
by Martin Pool - simple weave-based annotate code (not complete) | 56 | if to_file is None: | 
| 57 | to_file = sys.stdout | |
| 1185.16.53
by Martin Pool - annotate improvements from Goffreddo, with extra bug fixes and tests | 58 | |
| 2831.3.1
by Ian Clatworthy code cleanups for annotate.py | 59 |     # Handle the show_ids case
 | 
| 2182.3.9
by John Arbash Meinel Faster annotate --show-ids. No need to pull the history or the revision info | 60 | last_rev_id = None | 
| 61 | if show_ids: | |
| 2831.3.1
by Ian Clatworthy code cleanups for annotate.py | 62 | annotations = _annotations(branch.repository, file_id, rev_id) | 
| 2182.3.9
by John Arbash Meinel Faster annotate --show-ids. No need to pull the history or the revision info | 63 | max_origin_len = max(len(origin) for origin, text in annotations) | 
| 64 | for origin, text in annotations: | |
| 65 | if full or last_rev_id != origin: | |
| 66 | this = origin | |
| 67 | else: | |
| 68 | this = '' | |
| 69 | to_file.write('%*s | %s' % (max_origin_len, this, text)) | |
| 70 | last_rev_id = origin | |
| 71 |         return
 | |
| 72 | ||
| 2831.3.1
by Ian Clatworthy code cleanups for annotate.py | 73 |     # Calculate the lengths of the various columns
 | 
| 1185.33.39
by Martin Pool [patch] annotate --long (robey pointer) | 74 | annotation = list(_annotate_file(branch, rev_id, file_id)) | 
| 2027.3.1
by John Arbash Meinel 'bzr annotate' shouldn't fail on an empty file: fix bug #56814 | 75 | if len(annotation) == 0: | 
| 2182.3.4
by John Arbash Meinel add show-ids and test that nearby areas are collapsed without full | 76 | max_origin_len = max_revno_len = max_revid_len = 0 | 
| 2027.3.1
by John Arbash Meinel 'bzr annotate' shouldn't fail on an empty file: fix bug #56814 | 77 | else: | 
| 2182.3.8
by John Arbash Meinel Some cleanup to make annotate.py < 79 chars wide. | 78 | max_origin_len = max(len(x[1]) for x in annotation) | 
| 2182.3.1
by John Arbash Meinel Annotate now shows dotted revnos instead of plain revnos. | 79 | max_revno_len = max(len(x[0]) for x in annotation) | 
| 2182.3.4
by John Arbash Meinel add show-ids and test that nearby areas are collapsed without full | 80 | max_revid_len = max(len(x[3]) for x in annotation) | 
| 2182.3.2
by John Arbash Meinel Use shortened revnos unless --long is supplied | 81 | if not verbose: | 
| 2182.3.7
by John Arbash Meinel Cleanup and add blackbox tests for annotate. | 82 | max_revno_len = min(max_revno_len, 12) | 
| 83 | max_revno_len = max(max_revno_len, 3) | |
| 2182.3.2
by John Arbash Meinel Use shortened revnos unless --long is supplied | 84 | |
| 2831.3.1
by Ian Clatworthy code cleanups for annotate.py | 85 |     # Output the annotations
 | 
| 86 | prevanno = '' | |
| 87 | encoding = getattr(to_file, 'encoding', None) or \ | |
| 88 | osutils.get_terminal_encoding() | |
| 2182.3.4
by John Arbash Meinel add show-ids and test that nearby areas are collapsed without full | 89 | for (revno_str, author, date_str, line_rev_id, text) in annotation: | 
| 2182.3.9
by John Arbash Meinel Faster annotate --show-ids. No need to pull the history or the revision info | 90 | if verbose: | 
| 91 | anno = '%-*s %-*s %8s ' % (max_revno_len, revno_str, | |
| 92 | max_origin_len, author, date_str) | |
| 1185.16.53
by Martin Pool - annotate improvements from Goffreddo, with extra bug fixes and tests | 93 | else: | 
| 2182.3.9
by John Arbash Meinel Faster annotate --show-ids. No need to pull the history or the revision info | 94 | if len(revno_str) > max_revno_len: | 
| 95 | revno_str = revno_str[:max_revno_len-1] + '>' | |
| 96 | anno = "%-*s %-7s " % (max_revno_len, revno_str, author[:7]) | |
| 2831.3.1
by Ian Clatworthy code cleanups for annotate.py | 97 | if anno.lstrip() == "" and full: | 
| 98 | anno = prevanno | |
| 2593.1.1
by Adeodato Simó Improve annotate to prevent unicode exceptions in certain situations. | 99 | try: | 
| 100 | to_file.write(anno) | |
| 101 | except UnicodeEncodeError: | |
| 2593.1.4
by Adeodato Simó Add comment from John to the try/except block. | 102 |             # cmd_annotate should be passing in an 'exact' object, which means
 | 
| 103 |             # we have a direct handle to sys.stdout or equivalent. It may not
 | |
| 104 |             # be able to handle the exact Unicode characters, but 'annotate' is
 | |
| 105 |             # a user function (non-scripting), so shouldn't die because of
 | |
| 106 |             # unrepresentable annotation characters. So encode using 'replace',
 | |
| 107 |             # and write them again.
 | |
| 2593.1.3
by Adeodato Simó Cope with to_file.encoding being None or not present. | 108 | to_file.write(anno.encode(encoding, 'replace')) | 
| 2911.6.1
by Blake Winton Change 'print >> f,'s to 'f.write('s. | 109 | to_file.write('| %s\n' % (text,)) | 
| 2831.3.1
by Ian Clatworthy code cleanups for annotate.py | 110 | prevanno = anno | 
| 111 | ||
| 112 | ||
| 113 | def _annotations(repo, file_id, rev_id): | |
| 114 | """Return the list of (origin,text) for a revision of a file in a repository.""" | |
| 115 | w = repo.weave_store.get_weave(file_id, repo.get_transaction()) | |
| 116 | return list(w.annotate_iter(rev_id)) | |
| 1185.16.53
by Martin Pool - annotate improvements from Goffreddo, with extra bug fixes and tests | 117 | |
| 2182.3.10
by John Arbash Meinel minor cleanup. | 118 | |
| 2245.3.1
by John Arbash Meinel bzr annotate should use Branch's dotted revnos. | 119 | def _annotate_file(branch, rev_id, file_id): | 
| 2182.3.10
by John Arbash Meinel minor cleanup. | 120 | """Yield the origins for each line of a file. | 
| 121 | ||
| 2671.5.3
by Lukáš Lalinsky Use the author name in annotate. | 122 |     This includes detailed information, such as the author name, and
 | 
| 2182.3.10
by John Arbash Meinel minor cleanup. | 123 |     date string for the commit, rather than just the revision id.
 | 
| 124 |     """
 | |
| 2418.5.8
by John Arbash Meinel Update annotate.py to use the new helper function. | 125 | revision_id_to_revno = branch.get_revision_id_to_revno_map() | 
| 2831.3.1
by Ian Clatworthy code cleanups for annotate.py | 126 | annotations = _annotations(branch.repository, file_id, rev_id) | 
| 1385
by Martin Pool - simple weave-based annotate code (not complete) | 127 | last_origin = None | 
| 1551.9.6
by Aaron Bentley Optimize annotate by retrieving all revisions at once | 128 | revision_ids = set(o for o, t in annotations) | 
| 129 | revision_ids = [o for o in revision_ids if | |
| 130 | branch.repository.has_revision(o)] | |
| 131 | revisions = dict((r.revision_id, r) for r in | |
| 132 | branch.repository.get_revisions(revision_ids)) | |
| 133 | for origin, text in annotations: | |
| 1385
by Martin Pool - simple weave-based annotate code (not complete) | 134 | text = text.rstrip('\r\n') | 
| 135 | if origin == last_origin: | |
| 1185.16.53
by Martin Pool - annotate improvements from Goffreddo, with extra bug fixes and tests | 136 | (revno_str, author, date_str) = ('','','') | 
| 1385
by Martin Pool - simple weave-based annotate code (not complete) | 137 | else: | 
| 138 | last_origin = origin | |
| 1551.9.6
by Aaron Bentley Optimize annotate by retrieving all revisions at once | 139 | if origin not in revisions: | 
| 1185.16.53
by Martin Pool - annotate improvements from Goffreddo, with extra bug fixes and tests | 140 | (revno_str, author, date_str) = ('?','?','?') | 
| 1185.16.1
by Martin Pool - update annotate for new branch api | 141 | else: | 
| 2182.3.1
by John Arbash Meinel Annotate now shows dotted revnos instead of plain revnos. | 142 | revno_str = '.'.join(str(i) for i in | 
| 143 | revision_id_to_revno[origin]) | |
| 1551.9.6
by Aaron Bentley Optimize annotate by retrieving all revisions at once | 144 | rev = revisions[origin] | 
| 1185.16.32
by Martin Pool - add a basic annotate built-in command | 145 | tz = rev.timezone or 0 | 
| 2182.3.8
by John Arbash Meinel Some cleanup to make annotate.py < 79 chars wide. | 146 | date_str = time.strftime('%Y%m%d', | 
| 1185.16.32
by Martin Pool - add a basic annotate built-in command | 147 | time.gmtime(rev.timestamp + tz)) | 
| 148 |             # a lazy way to get something like the email address
 | |
| 149 |             # TODO: Get real email address
 | |
| 2671.5.7
by Lukáš Lalinsky Rename get_author to get_apparent_author, revert the long log back to displaying the committer. | 150 | author = rev.get_apparent_author() | 
| 1185.16.53
by Martin Pool - annotate improvements from Goffreddo, with extra bug fixes and tests | 151 | try: | 
| 152 | author = extract_email_address(author) | |
| 2182.3.1
by John Arbash Meinel Annotate now shows dotted revnos instead of plain revnos. | 153 | except errors.NoEmailInUsername: | 
| 1185.16.53
by Martin Pool - annotate improvements from Goffreddo, with extra bug fixes and tests | 154 | pass # use the whole name | 
| 1563.2.1
by Robert Collins Merge in a variation of the versionedfile api from versioned-file. | 155 | yield (revno_str, author, date_str, origin, text) | 
| 1551.9.16
by Aaron Bentley Implement Tree.annotate_iter for RevisionTree and WorkingTree | 156 | |
| 157 | ||
| 2770.1.5
by Aaron Bentley Clean up docs, test matching blocks for reannotate | 158 | def reannotate(parents_lines, new_lines, new_revision_id, | 
| 159 | _left_matching_blocks=None): | |
| 1551.9.16
by Aaron Bentley Implement Tree.annotate_iter for RevisionTree and WorkingTree | 160 | """Create a new annotated version from new lines and parent annotations. | 
| 161 |     
 | |
| 1551.9.17
by Aaron Bentley Annotate for working trees across all parents | 162 |     :param parents_lines: List of annotated lines for all parents
 | 
| 1551.9.16
by Aaron Bentley Implement Tree.annotate_iter for RevisionTree and WorkingTree | 163 |     :param new_lines: The un-annotated new lines
 | 
| 164 |     :param new_revision_id: The revision-id to associate with new lines
 | |
| 165 |         (will often be CURRENT_REVISION)
 | |
| 2770.1.5
by Aaron Bentley Clean up docs, test matching blocks for reannotate | 166 |     :param left_matching_blocks: a hint about which areas are common
 | 
| 167 |         between the text and its left-hand-parent.  The format is
 | |
| 168 |         the SequenceMatcher.get_matching_blocks format.
 | |
| 1551.9.16
by Aaron Bentley Implement Tree.annotate_iter for RevisionTree and WorkingTree | 169 |     """
 | 
| 2770.1.1
by Aaron Bentley Initial implmentation of plain knit annotation | 170 | if len(parents_lines) == 0: | 
| 171 | for line in new_lines: | |
| 172 | yield new_revision_id, line | |
| 173 | elif len(parents_lines) == 1: | |
| 2770.1.4
by Aaron Bentley Further optimize annotation, using existing matching blocks | 174 | for data in _reannotate(parents_lines[0], new_lines, new_revision_id, | 
| 2770.1.5
by Aaron Bentley Clean up docs, test matching blocks for reannotate | 175 | _left_matching_blocks): | 
| 1551.9.17
by Aaron Bentley Annotate for working trees across all parents | 176 | yield data | 
| 177 | else: | |
| 2770.1.5
by Aaron Bentley Clean up docs, test matching blocks for reannotate | 178 | block_list = [_left_matching_blocks] + [None] * len(parents_lines) | 
| 2770.1.4
by Aaron Bentley Further optimize annotation, using existing matching blocks | 179 | reannotations = [list(_reannotate(p, new_lines, new_revision_id, b)) | 
| 180 | for p, b in zip(parents_lines, block_list)] | |
| 1551.9.17
by Aaron Bentley Annotate for working trees across all parents | 181 | for annos in zip(*reannotations): | 
| 182 | origins = set(a for a, l in annos) | |
| 183 | line = annos[0][1] | |
| 184 | if len(origins) == 1: | |
| 185 | yield iter(origins).next(), line | |
| 186 | elif len(origins) == 2 and new_revision_id in origins: | |
| 187 | yield (x for x in origins if x != new_revision_id).next(), line | |
| 188 | else: | |
| 189 | yield new_revision_id, line | |
| 1551.9.18
by Aaron Bentley Updates from review comments | 190 | |
| 1551.9.17
by Aaron Bentley Annotate for working trees across all parents | 191 | |
| 2770.1.5
by Aaron Bentley Clean up docs, test matching blocks for reannotate | 192 | def _reannotate(parent_lines, new_lines, new_revision_id, | 
| 193 | matching_blocks=None): | |
| 1551.9.16
by Aaron Bentley Implement Tree.annotate_iter for RevisionTree and WorkingTree | 194 | new_cur = 0 | 
| 2770.1.5
by Aaron Bentley Clean up docs, test matching blocks for reannotate | 195 | if matching_blocks is None: | 
| 2831.3.1
by Ian Clatworthy code cleanups for annotate.py | 196 | plain_parent_lines = [l for r, l in parent_lines] | 
| 197 | matcher = patiencediff.PatienceSequenceMatcher(None, | |
| 198 | plain_parent_lines, new_lines) | |
| 2770.1.5
by Aaron Bentley Clean up docs, test matching blocks for reannotate | 199 | matching_blocks = matcher.get_matching_blocks() | 
| 200 | for i, j, n in matching_blocks: | |
| 1551.9.16
by Aaron Bentley Implement Tree.annotate_iter for RevisionTree and WorkingTree | 201 | for line in new_lines[new_cur:j]: | 
| 202 | yield new_revision_id, line | |
| 203 | for data in parent_lines[i:i+n]: | |
| 1551.9.18
by Aaron Bentley Updates from review comments | 204 | yield data | 
| 1551.9.16
by Aaron Bentley Implement Tree.annotate_iter for RevisionTree and WorkingTree | 205 | new_cur = j + n |