~abentley/bzrtools/bzrtools.dev

« back to all changes in this revision

Viewing changes to zap.py

  • Committer: Aaron Bentley
  • Date: 2011-04-12 04:13:00 UTC
  • mto: This revision was merged to the branch mainline in revision 757.
  • Revision ID: aaron@aaronbentley.com-20110412041300-k13os9o9cq8hlox0
Revamp zap's changed-file handling.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2006-2007, 2010-2011 Aaron Bentley <aaron@aaronbentley.com>
 
2
# Copyright (C) 2007 Charlie Shepherd <masterdriverz@gentoo.org>
 
3
# Copyright (C) 2011 Canonical Ltd.
 
4
#
 
5
#    This program is free software; you can redistribute it and/or modify
 
6
#    it under the terms of the GNU General Public License as published by
 
7
#    the Free Software Foundation; either version 2 of the License, or
 
8
#    (at your option) any later version.
 
9
#
 
10
#    This program is distributed in the hope that it will be useful,
 
11
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
#    GNU General Public License for more details.
 
14
#
 
15
#    You should have received a copy of the GNU General Public License
 
16
#    along with this program; if not, write to the Free Software
 
17
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
 
1
19
from shutil import rmtree
2
20
 
 
21
from bzrlib import (
 
22
    bzrdir,
 
23
    revision as _mod_revision,
 
24
    )
3
25
from bzrlib.branch import Branch
4
 
from bzrlib.errors import NoWorkingTree, NotLocalUrl, NotBranchError
 
26
from bzrlib.errors import NoWorkingTree, NotBranchError
 
27
from bzrlib import registry
5
28
from bzrlib.workingtree import WorkingTree
6
29
 
7
 
from errors import (NotCheckout, UncommittedCheckout, ParentMissingRevisions, 
 
30
from errors import (NotCheckout, UncommittedCheckout, ParentMissingRevisions,
8
31
                    NoParent)
9
32
 
10
33
 
11
 
def zap(path, remove_branch=False):
 
34
class AllowChanged(object):
 
35
 
 
36
    @classmethod
 
37
    def check_changed(klass, wt, remove_branch):
 
38
        pass
 
39
 
 
40
 
 
41
class CheckChanged(object):
 
42
 
 
43
    @classmethod
 
44
    def check_changed(klass, wt, remove_branch):
 
45
        delta = wt.changes_from(wt.basis_tree(), want_unchanged=False)
 
46
        if delta.has_changed():
 
47
            klass.handle_changed(wt, remove_branch)
 
48
 
 
49
 
 
50
class HaltOnChange(CheckChanged):
 
51
 
 
52
    @staticmethod
 
53
    def handle_changed(wt, remove_branch):
 
54
        raise UncommittedCheckout()
 
55
 
 
56
 
 
57
class StoreChanges(CheckChanged):
 
58
 
 
59
    @staticmethod
 
60
    def handle_changed(wt, remove_branch):
 
61
        from bzrlib.plugins.pipeline.pipeline import PipeManager
 
62
        if remove_branch:
 
63
            raise AssertionError('Cannot store changes in deleted branch.')
 
64
        PipeManager.from_checkout(wt).store_uncommitted()
 
65
 
 
66
 
 
67
change_policy_registry = registry.Registry()
 
68
 
 
69
 
 
70
change_policy_registry.register('force', AllowChanged,
 
71
                                'Delete tree even if contents are modified.')
 
72
 
 
73
 
 
74
change_policy_registry.register('store', StoreChanges,
 
75
                                'Store changes in branch.  (Requires'
 
76
                                ' bzr-pipeline.)')
 
77
 
 
78
 
 
79
change_policy_registry.register('check', StoreChanges,
 
80
                                'Stop if tree contents are modified.')
 
81
 
 
82
 
 
83
def zap(path, remove_branch=False, policy=HaltOnChange):
12
84
    try:
13
 
        wt = WorkingTree.open(path)
 
85
        wt = bzrdir.BzrDir.open(path).open_workingtree(path,
 
86
                                                       recommend_upgrade=False)
14
87
    except (NoWorkingTree, NotBranchError):
15
88
        raise NotCheckout(path)
16
89
    tree_base = wt.bzrdir.transport.base
18
91
    branch_base = branch.bzrdir.transport.base
19
92
    if tree_base == branch_base:
20
93
        raise NotCheckout(path)
21
 
    delta = wt.changes_from(wt.basis_tree(), want_unchanged=False)
22
 
    if delta.has_changed():
23
 
        raise UncommittedCheckout()
 
94
    policy.check_changed(wt, remove_branch)
24
95
    if remove_branch:
25
96
        parent_loc = branch.get_parent()
26
97
        if parent_loc is None:
27
98
            raise NoParent()
28
99
        parent = Branch.open(parent_loc)
29
 
        p_ancestry = parent.repository.get_ancestry(parent.last_revision())
30
 
        if branch.last_revision() not in p_ancestry:
 
100
        last_revision = _mod_revision.ensure_null(parent.last_revision())
 
101
        p_ancestry = parent.repository.get_ancestry(last_revision)
 
102
        if (last_revision != _mod_revision.NULL_REVISION and
 
103
            branch.last_revision() not in p_ancestry):
31
104
            raise ParentMissingRevisions(branch.get_parent())
32
105
    rmtree(path)
33
106
    if remove_branch:
41
114
def test_suite():
42
115
    import os
43
116
    from unittest import makeSuite
44
 
    
45
 
    from bzrlib.bzrdir import BzrDir, BzrDirMetaFormat1
46
 
    from bzrlib.branch import BranchReferenceFormat
 
117
 
47
118
    from bzrlib.tests import TestCaseInTempDir
48
119
 
 
120
 
 
121
    class PipelinePluginFeature:
 
122
 
 
123
        @staticmethod
 
124
        def available():
 
125
            try:
 
126
                import bzrlib.plugins.pipeline
 
127
            except ImportError:
 
128
                return False
 
129
            else:
 
130
                return True
 
131
 
 
132
 
49
133
    class TestZap(TestCaseInTempDir):
50
134
 
51
135
        def make_checkout(self):
52
 
            wt = BzrDir.create_standalone_workingtree('source')
53
 
            os.mkdir('checkout')
54
 
            checkout = BzrDirMetaFormat1().initialize('checkout')
55
 
            BranchReferenceFormat().initialize(checkout, wt.branch)
56
 
            return checkout.create_workingtree()
 
136
            wt = bzrdir.BzrDir.create_standalone_workingtree('source')
 
137
            return wt.branch.create_checkout('checkout', lightweight=True)
57
138
 
58
139
        def make_checkout2(self):
59
140
            wt = self.make_checkout()
60
141
            wt2 = wt.branch.bzrdir.sprout('source2').open_workingtree()
61
 
            os.mkdir('checkout2')
62
 
            checkout = BzrDirMetaFormat1().initialize('checkout2')
63
 
            BranchReferenceFormat().initialize(checkout, wt2.branch)
64
 
            return checkout.create_workingtree()
 
142
            return wt2.branch.create_checkout('checkout2', lightweight=True)
65
143
 
66
144
        def test_is_checkout(self):
67
145
            self.assertRaises(NotCheckout, zap, '.')
68
 
            wt = BzrDir.create_standalone_workingtree('.')
 
146
            wt = bzrdir.BzrDir.create_standalone_workingtree('.')
69
147
            self.assertRaises(NotCheckout, zap, '.')
70
148
 
71
149
        def test_zap_works(self):
75
153
            self.assertIs(False, os.path.exists('checkout'))
76
154
            self.assertIs(True, os.path.exists('source'))
77
155
 
78
 
        def test_zap_branch(self):
 
156
        def test_zap_branch(self):
79
157
            self.make_checkout2()
80
158
            base = WorkingTree.open('checkout').branch.base
81
159
            self.assertIs(True, os.path.exists('checkout'))
94
172
            checkout.commit('commit changes to branch')
95
173
            zap('checkout')
96
174
 
 
175
        def make_modified_checkout(self):
 
176
            checkout = self.make_checkout()
 
177
            os.mkdir('checkout/foo')
 
178
            checkout.add('foo')
 
179
            return checkout
 
180
 
 
181
        def test_allow_modified(self):
 
182
            self.make_modified_checkout()
 
183
            self.assertRaises(UncommittedCheckout, zap, 'checkout')
 
184
            zap('checkout', policy=AllowChanged)
 
185
 
 
186
        def test_store(self):
 
187
            self.requireFeature(PipelinePluginFeature)
 
188
            checkout = self.make_modified_checkout()
 
189
            zap('checkout', policy=StoreChanges)
 
190
            self.assertIn('stored-transform',
 
191
                checkout.branch.bzrdir.transport.list_dir('branch'))
 
192
 
 
193
        def test_store_remove_branch(self):
 
194
            self.requireFeature(PipelinePluginFeature)
 
195
            checkout = self.make_modified_checkout()
 
196
            branch = self.make_branch('branch')
 
197
            checkout.branch.set_parent(branch.base)
 
198
            e = self.assertRaises(AssertionError, zap, 'checkout',
 
199
                                  policy=StoreChanges, remove_branch=True)
 
200
            self.assertEqual('Cannot store changes in deleted branch.', str(e))
 
201
 
 
202
        def test_store_remove_branch_unmodified(self):
 
203
            self.requireFeature(PipelinePluginFeature)
 
204
            checkout = self.make_checkout()
 
205
            branch = self.make_branch('branch')
 
206
            checkout.branch.set_parent(branch.base)
 
207
            zap('checkout', policy=StoreChanges, remove_branch=True)
 
208
 
97
209
    return makeSuite(TestZap)