~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/status.py

  • Committer: Aaron Bentley
  • Date: 2007-12-12 15:17:13 UTC
  • mto: This revision was merged to the branch mainline in revision 3113.
  • Revision ID: abentley@panoramicfeedback.com-20071212151713-ox5n8rlx8m3nsspy
Add support for reconfiguring repositories into branches or trees

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# (C) 2005 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
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
17
import sys
 
18
 
 
19
from bzrlib import (
 
20
    delta as _mod_delta,
 
21
    tree,
 
22
    )
 
23
from bzrlib.diff import _raise_if_nonexistent
 
24
import bzrlib.errors as errors
 
25
from bzrlib.log import line_log
18
26
from bzrlib.osutils import is_inside_any
19
 
from bzrlib.delta import compare_trees
20
 
from bzrlib.log import line_log
21
 
from bzrlib.errors import NoSuchRevision
 
27
from bzrlib.symbol_versioning import (deprecated_function,
 
28
        )
 
29
from bzrlib.trace import warning
22
30
 
23
31
# TODO: when showing single-line logs, truncate to the width of the terminal
24
32
# if known, but only if really going to the terminal (not into a file)
25
33
 
26
34
 
27
 
def show_status(branch, show_unchanged=False,
28
 
                specific_files=None,
29
 
                show_ids=False,
30
 
                to_file=None,
31
 
                show_pending=True,
32
 
                revision=None):
 
35
def show_tree_status(wt, show_unchanged=None,
 
36
                     specific_files=None,
 
37
                     show_ids=False,
 
38
                     to_file=None,
 
39
                     show_pending=True,
 
40
                     revision=None,
 
41
                     short=False,
 
42
                     versioned=False):
33
43
    """Display summary of changes.
34
44
 
35
45
    By default this compares the working tree to a previous revision. 
39
49
    The result is written out as Unicode and to_file should be able 
40
50
    to encode that.
41
51
 
42
 
    show_unchanged
43
 
        If set, includes unchanged files.
44
 
 
45
 
    specific_files
46
 
        If set, only show the status of files in this list.
47
 
 
48
 
    show_ids
49
 
        If set, includes each file's id.
50
 
 
51
 
    to_file
52
 
        If set, write to this file (default stdout.)
53
 
 
54
 
    show_pending
55
 
        If set, write pending merges.
56
 
 
57
 
    revision
58
 
        If None the compare latest revision with working tree
 
52
    If showing the status of a working tree, extra information is included
 
53
    about unknown files, conflicts, and pending merges.
 
54
 
 
55
    :param show_unchanged: Deprecated parameter. If set, includes unchanged 
 
56
        files.
 
57
    :param specific_files: If set, a list of filenames whose status should be
 
58
        shown.  It is an error to give a filename that is not in the working 
 
59
        tree, or in the working inventory or in the basis inventory.
 
60
    :param show_ids: If set, includes each file's id.
 
61
    :param to_file: If set, write to this file (default stdout.)
 
62
    :param show_pending: If set, write pending merges.
 
63
    :param revision: If None the compare latest revision with working tree
 
64
        If not None it must be a RevisionSpec list.
59
65
        If one revision show compared it with working tree.
60
66
        If two revisions show status between first and second.
 
67
    :param short: If True, gives short SVN-style status lines.
 
68
    :param versioned: If True, only shows versioned files.
61
69
    """
62
 
    if to_file == None:
 
70
    if show_unchanged is not None:
 
71
        warn("show_status_trees with show_unchanged has been deprecated "
 
72
             "since bzrlib 0.9", DeprecationWarning, stacklevel=2)
 
73
 
 
74
    if to_file is None:
63
75
        to_file = sys.stdout
64
76
    
65
 
    branch.lock_read()
 
77
    wt.lock_read()
66
78
    try:
67
79
        new_is_working_tree = True
68
80
        if revision is None:
69
 
            old = branch.basis_tree()
70
 
            new = branch.working_tree()
 
81
            if wt.last_revision() != wt.branch.last_revision():
 
82
                warning("working tree is out of date, run 'bzr update'")
 
83
            new = wt
 
84
            old = new.basis_tree()
71
85
        elif len(revision) > 0:
72
86
            try:
73
 
                rev_id = revision[0].in_history(branch).rev_id
74
 
                old = branch.revision_tree(rev_id)
75
 
            except NoSuchRevision, e:
76
 
                raise BzrCommandError(str(e))
77
 
            if len(revision) > 1:
 
87
                rev_id = revision[0].in_history(wt.branch).rev_id
 
88
                old = wt.branch.repository.revision_tree(rev_id)
 
89
            except errors.NoSuchRevision, e:
 
90
                raise errors.BzrCommandError(str(e))
 
91
            if (len(revision) > 1) and (revision[1].spec is not None):
78
92
                try:
79
 
                    rev_id = revision[1].in_history(branch).rev_id
80
 
                    new = branch.revision_tree(rev_id)
 
93
                    rev_id = revision[1].in_history(wt.branch).rev_id
 
94
                    new = wt.branch.repository.revision_tree(rev_id)
81
95
                    new_is_working_tree = False
82
 
                except NoSuchRevision, e:
83
 
                    raise BzrCommandError(str(e))
84
 
            else:
85
 
                new = branch.working_tree()
86
 
                
87
 
 
88
 
        delta = compare_trees(old, new, want_unchanged=show_unchanged,
89
 
                              specific_files=specific_files)
90
 
 
91
 
        delta.show(to_file,
92
 
                   show_ids=show_ids,
93
 
                   show_unchanged=show_unchanged)
94
 
 
95
 
        if new_is_working_tree:
96
 
            list_paths('unknown', new.unknowns(), specific_files, to_file)
97
 
            list_paths('conflicts', new.iter_conflicts(), specific_files, to_file)
98
 
        if new_is_working_tree and show_pending:
99
 
            show_pending_merges(new, to_file)
 
96
                except errors.NoSuchRevision, e:
 
97
                    raise errors.BzrCommandError(str(e))
 
98
            else:
 
99
                new = wt
 
100
        old.lock_read()
 
101
        new.lock_read()
 
102
        try:
 
103
            _raise_if_nonexistent(specific_files, old, new)
 
104
            want_unversioned = not versioned
 
105
            if short:
 
106
                changes = new._iter_changes(old, show_unchanged, specific_files,
 
107
                    require_versioned=False, want_unversioned=want_unversioned)
 
108
                reporter = _mod_delta._ChangeReporter(output_file=to_file,
 
109
                    unversioned_filter=new.is_ignored)
 
110
                _mod_delta.report_changes(changes, reporter)
 
111
            else:
 
112
                delta = new.changes_from(old, want_unchanged=show_unchanged,
 
113
                                      specific_files=specific_files,
 
114
                                      want_unversioned=want_unversioned)
 
115
                # filter out unknown files. We may want a tree method for
 
116
                # this
 
117
                delta.unversioned = [unversioned for unversioned in
 
118
                    delta.unversioned if not new.is_ignored(unversioned[0])]
 
119
                delta.show(to_file,
 
120
                           show_ids=show_ids,
 
121
                           show_unchanged=show_unchanged,
 
122
                           short_status=False)
 
123
            # show the new conflicts only for now. XXX: get them from the
 
124
            # delta.
 
125
            conflicts = new.conflicts()
 
126
            if specific_files is not None:
 
127
                conflicts = conflicts.select_conflicts(new, specific_files,
 
128
                    ignore_misses=True, recurse=True)[1]
 
129
            if len(conflicts) > 0 and not short:
 
130
                to_file.write("conflicts:\n")
 
131
            for conflict in conflicts:
 
132
                if short:
 
133
                    prefix = 'C  '
 
134
                else:
 
135
                    prefix = ' '
 
136
                to_file.write("%s %s\n" % (prefix, conflict))
 
137
            if new_is_working_tree and show_pending:
 
138
                show_pending_merges(new, to_file, short)
 
139
        finally:
 
140
            old.unlock()
 
141
            new.unlock()
100
142
    finally:
101
 
        branch.unlock()
 
143
        wt.unlock()
102
144
 
103
 
def show_pending_merges(new, to_file):
 
145
def show_pending_merges(new, to_file, short=False):
104
146
    """Write out a display of pending merges in a working tree."""
105
 
    pending = new.pending_merges()
 
147
    parents = new.get_parent_ids()
 
148
    if len(parents) < 2:
 
149
        return
 
150
    pending = parents[1:]
106
151
    branch = new.branch
107
 
    if len(pending) == 0:
108
 
        return
109
 
    print >>to_file, 'pending merges:'
110
 
    last_revision = branch.last_revision()
 
152
    last_revision = parents[0]
 
153
    if not short:
 
154
        to_file.write('pending merges:\n')
111
155
    if last_revision is not None:
112
 
        ignore = set(branch.get_ancestry(last_revision))
 
156
        try:
 
157
            ignore = set(branch.repository.get_ancestry(last_revision,
 
158
                                                        topo_sorted=False))
 
159
        except errors.NoSuchRevision:
 
160
            # the last revision is a ghost : assume everything is new 
 
161
            # except for it
 
162
            ignore = set([None, last_revision])
113
163
    else:
114
 
        ignore = set()
115
 
    for merge in new.pending_merges():
 
164
        ignore = set([None])
 
165
    # TODO: this could be improved using merge_sorted - we'd get the same 
 
166
    # output rather than one level of indent.
 
167
    for merge in pending:
116
168
        ignore.add(merge)
117
169
        try:
118
 
            m_revision = branch.get_revision(merge)
119
 
            print >> to_file, ' ', line_log(m_revision, 77)
120
 
            inner_merges = branch.get_ancestry(merge)
 
170
            from bzrlib.osutils import terminal_width
 
171
            width = terminal_width()
 
172
            m_revision = branch.repository.get_revision(merge)
 
173
            if short:
 
174
                prefix = 'P  '
 
175
            else:
 
176
                prefix = ' '
 
177
            to_file.write(prefix + ' ' + line_log(m_revision, width - 4))
 
178
            to_file.write('\n')
 
179
            inner_merges = branch.repository.get_ancestry(merge)
 
180
            assert inner_merges[0] is None
 
181
            inner_merges.pop(0)
121
182
            inner_merges.reverse()
122
183
            for mmerge in inner_merges:
123
184
                if mmerge in ignore:
124
185
                    continue
125
 
                mm_revision = branch.get_revision(mmerge)
126
 
                print >> to_file, '   ', line_log(mm_revision, 75)
 
186
                mm_revision = branch.repository.get_revision(mmerge)
 
187
                if short:
 
188
                    prefix = 'P.  '
 
189
                else:
 
190
                    prefix = '   '
 
191
                to_file.write(prefix + ' ' + line_log(mm_revision, width - 5))
 
192
                to_file.write('\n')
127
193
                ignore.add(mmerge)
128
 
        except NoSuchRevision:
129
 
            print >> to_file, ' ', merge 
130
 
        
131
 
def list_paths(header, paths, specific_files, to_file):
132
 
    done_header = False
133
 
    for path in paths:
134
 
        if specific_files and not is_inside_any(specific_files, path):
135
 
            continue
136
 
        if not done_header:
137
 
            print >>to_file, '%s:' % header
138
 
            done_header = True
139
 
        print >>to_file, ' ', path
 
194
        except errors.NoSuchRevision:
 
195
            if short:
 
196
                prefix = 'P  '
 
197
            else:
 
198
                prefix = ' '
 
199
            to_file.write(prefix + ' ' + merge)
 
200
            to_file.write('\n')