1
# Copyright (C) 2006-2007, 2010-2011 Aaron Bentley <aaron@aaronbentley.com>
2
# Copyright (C) 2013 Aaron Bentley <aaron@aaronbentley.com>
3
# Copyright (C) 2007 Charlie Shepherd <masterdriverz@gentoo.org>
4
# Copyright (C) 2011 Canonical Ltd.
6
# This program is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 2 of the License, or
9
# (at your option) any later version.
11
# This program is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
# GNU General Public License for more details.
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
from shutil import rmtree
24
revision as _mod_revision,
26
from bzrlib.branch import Branch
27
from bzrlib.errors import BzrCommandError, NoWorkingTree, NotBranchError
28
from bzrlib import registry
29
from bzrlib.workingtree import WorkingTree
31
from errors import (NotCheckout, UncommittedCheckout, ParentMissingRevisions,
33
from bzrlib.plugins.bzrtools.bzrtools import read_locked
36
class AllowChanged(object):
39
def check_changed(klass, wt, remove_branch):
43
class CheckChanged(object):
46
def check_changed(klass, wt, remove_branch):
47
delta = wt.changes_from(wt.basis_tree(), want_unchanged=False)
48
if delta.has_changed():
49
klass.handle_changed(wt, remove_branch)
52
class HaltOnChange(CheckChanged):
55
def handle_changed(wt, remove_branch):
56
raise UncommittedCheckout()
59
class StoreChanges(CheckChanged):
62
def handle_changed(wt, remove_branch):
63
from bzrlib.plugins.pipeline.pipeline import PipeManager
65
raise BzrCommandError('Cannot store changes in deleted branch.')
66
PipeManager.from_checkout(wt).store_uncommitted()
69
change_policy_registry = registry.Registry()
72
change_policy_registry.register('force', AllowChanged,
73
'Delete tree even if contents are modified.')
76
change_policy_registry.register('store', StoreChanges,
77
'Store changes in branch. (Requires'
81
change_policy_registry.register('check', HaltOnChange,
82
'Stop if tree contents are modified.')
85
change_policy_registry.default_key = 'check'
89
def zap(path, remove_branch=False, policy=HaltOnChange):
91
wt = bzrdir.BzrDir.open(path).open_workingtree(path,
92
recommend_upgrade=False)
93
except (NoWorkingTree, NotBranchError):
94
raise NotCheckout(path)
95
tree_base = wt.bzrdir.transport.base
97
branch_base = branch.bzrdir.transport.base
98
if tree_base == branch_base:
99
raise NotCheckout(path)
100
policy.check_changed(wt, remove_branch)
102
parent_loc = branch.get_parent()
103
if parent_loc is None:
105
with read_locked(Branch.open(parent_loc)) as parent:
106
last_revision = _mod_revision.ensure_null(parent.last_revision())
107
if last_revision != _mod_revision.NULL_REVISION:
108
graph = parent.repository.get_graph()
109
heads = graph.heads([last_revision, branch.last_revision()])
110
if branch.last_revision() in heads:
111
raise ParentMissingRevisions(branch.get_parent())
114
t = branch.bzrdir.transport
115
while t.base != branch_base:
123
from unittest import makeSuite
125
from bzrlib.tests import TestCaseWithTransport
128
class PipelinePluginFeature:
133
import bzrlib.plugins.pipeline
140
class TestZap(TestCaseWithTransport):
142
def make_checkout(self):
143
wt = bzrdir.BzrDir.create_standalone_workingtree('source')
144
return wt.branch.create_checkout('checkout', lightweight=True)
146
def make_checkout2(self):
147
wt = self.make_checkout()
148
wt2 = wt.branch.bzrdir.sprout('source2').open_workingtree()
149
return wt2.branch.create_checkout('checkout2', lightweight=True)
151
def test_is_checkout(self):
152
self.assertRaises(NotCheckout, zap, '.')
153
wt = bzrdir.BzrDir.create_standalone_workingtree('.')
154
self.assertRaises(NotCheckout, zap, '.')
156
def test_zap_works(self):
158
self.assertIs(True, os.path.exists('checkout'))
160
self.assertIs(False, os.path.exists('checkout'))
161
self.assertIs(True, os.path.exists('source'))
163
def test_zap_branch(self):
164
self.make_checkout2()
165
base = WorkingTree.open('checkout').branch.base
166
self.assertIs(True, os.path.exists('checkout'))
167
self.assertRaises(NoParent, zap, 'checkout', remove_branch=True)
168
self.assertIs(True, os.path.exists('checkout'))
169
self.assertIs(True, os.path.exists('source'))
170
zap('checkout2', remove_branch=True)
171
self.assertIs(False, os.path.exists('checkout2'))
172
self.assertIs(False, os.path.exists('source2'))
174
def test_checks_modified(self):
175
checkout = self.make_checkout()
176
os.mkdir('checkout/foo')
178
self.assertRaises(UncommittedCheckout, zap, 'checkout')
179
checkout.commit('commit changes to branch')
182
def make_modified_checkout(self):
183
checkout = self.make_checkout()
184
os.mkdir('checkout/foo')
188
def test_allow_modified(self):
189
self.make_modified_checkout()
190
self.assertRaises(UncommittedCheckout, zap, 'checkout')
191
zap('checkout', policy=AllowChanged)
193
def test_store(self):
194
self.requireFeature(PipelinePluginFeature)
195
checkout = self.make_modified_checkout()
196
zap('checkout', policy=StoreChanges)
197
self.assertIn('stored-transform',
198
checkout.branch.bzrdir.transport.list_dir('branch'))
200
def test_store_remove_branch(self):
201
self.requireFeature(PipelinePluginFeature)
202
checkout = self.make_modified_checkout()
203
branch = self.make_branch('branch')
204
checkout.branch.set_parent(branch.base)
205
e = self.assertRaises(BzrCommandError, zap, 'checkout',
206
policy=StoreChanges, remove_branch=True)
207
self.assertEqual('Cannot store changes in deleted branch.', str(e))
209
def test_store_remove_branch_unmodified(self):
210
self.requireFeature(PipelinePluginFeature)
211
checkout = self.make_checkout()
212
branch = self.make_branch('branch')
213
checkout.branch.set_parent(branch.base)
214
zap('checkout', policy=StoreChanges, remove_branch=True)
216
def test_zap_branch_with_unique_revision(self):
217
parent = self.make_branch_and_tree('parent')
219
new_branch = self.make_branch('new')
220
new_branch.set_parent(parent.branch.base)
221
checkout = new_branch.create_checkout('checkout', lightweight=True)
222
checkout.commit('unique')
223
self.assertRaises(ParentMissingRevisions, zap, 'checkout',
226
return makeSuite(TestZap)