17
17
"""Routines for extracting all version information from a bzr branch."""
19
from __future__ import absolute_import
21
23
from bzrlib.osutils import local_time_offset, format_date
22
from bzrlib import registry
26
revision as _mod_revision,
25
30
def create_date_str(timestamp=None, offset=None):
45
50
check_for_clean=False,
46
51
include_revision_history=False,
47
52
include_file_revisions=False,
49
55
"""Build up information about the given branch.
50
56
If working_tree is given, it can be checked for changes.
61
67
include the explicit last-changed revision for each file.
62
68
:param template: Template for the output formatting, not used by
70
:param revision_id: Revision id to print version for (optional)
65
72
self._branch = branch
66
self._working_tree = working_tree
67
73
self._check = check_for_clean
68
74
self._include_history = include_revision_history
69
75
self._include_file_revs = include_file_revisions
73
79
self._file_revisions = {}
74
self._revision_history_info= []
80
self._revision_id = revision_id
82
if self._revision_id is None:
83
self._tree = working_tree
84
self._working_tree = working_tree
86
self._tree = self._branch.repository.revision_tree(self._revision_id)
87
# the working tree is not relevant if an explicit revision was specified
88
self._working_tree = None
76
90
def _extract_file_revisions(self):
77
91
"""Extract the working revisions for all files"""
79
93
# Things seem clean if we never look :)
82
if self._working_tree is not None:
96
if self._working_tree is self._tree:
83
97
basis_tree = self._working_tree.basis_tree()
84
98
# TODO: jam 20070215 The working tree should actually be locked at
85
99
# a higher level, but this will do for now.
86
100
self._working_tree.lock_read()
88
basis_tree = self._branch.basis_tree()
102
basis_tree = self._branch.repository.revision_tree(self._revision_id)
90
104
basis_tree.lock_read()
93
107
for info in basis_tree.list_files(include_root=True):
94
108
self._file_revisions[info[0]] = info[-1].revision
96
if not self._check or self._working_tree is None:
110
if not self._check or self._working_tree is not self._tree:
99
113
delta = self._working_tree.changes_from(basis_tree,
130
144
if self._working_tree is not None:
131
145
self._working_tree.unlock()
133
def _extract_revision_history(self):
147
def _iter_revision_history(self):
134
148
"""Find the messages for all revisions in history."""
136
# Unfortunately, there is no WorkingTree.revision_history
137
rev_hist = self._branch.revision_history()
138
if self._working_tree is not None:
139
last_rev = self._working_tree.last_revision()
140
if last_rev not in rev_hist:
141
raise AssertionError(
142
"Working Tree's last revision not in branch.revision_history")
143
rev_hist = rev_hist[:rev_hist.index(last_rev)+1]
150
last_rev = self._get_revision_id()
145
152
repository = self._branch.repository
146
153
repository.lock_read()
148
for revision_id in rev_hist:
155
graph = repository.get_graph()
156
revhistory = list(graph.iter_lefthand_ancestry(
157
last_rev, [_mod_revision.NULL_REVISION]))
158
for revision_id in reversed(revhistory):
149
159
rev = repository.get_revision(revision_id)
150
self._revision_history_info.append(
151
(rev.revision_id, rev.message,
152
rev.timestamp, rev.timezone))
160
yield (rev.revision_id, rev.message,
161
rev.timestamp, rev.timezone)
154
163
repository.unlock()
156
165
def _get_revision_id(self):
157
166
"""Get the revision id we are working on."""
167
if self._revision_id is not None:
168
return self._revision_id
158
169
if self._working_tree is not None:
159
170
return self._working_tree.last_revision()
160
171
return self._branch.last_revision()