/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.5.17 by John Arbash Meinel
adding apply-changset, plus more meta information.
1
#!/usr/bin/env python
2
"""\
3
This contains the apply changset function for bzr
4
"""
5
6
import bzrlib
0.5.67 by John Arbash Meinel
Working on apply_changeset
7
import os
8
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
9
from bzrlib.trace import mutter, warning
0.5.110 by Aaron Bentley
Switched to using the common ancestor for changeset merge base
10
from bzrlib.revision import common_ancestor
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
11
0.5.83 by John Arbash Meinel
Tests pass. Now ChangesetTree has it's own inventory.
12
def _install_info(branch, cset_info, cset_tree):
0.5.67 by John Arbash Meinel
Working on apply_changeset
13
    """Make sure that there is a text entry for each 
14
    file in the changeset.
15
    """
0.5.102 by John Arbash Meinel
Updated to latest bzr.dev changes (serialization, test cases, etc)
16
    from bzrlib.xml import serializer_v4
0.5.67 by John Arbash Meinel
Working on apply_changeset
17
    from cStringIO import StringIO
18
0.5.83 by John Arbash Meinel
Tests pass. Now ChangesetTree has it's own inventory.
19
    inv = cset_tree.inventory
0.5.67 by John Arbash Meinel
Working on apply_changeset
20
    # First, install all required texts
0.5.83 by John Arbash Meinel
Tests pass. Now ChangesetTree has it's own inventory.
21
    for path, ie in inv.iter_entries():
22
        if ie.text_id is not None and ie.text_id not in branch.text_store:
0.5.82 by John Arbash Meinel
Lots of changes, changing separators, updating tests, updated ChangesetTree to include text_ids
23
            branch.text_store.add(cset_tree.get_file(ie.file_id), ie.text_id)
0.5.67 by John Arbash Meinel
Working on apply_changeset
24
25
    # Now install the final inventory
26
    if cset_info.target not in branch.inventory_store:
27
        # bzrlib.commit uses a temporary file, but store.add
28
        # reads in the entire file anyway
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
29
        if cset_info.target in branch.inventory_store:
30
            warning('Target inventory already exists in destination.')
31
        else:
32
            sio = StringIO()
0.5.102 by John Arbash Meinel
Updated to latest bzr.dev changes (serialization, test cases, etc)
33
            serializer_v4.write_inventory(inv, sio)
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
34
            branch.inventory_store.add(sio.getvalue(), cset_info.target)
35
            del sio
0.5.67 by John Arbash Meinel
Working on apply_changeset
36
37
    # Now that we have installed the inventory and texts
38
    # install the revision entries.
39
    for rev in cset_info.real_revisions:
40
        if rev.revision_id not in branch.revision_store:
41
            sio = StringIO()
0.5.102 by John Arbash Meinel
Updated to latest bzr.dev changes (serialization, test cases, etc)
42
            serializer_v4.write_revision(rev, sio)
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
43
            branch.revision_store.add(sio.getvalue(), rev.revision_id)
0.5.67 by John Arbash Meinel
Working on apply_changeset
44
            del sio
45
46
def merge_revs(branch, rev_base, rev_other,
47
        ignore_zero=False, check_clean=True):
48
    """This will merge the tree of rev_other into 
49
    the working tree of branch using the base given by rev_base.
50
    All the revision XML should be inside branch.
51
    """
52
    import tempfile, shutil
53
    from bzrlib.merge import merge_inner, MergeTree
54
    from bzrlib.errors import BzrCommandError
55
56
    tempdir = tempfile.mkdtemp(prefix='bzr-')
57
    try:
58
        if check_clean:
59
            from bzrlib.diff import compare_trees
60
            changes = compare_trees(branch.working_tree(), 
61
                                    branch.basis_tree(), False)
62
63
            if changes.has_changed():
64
                raise BzrCommandError("Working tree has uncommitted changes.")
65
66
        other_dir = os.path.join(tempdir, 'other')
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
67
        os.mkdir(other_dir)
0.5.67 by John Arbash Meinel
Working on apply_changeset
68
        other_tree = MergeTree(branch.revision_tree(rev_other), other_dir)
69
70
        base_dir = os.path.join(tempdir, 'base')
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
71
        os.mkdir(base_dir)
0.5.67 by John Arbash Meinel
Working on apply_changeset
72
        base_tree = MergeTree(branch.revision_tree(rev_base), base_dir)
73
74
        merge_inner(branch, other_tree, base_tree, tempdir,
75
            ignore_zero=ignore_zero)
76
    finally:
77
        shutil.rmtree(tempdir)
78
0.5.69 by John Arbash Meinel
Applying patch from Robey Pointer to clean up apply_changeset.
79
def apply_changeset(branch, from_file, reverse=False, auto_commit=False):
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
80
    """Read in a changeset from the given file, and apply it to
81
    the supplied branch.
0.5.86 by John Arbash Meinel
Updated the auto-commit functionality, and adding to pending-merges, more testing.
82
83
    :return: True if the changeset was automatically committed to the
84
             ancestry, False otherwise.
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
85
    """
0.5.17 by John Arbash Meinel
adding apply-changset, plus more meta information.
86
    import sys, read_changeset
87
0.5.69 by John Arbash Meinel
Applying patch from Robey Pointer to clean up apply_changeset.
88
    if reverse:
89
        raise Exception('reverse not implemented yet')
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
90
91
    cset = read_changeset.read_changeset(from_file, branch)
92
0.5.86 by John Arbash Meinel
Updated the auto-commit functionality, and adding to pending-merges, more testing.
93
    return _apply_cset(branch, cset, reverse=reverse, auto_commit=auto_commit)
0.5.69 by John Arbash Meinel
Applying patch from Robey Pointer to clean up apply_changeset.
94
        
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
95
def _apply_cset(branch, cset, reverse=False, auto_commit=False):
96
    """Apply an in-memory changeset to a given branch.
97
    """
98
0.5.83 by John Arbash Meinel
Tests pass. Now ChangesetTree has it's own inventory.
99
    cset_info, cset_tree = cset
0.5.67 by John Arbash Meinel
Working on apply_changeset
100
0.5.83 by John Arbash Meinel
Tests pass. Now ChangesetTree has it's own inventory.
101
    _install_info(branch, cset_info, cset_tree)
0.5.67 by John Arbash Meinel
Working on apply_changeset
102
103
    # We could technically optimize more, by using the ChangesetTree
104
    # we already have in memory, but after installing revisions
105
    # this code can work the way merge should work in the
106
    # future.
107
    #
108
    # TODO:
109
    #   This shouldn't use the base of the changeset as the base
110
    #   for the merge, the merge code should pick the best merge
111
    #   based on the ancestry of both trees.
112
    #
0.5.110 by Aaron Bentley
Switched to using the common ancestor for changeset merge base
113
    base = common_ancestor(branch.last_patch(), cset_info.target, branch)
114
    merge_revs(branch, base, cset_info.target)
0.5.17 by John Arbash Meinel
adding apply-changset, plus more meta information.
115
0.5.86 by John Arbash Meinel
Updated the auto-commit functionality, and adding to pending-merges, more testing.
116
    auto_committed = False
117
    
118
    # There are 2 cases where I am allowing automatic committing.
119
    # 1) If the final revision has a parent of the current last revision
120
    #    (branch.last_patch() in cset.target.parents)
121
    #    that means that the changeset target has already merged the current
122
    #    tree.
123
    # 2) A cset contains a list of revisions. If the first entry has a parent
124
    #    of branch.last_patch(), then we can start merging there, and add the
125
    #    rest of the revisions. But it gets better. Some of the entries in the
126
    #    list might already be in the revision list, so we keep going until
127
    #    we find the first revision *not* in the list. If it's parent is
128
    #    branch.last_patch(), then we can also append history from there.
129
    #    This second part is a little more controversial, because the cset
130
    #    probably does not include all of the inventories. So you would have
131
    #    entries in branch.revision_history() without an associated inventory.
132
    #    we could just explicitly disable this. But if we had the inventory
133
    #    entries available, it is what 'bzr merge' would do.
134
    #    If we disable this, the target will just show up as a pending_merge
0.5.17 by John Arbash Meinel
adding apply-changset, plus more meta information.
135
    if auto_commit:
0.5.67 by John Arbash Meinel
Working on apply_changeset
136
        # When merging, if the revision to be merged has a parent
137
        # of the current revision, then it can be installed
138
        # directly.
139
        #
140
        # TODO: 
141
        #   There is actually a slightly stronger statement
142
        #   whereby if the current revision is in the ancestry
143
        #   of the merged revisions, it doesn't need to be the
144
        #   immediate ancestry, but that requires searching
145
        #   a potentially branching history.
146
        #
0.5.86 by John Arbash Meinel
Updated the auto-commit functionality, and adding to pending-merges, more testing.
147
        rh = branch.revision_history()
148
        revs_to_merge = None
149
        found_parent = False
150
        if len(rh) == 0 and len(cset_info.real_revisions[0].parents) == 0:
151
            found_parent = True
152
            revs_to_merge = cset_info.real_revisions
153
        else:
154
            for rev_num, rev in enumerate(cset_info.real_revisions):
155
                if rev.revision_id not in rh:
156
                    for parent in rev.parents:
157
                        if parent.revision_id == rh[-1]:
158
                            found_parent = True
159
                    if found_parent:
160
                        # All revisions up until now already
161
                        # existed in the target history
162
                        # and this last one is a child of the
163
                        # last entry in the history.
164
                        # so we can add the rest
165
                        revs_to_merge = cset_info.real_revisions[rev_num:]
166
                    # Even if we don't find anything, we need to
167
                    # stop here
168
                    break
169
170
        if found_parent:
171
            rev_ids = [r.revision_id for r in revs_to_merge]
172
            branch.append_revision(*rev_ids)
173
            auto_committed = True
174
        else:
175
            # We can also merge if the *last* revision has an
176
            # appropriate parent.
177
            target_has_parent = False
178
            target_rev = branch.get_revision(cset_info.target)
179
            lastrev_id = branch.last_patch()
180
            for parent in target_rev.parents:
181
                if parent.revision_id == lastrev_id:
182
                    target_has_parent = True
183
184
            if target_has_parent:
185
                branch.append_revision(target_rev.revision_id)
186
            else:
187
                print '** Could not auto-commit.'
188
189
    if not auto_committed:
190
        branch.add_pending_merge(cset_info.target)
191
192
    return auto_committed
0.5.17 by John Arbash Meinel
adding apply-changset, plus more meta information.
193