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