~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/status.py

  • Committer: Vincent Ladeuil
  • Date: 2008-08-26 08:25:27 UTC
  • mto: (3668.1.1 trunk) (3703.1.1 trunk)
  • mto: This revision was merged to the branch mainline in revision 3669.
  • Revision ID: v.ladeuil+lp@free.fr-20080826082527-109yyxzc0u24oeel
Fix all calls to tempfile.mkdtemp to osutils.mkdtemp.

* bzrlib/transform.py:
(TransformPreview.__init__): Use osutils.mkdtemp instead of
tempfile.mkdtemp.

* bzrlib/tests/test_whitebox.py:
(MoreTests.test_relpath): Use osutils.mkdtemp instead of
tempfile.mkdtemp.

* bzrlib/tests/test_setup.py:
(TestSetup.test_build_and_install): Use osutils.mkdtemp instead of
tempfile.mkdtemp.

* bzrlib/tests/test_bundle.py:
(BundleTester.get_checkout): Use osutils.mkdtemp instead of
tempfile.mkdtemp.

* bzrlib/tests/blackbox/test_outside_wt.py:
(TestOutsideWT.test_cwd_log,
TestOutsideWT.test_diff_outside_tree): Use osutils.mkdtemp instead
of tempfile.mkdtemp.

* bzrlib/smart/repository.py:
(SmartServerRepositoryTarball._copy_to_tempdir): Use
osutils.mkdtemp instead of tempfile.mkdtemp.
(SmartServerRepositoryTarball._tarfile_response): Line too long.

* bzrlib/remote.py:
(RemoteRepository._copy_repository_tarball): Use osutils.mkdtemp
instead of tempfile.mkdtemp.

* bzrlib/osutils.py:
(_mac_mkdtemp): Add docstring.

* bzrlib/mail_client.py:
(ExternalMailClient.compose): Use osutils.mkdtemp instead of
tempfile.mkdtemp.

* bzrlib/diff.py:
(DiffFromTool.__init__): Use osutils.mkdtemp instead of
tempfile.mkdtemp.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
16
16
 
17
17
import sys
18
18
 
19
 
from bzrlib.delta import compare_trees
 
19
from bzrlib import (
 
20
    delta as _mod_delta,
 
21
    log,
 
22
    osutils,
 
23
    tree,
 
24
    tsort,
 
25
    revision as _mod_revision,
 
26
    )
20
27
from bzrlib.diff import _raise_if_nonexistent
21
28
import bzrlib.errors as errors
22
 
from bzrlib.log import line_log
23
29
from bzrlib.osutils import is_inside_any
24
30
from bzrlib.symbol_versioning import (deprecated_function,
25
 
        zero_eight,
26
31
        )
 
32
from bzrlib.trace import warning
27
33
 
28
34
# TODO: when showing single-line logs, truncate to the width of the terminal
29
35
# if known, but only if really going to the terminal (not into a file)
30
36
 
31
37
 
32
 
@deprecated_function(zero_eight)
33
 
def show_status(branch, show_unchanged=None,
34
 
                specific_files=None,
35
 
                show_ids=False,
36
 
                to_file=None,
37
 
                show_pending=True,
38
 
                revision=None):
39
 
    """Display summary of changes.
40
 
 
41
 
    Please use show_tree_status instead.
42
 
 
43
 
    By default this compares the working tree to a previous revision. 
44
 
    If the revision argument is given, summarizes changes between the 
45
 
    working tree and another, or between two revisions.
46
 
 
47
 
    The result is written out as Unicode and to_file should be able 
48
 
    to encode that.
49
 
 
50
 
    show_unchanged
51
 
        If set, includes unchanged files.
52
 
 
53
 
    specific_files
54
 
        If set, only show the status of files in this list.
55
 
 
56
 
    show_ids
57
 
        If set, includes each file's id.
58
 
 
59
 
    to_file
60
 
        If set, write to this file (default stdout.)
61
 
 
62
 
    show_pending
63
 
        If set, write pending merges.
64
 
 
65
 
    revision
66
 
        If None the compare latest revision with working tree
67
 
        If one revision show compared it with working tree.
68
 
        If two revisions show status between first and second.
69
 
    """
70
 
    show_tree_status(branch.bzrdir.open_workingtree(), show_unchanged, 
71
 
                     specific_files, show_ids, to_file, show_pending, revision)
72
 
 
73
 
 
74
38
def show_tree_status(wt, show_unchanged=None,
75
39
                     specific_files=None,
76
40
                     show_ids=False,
77
41
                     to_file=None,
78
42
                     show_pending=True,
79
 
                     revision=None):
 
43
                     revision=None,
 
44
                     short=False,
 
45
                     versioned=False):
80
46
    """Display summary of changes.
81
47
 
82
48
    By default this compares the working tree to a previous revision. 
97
63
    :param show_ids: If set, includes each file's id.
98
64
    :param to_file: If set, write to this file (default stdout.)
99
65
    :param show_pending: If set, write pending merges.
100
 
    :param revision: If None the compare latest revision with working tree
101
 
        If not None it must be a RevisionSpec list.
102
 
        If one revision show compared it with working tree.
103
 
        If two revisions show status between first and second.
 
66
    :param revision: If None, compare latest revision with working tree
 
67
        If not None, it must be a RevisionSpec list.
 
68
        If one revision, compare with working tree.
 
69
        If two revisions, show status between first and second.
 
70
    :param short: If True, gives short SVN-style status lines.
 
71
    :param versioned: If True, only shows versioned files.
104
72
    """
105
73
    if show_unchanged is not None:
106
 
        warn("show_status_trees with show_unchanged has been deprecated "
 
74
        warn("show_tree_status with show_unchanged has been deprecated "
107
75
             "since bzrlib 0.9", DeprecationWarning, stacklevel=2)
108
76
 
109
77
    if to_file is None:
113
81
    try:
114
82
        new_is_working_tree = True
115
83
        if revision is None:
 
84
            if wt.last_revision() != wt.branch.last_revision():
 
85
                warning("working tree is out of date, run 'bzr update'")
116
86
            new = wt
117
87
            old = new.basis_tree()
118
88
        elif len(revision) > 0:
119
89
            try:
120
 
                rev_id = revision[0].in_history(wt.branch).rev_id
 
90
                rev_id = revision[0].as_revision_id(wt.branch)
121
91
                old = wt.branch.repository.revision_tree(rev_id)
122
92
            except errors.NoSuchRevision, e:
123
93
                raise errors.BzrCommandError(str(e))
124
94
            if (len(revision) > 1) and (revision[1].spec is not None):
125
95
                try:
126
 
                    rev_id = revision[1].in_history(wt.branch).rev_id
 
96
                    rev_id = revision[1].as_revision_id(wt.branch)
127
97
                    new = wt.branch.repository.revision_tree(rev_id)
128
98
                    new_is_working_tree = False
129
99
                except errors.NoSuchRevision, e:
130
100
                    raise errors.BzrCommandError(str(e))
131
101
            else:
132
102
                new = wt
133
 
        _raise_if_nonexistent(specific_files, old, new)
134
 
        delta = compare_trees(old, new, want_unchanged=show_unchanged,
135
 
                              specific_files=specific_files)
136
 
        delta.show(to_file,
137
 
                   show_ids=show_ids,
138
 
                   show_unchanged=show_unchanged)
139
 
 
140
 
        if new_is_working_tree:
141
 
            list_paths('unknown', new.unknowns(), specific_files, to_file)
142
 
            conflict_title = False
143
 
            for conflict in wt.conflicts():
144
 
                if conflict_title is False:
145
 
                    print >> to_file, "conflicts:"
146
 
                    conflict_title = True
147
 
                print >> to_file, "  %s" % conflict
148
 
        if new_is_working_tree and show_pending:
149
 
            show_pending_merges(new, to_file)
 
103
        old.lock_read()
 
104
        new.lock_read()
 
105
        try:
 
106
            _raise_if_nonexistent(specific_files, old, new)
 
107
            want_unversioned = not versioned
 
108
            if short:
 
109
                changes = new.iter_changes(old, show_unchanged, specific_files,
 
110
                    require_versioned=False, want_unversioned=want_unversioned)
 
111
                reporter = _mod_delta._ChangeReporter(output_file=to_file,
 
112
                    unversioned_filter=new.is_ignored)
 
113
                _mod_delta.report_changes(changes, reporter)
 
114
            else:
 
115
                delta = new.changes_from(old, want_unchanged=show_unchanged,
 
116
                                      specific_files=specific_files,
 
117
                                      want_unversioned=want_unversioned)
 
118
                # filter out unknown files. We may want a tree method for
 
119
                # this
 
120
                delta.unversioned = [unversioned for unversioned in
 
121
                    delta.unversioned if not new.is_ignored(unversioned[0])]
 
122
                delta.show(to_file,
 
123
                           show_ids=show_ids,
 
124
                           show_unchanged=show_unchanged,
 
125
                           short_status=False)
 
126
            # show the new conflicts only for now. XXX: get them from the
 
127
            # delta.
 
128
            conflicts = new.conflicts()
 
129
            if specific_files is not None:
 
130
                conflicts = conflicts.select_conflicts(new, specific_files,
 
131
                    ignore_misses=True, recurse=True)[1]
 
132
            if len(conflicts) > 0 and not short:
 
133
                to_file.write("conflicts:\n")
 
134
            for conflict in conflicts:
 
135
                if short:
 
136
                    prefix = 'C  '
 
137
                else:
 
138
                    prefix = ' '
 
139
                to_file.write("%s %s\n" % (prefix, conflict))
 
140
            if (new_is_working_tree and show_pending
 
141
                and specific_files is None):
 
142
                show_pending_merges(new, to_file, short)
 
143
        finally:
 
144
            old.unlock()
 
145
            new.unlock()
150
146
    finally:
151
147
        wt.unlock()
152
148
 
153
 
def show_pending_merges(new, to_file):
 
149
 
 
150
def _get_sorted_revisions(tip_revision, revision_ids, parent_map):
 
151
    """Get an iterator which will return the revisions in merge sorted order.
 
152
 
 
153
    This will build up a list of all nodes, such that only nodes in the list
 
154
    are referenced. It then uses MergeSorter to return them in 'merge-sorted'
 
155
    order.
 
156
 
 
157
    :param revision_ids: A set of revision_ids
 
158
    :param parent_map: The parent information for each node. Revisions which
 
159
        are considered ghosts should not be present in the map.
 
160
    :return: iterator from MergeSorter.iter_topo_order()
 
161
    """
 
162
    # MergeSorter requires that all nodes be present in the graph, so get rid
 
163
    # of any references pointing outside of this graph.
 
164
    parent_graph = {}
 
165
    for revision_id in revision_ids:
 
166
        if revision_id not in parent_map: # ghost
 
167
            parent_graph[revision_id] = []
 
168
        else:
 
169
            # Only include parents which are in this sub-graph
 
170
            parent_graph[revision_id] = [p for p in parent_map[revision_id]
 
171
                                            if p in revision_ids]
 
172
    sorter = tsort.MergeSorter(parent_graph, tip_revision)
 
173
    return sorter.iter_topo_order()
 
174
 
 
175
 
 
176
def show_pending_merges(new, to_file, short=False):
154
177
    """Write out a display of pending merges in a working tree."""
155
 
    pending = new.pending_merges()
156
 
    branch = new.branch
157
 
    if len(pending) == 0:
 
178
    parents = new.get_parent_ids()
 
179
    if len(parents) < 2:
158
180
        return
159
 
    print >>to_file, 'pending merges:'
160
 
    last_revision = branch.last_revision()
161
 
    if last_revision is not None:
162
 
        ignore = set(branch.repository.get_ancestry(last_revision))
 
181
 
 
182
    # we need one extra space for terminals that wrap on last char
 
183
    term_width = osutils.terminal_width() - 1
 
184
    if short:
 
185
        first_prefix = 'P   '
 
186
        sub_prefix = 'P.   '
163
187
    else:
164
 
        ignore = set([None])
165
 
    for merge in new.pending_merges():
166
 
        ignore.add(merge)
 
188
        first_prefix = '  '
 
189
        sub_prefix = '    '
 
190
 
 
191
    pending = parents[1:]
 
192
    branch = new.branch
 
193
    last_revision = parents[0]
 
194
    if not short:
 
195
        to_file.write('pending merges:\n')
 
196
    graph = branch.repository.get_graph()
 
197
    other_revisions = [last_revision]
 
198
    log_formatter = log.LineLogFormatter(to_file)
 
199
    for merge in pending:
167
200
        try:
168
 
            from bzrlib.osutils import terminal_width
169
 
            width = terminal_width()
170
 
            m_revision = branch.repository.get_revision(merge)
171
 
            print >> to_file, ' ', line_log(m_revision, width - 3)
172
 
            inner_merges = branch.repository.get_ancestry(merge)
173
 
            assert inner_merges[0] == None
174
 
            inner_merges.pop(0)
175
 
            inner_merges.reverse()
176
 
            for mmerge in inner_merges:
177
 
                if mmerge in ignore:
178
 
                    continue
179
 
                mm_revision = branch.repository.get_revision(mmerge)
180
 
                print >> to_file, '   ', line_log(mm_revision, width - 5)
181
 
                ignore.add(mmerge)
 
201
            rev = branch.repository.get_revisions([merge])[0]
182
202
        except errors.NoSuchRevision:
183
 
            print >> to_file, ' ', merge
184
 
        
185
 
def list_paths(header, paths, specific_files, to_file):
186
 
    done_header = False
187
 
    for path in paths:
188
 
        if specific_files and not is_inside_any(specific_files, path):
 
203
            # If we are missing a revision, just print out the revision id
 
204
            to_file.write(first_prefix + '(ghost) ' + merge + '\n')
 
205
            other_revisions.append(merge)
189
206
            continue
190
 
        if not done_header:
191
 
            print >>to_file, '%s:' % header
192
 
            done_header = True
193
 
        print >>to_file, ' ', path
 
207
 
 
208
        # Log the merge, as it gets a slightly different formatting
 
209
        log_message = log_formatter.log_string(None, rev,
 
210
                        term_width - len(first_prefix))
 
211
        to_file.write(first_prefix + log_message + '\n')
 
212
        # Find all of the revisions in the merge source, which are not in the
 
213
        # last committed revision.
 
214
        merge_extra = graph.find_unique_ancestors(merge, other_revisions)
 
215
        other_revisions.append(merge)
 
216
        merge_extra.discard(_mod_revision.NULL_REVISION)
 
217
 
 
218
        # Get a handle to all of the revisions we will need
 
219
        try:
 
220
            revisions = dict((rev.revision_id, rev) for rev in
 
221
                             branch.repository.get_revisions(merge_extra))
 
222
        except errors.NoSuchRevision:
 
223
            # One of the sub nodes is a ghost, check each one
 
224
            revisions = {}
 
225
            for revision_id in merge_extra:
 
226
                try:
 
227
                    rev = branch.repository.get_revisions([revision_id])[0]
 
228
                except errors.NoSuchRevision:
 
229
                    revisions[revision_id] = None
 
230
                else:
 
231
                    revisions[revision_id] = rev
 
232
 
 
233
        # Display the revisions brought in by this merge.
 
234
        rev_id_iterator = _get_sorted_revisions(merge, merge_extra,
 
235
                            branch.repository.get_parent_map(merge_extra))
 
236
        # Skip the first node
 
237
        num, first, depth, eom = rev_id_iterator.next()
 
238
        if first != merge:
 
239
            raise AssertionError('Somehow we misunderstood how'
 
240
                ' iter_topo_order works %s != %s' % (first, merge))
 
241
        for num, sub_merge, depth, eom in rev_id_iterator:
 
242
            rev = revisions[sub_merge]
 
243
            if rev is None:
 
244
                to_file.write(sub_prefix + '(ghost) ' + sub_merge + '\n')
 
245
                continue
 
246
            log_message = log_formatter.log_string(None,
 
247
                            revisions[sub_merge],
 
248
                            term_width - len(sub_prefix))
 
249
            to_file.write(sub_prefix + log_message + '\n')