~abentley/bzrtools/bzrtools.dev

« back to all changes in this revision

Viewing changes to fai.py

  • Committer: Michael Ellerman
  • Date: 2005-11-29 07:12:26 UTC
  • mto: (0.3.1 shelf-dev) (325.1.2 bzrtools)
  • mto: This revision was merged to the branch mainline in revision 334.
  • Revision ID: michael@ellerman.id.au-20051129071226-a04b3f827880025d
Unshelve --pick was broken, because we deleted the whole patch, even when only
part of it was unshelved. So now if we unshelve part of a patch, the patch is
replaced with a new patch that has just the unshelved parts. That's a long way
of saying it does what you'd expect.

Implementing this required changing HunkSelector to return both the selected,
and unselected hunks (ie. patches to shelve, and patches to keep).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2004 Aaron Bentley
2
 
# <aaron.bentley@utoronto.ca>
3
 
#
4
 
#    This program is free software; you can redistribute it and/or modify
5
 
#    it under the terms of the GNU General Public License as published by
6
 
#    the Free Software Foundation; either version 2 of the License, or
7
 
#    (at your option) any later version.
8
 
#
9
 
#    This program is distributed in the hope that it will be useful,
10
 
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 
#    GNU General Public License for more details.
13
 
#
14
 
#    You should have received a copy of the GNU General Public License
15
 
#    along with this program; if not, write to the Free Software
16
 
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 
 
18
 
import pybaz
19
 
from pybaz.backends.baz import sequence_cmd
20
 
import re
21
 
 
22
 
__docformat__ = "restructuredtext"
23
 
__doc__ = "Utility functions to be used by commands"
24
 
 
25
 
def direct_merges(merges, excludes=[]):
26
 
    """Get a list of direct merges, from a list of direct and indirect
27
 
    
28
 
    :param merges: Iterator of merge patchlogs
29
 
    :type merges: iter of `pybaz.Patchlog`
30
 
    :return: The direct merges
31
 
    :rtype: list of `pybaz.Patchlog`
32
 
    """
33
 
    indirect = set()
34
 
    logs = list(merges)
35
 
    if not logs:
36
 
        return []
37
 
    for log in logs:
38
 
        try:
39
 
            this_indirect = set([str(f) for f in log.new_patches 
40
 
                                 if f != log.revision and 
41
 
                                     str(f) not in indirect])
42
 
        except pybaz.errors.NamespaceError:
43
 
            print
44
 
            print "log ", log, " unusable, attempting to use archive copy."
45
 
            log = pybaz.Revision(str(log.revision)).patchlog
46
 
            this_indirect = set([str(f) for f in log.new_patches 
47
 
                                 if f != log.revision and 
48
 
                                     str(f) not in indirect])
49
 
        indirect.update(this_indirect)
50
 
        if log.continuation_of is not None:
51
 
            # continuations list everything in new_patches
52
 
            continue
53
 
        try:
54
 
            # ask baz if we can
55
 
            ancestor = log.revision.ancestor
56
 
        except pybaz.errors.ExecProblem:
57
 
            # baz does not know
58
 
            # guess
59
 
            if log.revision.patchlevel != 'version-0': 
60
 
                ancestor = namespace_previous(log.revision)
61
 
            else:
62
 
                found = False
63
 
                ancestor = None
64
 
                # ancestor might be in the tree
65
 
                for tree_log in pybaz.WorkingTree(log.tree).iter_logs(
66
 
                    log.revision.version, reverse=True):
67
 
                    if found:
68
 
                        ancestor = tree_log.revision
69
 
                        break
70
 
                    if tree_log.revision == log.revision:
71
 
                        found = True
72
 
                print "ancestor of %s is %s" % (log.revision, ancestor)
73
 
        if ancestor is not None:
74
 
            indirect.add(str(ancestor))
75
 
    return [log.revision for log in logs if not str(log.revision) in indirect
76
 
            and log.revision not in excludes]
77
 
 
78
 
 
79
 
def namespace_previous(revision):
80
 
    if revision.patchlevel == 'base-0':
81
 
        return None
82
 
    if revision.patchlevel == 'patch-1':
83
 
        return revision.version['base-0']
84
 
    if revision.patchlevel.startswith('patch'):
85
 
        level = int(revision.patchlevel[len('patch-'):]) -1
86
 
        return revision.version['patch-%d' % level]
87
 
    if revision.patchlevel == 'version-0':
88
 
        raise RuntimeError("cannot determine prior namespace level for a "
89
 
                           "version-0 patch ('%s')" % revision)
90
 
    if revision.patchlevel == 'versionfix-1':
91
 
        return revision.version['version-0']
92
 
    if revision.patchlevel.startswith('versionfix'):
93
 
        level = int(revision.patchlevel[len('versionfix-'):]) -1
94
 
        return revision.version['versionfix-%d' % level]
95
 
    raise NotImplementedError
96
 
 
97
 
def iter_new_merges(tree, version, reverse=False):
98
 
    """List patchlogs that are new in this tree since the last commit.
99
 
 
100
 
    :param tree: The working tree to calculate new revisions in
101
 
    :type tree: str
102
 
    :param version: The version to use when determining new logs
103
 
    :type version: str
104
 
    :param reverse: If true, list backwards, from newest to oldest
105
 
    :type reverse: bool
106
 
    :return: An iterator for new revision logs in this tree
107
 
    :rtype: Iterator of `pybaz.Patchlog`
108
 
    """
109
 
    assert (isinstance(version, pybaz.Version))
110
 
    for line in _iter_new_merges(tree, version.fullname, reverse):
111
 
        yield pybaz.Patchlog(line, tree)
112
 
 
113
 
def _iter_new_merges(directory, version, reverse):
114
 
    """List patchlogs that are new in this tree since the last commit.
115
 
 
116
 
    :param directory: The working tree to calculate new revisions in
117
 
    :type directory: str
118
 
    :param version: The version to use when determining new logs
119
 
    :type version: str
120
 
    :param reverse: If true, list backwards, from newest to oldest
121
 
    :type reverse: bool
122
 
    :return: An iterator for names of revisions new in this tree
123
 
    :rtype: Iterator of str
124
 
    """
125
 
    args = [ 'new-merges', '--dir', directory ]
126
 
    if reverse: 
127
 
        args.append('--reverse')
128
 
    args.append(version)
129
 
    return sequence_cmd(args)