~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/version_info_formats/__init__.py

  • Committer: Alexander Belchenko
  • Date: 2006-07-30 16:43:12 UTC
  • mto: (1711.2.111 jam-integration)
  • mto: This revision was merged to the branch mainline in revision 1906.
  • Revision ID: bialix@ukr.net-20060730164312-b025fd3ff0cee59e
rename  gpl.txt => COPYING.txt

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006 Canonical Ltd
2
 
#
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.
7
 
#
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.
12
 
#
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
 
 
17
 
"""Routines for extracting all version information from a bzr branch."""
18
 
 
19
 
import time
20
 
 
21
 
from bzrlib.osutils import local_time_offset, format_date
22
 
from bzrlib import registry
23
 
 
24
 
 
25
 
def create_date_str(timestamp=None, offset=None):
26
 
    """Just a wrapper around format_date to provide the right format.
27
 
 
28
 
    We don't want to use '%a' in the time string, because it is locale
29
 
    dependant. We also want to force timezone original, and show_offset
30
 
 
31
 
    Without parameters this function yields the current date in the local
32
 
    time zone.
33
 
    """
34
 
    if timestamp is None and offset is None:
35
 
        timestamp = time.time()
36
 
        offset = local_time_offset()
37
 
    return format_date(timestamp, offset, date_fmt='%Y-%m-%d %H:%M:%S',
38
 
                       timezone='original', show_offset=True)
39
 
 
40
 
 
41
 
class VersionInfoBuilder(object):
42
 
    """A class which lets you build up information about a revision."""
43
 
 
44
 
    def __init__(self, branch, working_tree=None,
45
 
                check_for_clean=False,
46
 
                include_revision_history=False,
47
 
                include_file_revisions=False,
48
 
                template=None):
49
 
        """Build up information about the given branch.
50
 
        If working_tree is given, it can be checked for changes.
51
 
 
52
 
        :param branch: The branch to work on
53
 
        :param working_tree: If supplied, preferentially check
54
 
            the working tree for changes.
55
 
        :param check_for_clean: If False, we will skip the expense
56
 
            of looking for changes.
57
 
        :param include_revision_history: If True, the output
58
 
            will include the full mainline revision history, including
59
 
            date and message
60
 
        :param include_file_revisions: The output should
61
 
            include the explicit last-changed revision for each file.
62
 
        :param template: Template for the output formatting, not used by
63
 
            all builders.
64
 
        """
65
 
        self._branch = branch
66
 
        self._working_tree = working_tree
67
 
        self._check = check_for_clean
68
 
        self._include_history = include_revision_history
69
 
        self._include_file_revs = include_file_revisions
70
 
        self._template = template
71
 
 
72
 
        self._clean = None
73
 
        self._file_revisions = {}
74
 
        self._revision_history_info= []
75
 
 
76
 
    def _extract_file_revisions(self):
77
 
        """Extract the working revisions for all files"""
78
 
 
79
 
        # Things seem clean if we never look :)
80
 
        self._clean = True
81
 
 
82
 
        if self._working_tree is not None:
83
 
            basis_tree = self._working_tree.basis_tree()
84
 
            # TODO: jam 20070215 The working tree should actually be locked at
85
 
            #       a higher level, but this will do for now.
86
 
            self._working_tree.lock_read()
87
 
        else:
88
 
            basis_tree = self._branch.basis_tree()
89
 
 
90
 
        basis_tree.lock_read()
91
 
        try:
92
 
            # Build up the list from the basis inventory
93
 
            for info in basis_tree.list_files(include_root=True):
94
 
                self._file_revisions[info[0]] = info[-1].revision
95
 
 
96
 
            if not self._check or self._working_tree is None:
97
 
                return
98
 
 
99
 
            delta = self._working_tree.changes_from(basis_tree,
100
 
                                                    include_root=True)
101
 
 
102
 
            # Using a 2-pass algorithm for renames. This is because you might have
103
 
            # renamed something out of the way, and then created a new file
104
 
            # in which case we would rather see the new marker
105
 
            # Or you might have removed the target, and then renamed
106
 
            # in which case we would rather see the renamed marker
107
 
            for (old_path, new_path, file_id,
108
 
                 kind, text_mod, meta_mod) in delta.renamed:
109
 
                self._clean = False
110
 
                self._file_revisions[old_path] = u'renamed to %s' % (new_path,)
111
 
            for path, file_id, kind in delta.removed:
112
 
                self._clean = False
113
 
                self._file_revisions[path] = 'removed'
114
 
            for path, file_id, kind in delta.added:
115
 
                self._clean = False
116
 
                self._file_revisions[path] = 'new'
117
 
            for (old_path, new_path, file_id,
118
 
                 kind, text_mod, meta_mod) in delta.renamed:
119
 
                self._clean = False
120
 
                self._file_revisions[new_path] = u'renamed from %s' % (old_path,)
121
 
            for path, file_id, kind, text_mod, meta_mod in delta.modified:
122
 
                self._clean = False
123
 
                self._file_revisions[path] = 'modified'
124
 
 
125
 
            for path in self._working_tree.unknowns():
126
 
                self._clean = False
127
 
                self._file_revisions[path] = 'unversioned'
128
 
        finally:
129
 
            basis_tree.unlock()
130
 
            if self._working_tree is not None:
131
 
                self._working_tree.unlock()
132
 
 
133
 
    def _extract_revision_history(self):
134
 
        """Find the messages for all revisions in history."""
135
 
 
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]
144
 
 
145
 
        repository =  self._branch.repository
146
 
        repository.lock_read()
147
 
        try:
148
 
            for revision_id in rev_hist:
149
 
                rev = repository.get_revision(revision_id)
150
 
                self._revision_history_info.append(
151
 
                    (rev.revision_id, rev.message,
152
 
                     rev.timestamp, rev.timezone))
153
 
        finally:
154
 
            repository.unlock()
155
 
 
156
 
    def _get_revision_id(self):
157
 
        """Get the revision id we are working on."""
158
 
        if self._working_tree is not None:
159
 
            return self._working_tree.last_revision()
160
 
        return self._branch.last_revision()
161
 
 
162
 
    def generate(self, to_file):
163
 
        """Output the version information to the supplied file.
164
 
 
165
 
        :param to_file: The file to write the stream to. The output
166
 
                will already be encoded, so to_file should not try
167
 
                to change encodings.
168
 
        :return: None
169
 
        """
170
 
        raise NotImplementedError(VersionInfoBuilder.generate)
171
 
 
172
 
 
173
 
format_registry = registry.Registry()
174
 
 
175
 
 
176
 
format_registry.register_lazy(
177
 
    'rio',
178
 
    'bzrlib.version_info_formats.format_rio',
179
 
    'RioVersionInfoBuilder',
180
 
    'Version info in RIO (simple text) format (default).')
181
 
format_registry.default_key = 'rio'
182
 
format_registry.register_lazy(
183
 
    'python',
184
 
    'bzrlib.version_info_formats.format_python',
185
 
    'PythonVersionInfoBuilder',
186
 
    'Version info in Python format.')
187
 
format_registry.register_lazy(
188
 
    'custom',
189
 
    'bzrlib.version_info_formats.format_custom',
190
 
    'CustomVersionInfoBuilder',
191
 
    'Version info in Custom template-based format.')