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): | 
| 1385
by Martin Pool - simple weave-based annotate code (not complete) | 42 | if to_file is None: | 
| 43 | to_file = sys.stdout | |
| 1185.16.53
by Martin Pool - annotate improvements from Goffreddo, with extra bug fixes and tests | 44 | |
| 2831.3.1
by Ian Clatworthy code cleanups for annotate.py | 45 |     # 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 | 46 | last_rev_id = None | 
| 47 | if show_ids: | |
| 2831.3.1
by Ian Clatworthy code cleanups for annotate.py | 48 | 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 | 49 | max_origin_len = max(len(origin) for origin, text in annotations) | 
| 50 | for origin, text in annotations: | |
| 51 | if full or last_rev_id != origin: | |
| 52 | this = origin | |
| 53 | else: | |
| 54 | this = '' | |
| 55 | to_file.write('%*s | %s' % (max_origin_len, this, text)) | |
| 56 | last_rev_id = origin | |
| 57 |         return
 | |
| 58 | ||
| 2831.3.1
by Ian Clatworthy code cleanups for annotate.py | 59 |     # Calculate the lengths of the various columns
 | 
| 1185.33.39
by Martin Pool [patch] annotate --long (robey pointer) | 60 | 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 | 61 | if len(annotation) == 0: | 
| 2182.3.4
by John Arbash Meinel add show-ids and test that nearby areas are collapsed without full | 62 | 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 | 63 | else: | 
| 2182.3.8
by John Arbash Meinel Some cleanup to make annotate.py < 79 chars wide. | 64 | 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. | 65 | 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 | 66 | 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 | 67 | if not verbose: | 
| 2182.3.7
by John Arbash Meinel Cleanup and add blackbox tests for annotate. | 68 | max_revno_len = min(max_revno_len, 12) | 
| 69 | max_revno_len = max(max_revno_len, 3) | |
| 2182.3.2
by John Arbash Meinel Use shortened revnos unless --long is supplied | 70 | |
| 2831.3.1
by Ian Clatworthy code cleanups for annotate.py | 71 |     # Output the annotations
 | 
| 72 | prevanno = '' | |
| 73 | encoding = getattr(to_file, 'encoding', None) or \ | |
| 74 | osutils.get_terminal_encoding() | |
| 2182.3.4
by John Arbash Meinel add show-ids and test that nearby areas are collapsed without full | 75 | 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 | 76 | if verbose: | 
| 77 | anno = '%-*s %-*s %8s ' % (max_revno_len, revno_str, | |
| 78 | max_origin_len, author, date_str) | |
| 1185.16.53
by Martin Pool - annotate improvements from Goffreddo, with extra bug fixes and tests | 79 | else: | 
| 2182.3.9
by John Arbash Meinel Faster annotate --show-ids. No need to pull the history or the revision info | 80 | if len(revno_str) > max_revno_len: | 
| 81 | revno_str = revno_str[:max_revno_len-1] + '>' | |
| 82 | anno = "%-*s %-7s " % (max_revno_len, revno_str, author[:7]) | |
| 2831.3.1
by Ian Clatworthy code cleanups for annotate.py | 83 | if anno.lstrip() == "" and full: | 
| 84 | anno = prevanno | |
| 2593.1.1
by Adeodato Simó Improve annotate to prevent unicode exceptions in certain situations. | 85 | try: | 
| 86 | to_file.write(anno) | |
| 87 | except UnicodeEncodeError: | |
| 2593.1.4
by Adeodato Simó Add comment from John to the try/except block. | 88 |             # cmd_annotate should be passing in an 'exact' object, which means
 | 
| 89 |             # we have a direct handle to sys.stdout or equivalent. It may not
 | |
| 90 |             # be able to handle the exact Unicode characters, but 'annotate' is
 | |
| 91 |             # a user function (non-scripting), so shouldn't die because of
 | |
| 92 |             # unrepresentable annotation characters. So encode using 'replace',
 | |
| 93 |             # and write them again.
 | |
| 2593.1.3
by Adeodato Simó Cope with to_file.encoding being None or not present. | 94 | to_file.write(anno.encode(encoding, 'replace')) | 
| 2593.1.1
by Adeodato Simó Improve annotate to prevent unicode exceptions in certain situations. | 95 | print >>to_file, '| %s' % (text,) | 
| 2831.3.1
by Ian Clatworthy code cleanups for annotate.py | 96 | prevanno = anno | 
| 97 | ||
| 98 | ||
| 99 | def _annotations(repo, file_id, rev_id): | |
| 100 | """Return the list of (origin,text) for a revision of a file in a repository.""" | |
| 101 | w = repo.weave_store.get_weave(file_id, repo.get_transaction()) | |
| 102 | return list(w.annotate_iter(rev_id)) | |
| 1185.16.53
by Martin Pool - annotate improvements from Goffreddo, with extra bug fixes and tests | 103 | |
| 2182.3.10
by John Arbash Meinel minor cleanup. | 104 | |
| 2245.3.1
by John Arbash Meinel bzr annotate should use Branch's dotted revnos. | 105 | def _annotate_file(branch, rev_id, file_id): | 
| 2182.3.10
by John Arbash Meinel minor cleanup. | 106 | """Yield the origins for each line of a file. | 
| 107 | ||
| 2671.5.3
by Lukáš Lalinsky Use the author name in annotate. | 108 |     This includes detailed information, such as the author name, and
 | 
| 2182.3.10
by John Arbash Meinel minor cleanup. | 109 |     date string for the commit, rather than just the revision id.
 | 
| 110 |     """
 | |
| 2418.5.8
by John Arbash Meinel Update annotate.py to use the new helper function. | 111 | revision_id_to_revno = branch.get_revision_id_to_revno_map() | 
| 2831.3.1
by Ian Clatworthy code cleanups for annotate.py | 112 | annotations = _annotations(branch.repository, file_id, rev_id) | 
| 1385
by Martin Pool - simple weave-based annotate code (not complete) | 113 | last_origin = None | 
| 1551.9.6
by Aaron Bentley Optimize annotate by retrieving all revisions at once | 114 | revision_ids = set(o for o, t in annotations) | 
| 115 | revision_ids = [o for o in revision_ids if | |
| 116 | branch.repository.has_revision(o)] | |
| 117 | revisions = dict((r.revision_id, r) for r in | |
| 118 | branch.repository.get_revisions(revision_ids)) | |
| 119 | for origin, text in annotations: | |
| 1385
by Martin Pool - simple weave-based annotate code (not complete) | 120 | text = text.rstrip('\r\n') | 
| 121 | if origin == last_origin: | |
| 1185.16.53
by Martin Pool - annotate improvements from Goffreddo, with extra bug fixes and tests | 122 | (revno_str, author, date_str) = ('','','') | 
| 1385
by Martin Pool - simple weave-based annotate code (not complete) | 123 | else: | 
| 124 | last_origin = origin | |
| 1551.9.6
by Aaron Bentley Optimize annotate by retrieving all revisions at once | 125 | if origin not in revisions: | 
| 1185.16.53
by Martin Pool - annotate improvements from Goffreddo, with extra bug fixes and tests | 126 | (revno_str, author, date_str) = ('?','?','?') | 
| 1185.16.1
by Martin Pool - update annotate for new branch api | 127 | else: | 
| 2182.3.1
by John Arbash Meinel Annotate now shows dotted revnos instead of plain revnos. | 128 | revno_str = '.'.join(str(i) for i in | 
| 129 | revision_id_to_revno[origin]) | |
| 1551.9.6
by Aaron Bentley Optimize annotate by retrieving all revisions at once | 130 | rev = revisions[origin] | 
| 1185.16.32
by Martin Pool - add a basic annotate built-in command | 131 | tz = rev.timezone or 0 | 
| 2182.3.8
by John Arbash Meinel Some cleanup to make annotate.py < 79 chars wide. | 132 | date_str = time.strftime('%Y%m%d', | 
| 1185.16.32
by Martin Pool - add a basic annotate built-in command | 133 | time.gmtime(rev.timestamp + tz)) | 
| 134 |             # a lazy way to get something like the email address
 | |
| 135 |             # 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. | 136 | author = rev.get_apparent_author() | 
| 1185.16.53
by Martin Pool - annotate improvements from Goffreddo, with extra bug fixes and tests | 137 | try: | 
| 138 | author = extract_email_address(author) | |
| 2182.3.1
by John Arbash Meinel Annotate now shows dotted revnos instead of plain revnos. | 139 | except errors.NoEmailInUsername: | 
| 1185.16.53
by Martin Pool - annotate improvements from Goffreddo, with extra bug fixes and tests | 140 | pass # use the whole name | 
| 1563.2.1
by Robert Collins Merge in a variation of the versionedfile api from versioned-file. | 141 | yield (revno_str, author, date_str, origin, text) | 
| 1551.9.16
by Aaron Bentley Implement Tree.annotate_iter for RevisionTree and WorkingTree | 142 | |
| 143 | ||
| 2770.1.5
by Aaron Bentley Clean up docs, test matching blocks for reannotate | 144 | def reannotate(parents_lines, new_lines, new_revision_id, | 
| 145 | _left_matching_blocks=None): | |
| 1551.9.16
by Aaron Bentley Implement Tree.annotate_iter for RevisionTree and WorkingTree | 146 | """Create a new annotated version from new lines and parent annotations. | 
| 147 |     
 | |
| 1551.9.17
by Aaron Bentley Annotate for working trees across all parents | 148 |     :param parents_lines: List of annotated lines for all parents
 | 
| 1551.9.16
by Aaron Bentley Implement Tree.annotate_iter for RevisionTree and WorkingTree | 149 |     :param new_lines: The un-annotated new lines
 | 
| 150 |     :param new_revision_id: The revision-id to associate with new lines
 | |
| 151 |         (will often be CURRENT_REVISION)
 | |
| 2770.1.5
by Aaron Bentley Clean up docs, test matching blocks for reannotate | 152 |     :param left_matching_blocks: a hint about which areas are common
 | 
| 153 |         between the text and its left-hand-parent.  The format is
 | |
| 154 |         the SequenceMatcher.get_matching_blocks format.
 | |
| 1551.9.16
by Aaron Bentley Implement Tree.annotate_iter for RevisionTree and WorkingTree | 155 |     """
 | 
| 2770.1.1
by Aaron Bentley Initial implmentation of plain knit annotation | 156 | if len(parents_lines) == 0: | 
| 157 | for line in new_lines: | |
| 158 | yield new_revision_id, line | |
| 159 | elif len(parents_lines) == 1: | |
| 2770.1.4
by Aaron Bentley Further optimize annotation, using existing matching blocks | 160 | 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 | 161 | _left_matching_blocks): | 
| 1551.9.17
by Aaron Bentley Annotate for working trees across all parents | 162 | yield data | 
| 163 | else: | |
| 2770.1.5
by Aaron Bentley Clean up docs, test matching blocks for reannotate | 164 | block_list = [_left_matching_blocks] + [None] * len(parents_lines) | 
| 2770.1.4
by Aaron Bentley Further optimize annotation, using existing matching blocks | 165 | reannotations = [list(_reannotate(p, new_lines, new_revision_id, b)) | 
| 166 | for p, b in zip(parents_lines, block_list)] | |
| 1551.9.17
by Aaron Bentley Annotate for working trees across all parents | 167 | for annos in zip(*reannotations): | 
| 168 | origins = set(a for a, l in annos) | |
| 169 | line = annos[0][1] | |
| 170 | if len(origins) == 1: | |
| 171 | yield iter(origins).next(), line | |
| 172 | elif len(origins) == 2 and new_revision_id in origins: | |
| 173 | yield (x for x in origins if x != new_revision_id).next(), line | |
| 174 | else: | |
| 175 | yield new_revision_id, line | |
| 1551.9.18
by Aaron Bentley Updates from review comments | 176 | |
| 1551.9.17
by Aaron Bentley Annotate for working trees across all parents | 177 | |
| 2770.1.5
by Aaron Bentley Clean up docs, test matching blocks for reannotate | 178 | def _reannotate(parent_lines, new_lines, new_revision_id, | 
| 179 | matching_blocks=None): | |
| 1551.9.16
by Aaron Bentley Implement Tree.annotate_iter for RevisionTree and WorkingTree | 180 | new_cur = 0 | 
| 2770.1.5
by Aaron Bentley Clean up docs, test matching blocks for reannotate | 181 | if matching_blocks is None: | 
| 2831.3.1
by Ian Clatworthy code cleanups for annotate.py | 182 | plain_parent_lines = [l for r, l in parent_lines] | 
| 183 | matcher = patiencediff.PatienceSequenceMatcher(None, | |
| 184 | plain_parent_lines, new_lines) | |
| 2770.1.5
by Aaron Bentley Clean up docs, test matching blocks for reannotate | 185 | matching_blocks = matcher.get_matching_blocks() | 
| 186 | for i, j, n in matching_blocks: | |
| 1551.9.16
by Aaron Bentley Implement Tree.annotate_iter for RevisionTree and WorkingTree | 187 | for line in new_lines[new_cur:j]: | 
| 188 | yield new_revision_id, line | |
| 189 | for data in parent_lines[i:i+n]: | |
| 1551.9.18
by Aaron Bentley Updates from review comments | 190 | yield data | 
| 1551.9.16
by Aaron Bentley Implement Tree.annotate_iter for RevisionTree and WorkingTree | 191 | new_cur = j + n |