Merge lp:~sergiusens/snapcraft/clean into lp:~snappy-dev/snapcraft/core

Proposed by Sergio Schvezov on 2015-09-17
Status: Merged
Approved by: John Lenton on 2015-09-17
Approved revision: 176
Merged at revision: 175
Proposed branch: lp:~sergiusens/snapcraft/clean
Merge into: lp:~snappy-dev/snapcraft/core
Diff against target: 242 lines (+158/-1)
7 files modified
integration-tests/units/jobs.pxu (+16/-0)
snapcraft/__init__.py (+1/-0)
snapcraft/cmds.py (+21/-0)
snapcraft/common.py (+4/-0)
snapcraft/main.py (+3/-0)
snapcraft/plugin.py (+2/-1)
snapcraft/tests/test_cmds.py (+111/-0)
To merge this branch: bzr merge lp:~sergiusens/snapcraft/clean
Reviewer Review Type Date Requested Status
John Lenton 2015-09-17 Approve on 2015-09-17
Review via email: mp+271487@code.launchpad.net

Commit Message

Add a clean command

To post a comment you must log in.
lp:~sergiusens/snapcraft/clean updated on 2015-09-17
174. By Sergio Schvezov on 2015-09-17

Use %r for proper string quoting

Leo Arias (elopio) wrote :

This is good, and works.

From our discussion on IRC, I'd like to see one integration test calling clean. And delete the parts dir if all the parts were removed by clean.

<sergiusens> elopio, like for every test possible?
<elopio> sergiusens: no, just one execution of clean.
<sergiusens> elopio, as in, for every test run in there?
<sergiusens> elopio, ok, I don't mind that :-)
<elopio> sergiusens: the parts directory is not removed.
<elopio> is that on purpose?
<sergiusens> elopio, yes; inside parts you can also have local plugins
<sergiusens> elopio, it's sort of a safe haven for things
<elopio> sergiusens: what about removing it if it's empty?
<sergiusens> elopio, so instead of removing everything I thought it be safer this way
<sergiusens> elopio, yeah, that can be arranged
<elopio> just feels weird to leave behind only one empty dir.

lp:~sergiusens/snapcraft/clean updated on 2015-09-17
175. By Sergio Schvezov on 2015-09-17

Remove parts if empty

176. By Sergio Schvezov on 2015-09-17

plainbox test for clean

John Lenton (chipaca) wrote :

Nice. Thanks.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'integration-tests/units/jobs.pxu'
2--- integration-tests/units/jobs.pxu 2015-09-17 06:24:37 +0000
3+++ integration-tests/units/jobs.pxu 2015-09-17 18:08:11 +0000
4@@ -90,6 +90,22 @@
5 ${SNAPCRAFT} stage
6 test "$(./stage/bin/test)" = "Hello world"
7
8+id: snapcraft/normal/simple-make-clean
9+plugin: shell
10+estimated_duration: 0.3
11+command:
12+ set -ex
13+ cp -rT $PLAINBOX_PROVIDER_DATA/simple-make .
14+ ${SNAPCRAFT} snap
15+ test "$(./stage/bin/test)" = "Hello world"
16+ test -d ./stage
17+ test -d ./parts
18+ test -d ./snap
19+ ${SNAPCRAFT} clean
20+ test ! -d ./stage
21+ test ! -d ./parts
22+ test ! -d ./snap
23+
24 id: snapcraft/normal/simple-cmake
25 plugin: shell
26 estimated_duration: 0.3
27
28=== modified file 'snapcraft/__init__.py'
29--- snapcraft/__init__.py 2015-09-15 21:02:02 +0000
30+++ snapcraft/__init__.py 2015-09-17 18:08:11 +0000
31@@ -34,6 +34,7 @@
32 def __init__(self, name, options):
33 self.name = name
34 self.options = options
35+ self.partdir = os.path.join(os.getcwd(), "parts", self.name)
36 self.sourcedir = os.path.join(os.getcwd(), "parts", self.name, "src")
37 self.builddir = os.path.join(os.getcwd(), "parts", self.name, "build")
38 self.ubuntudir = os.path.join(os.getcwd(), "parts", self.name, 'ubuntu')
39
40=== modified file 'snapcraft/cmds.py'
41--- snapcraft/cmds.py 2015-09-17 13:21:49 +0000
42+++ snapcraft/cmds.py 2015-09-17 18:08:11 +0000
43@@ -228,6 +228,27 @@
44 qemu.kill()
45
46
47+def clean(args):
48+ config = _load_config()
49+
50+ for part in config.all_parts:
51+ logger.info('Cleaning up for part %r', part.names()[0])
52+ if os.path.exists(part.partdir):
53+ shutil.rmtree(part.partdir)
54+
55+ # parts dir does not contain only generated code.
56+ if not os.listdir(common.get_partsdir()):
57+ os.rmdir(common.get_partsdir())
58+
59+ logger.info('Cleaning up staging area')
60+ if os.path.exists(common.get_stagedir()):
61+ shutil.rmtree(common.get_stagedir())
62+
63+ logger.info('Cleaning up snapping area')
64+ if os.path.exists(common.get_snapdir()):
65+ shutil.rmtree(common.get_snapdir())
66+
67+
68 def _check_for_collisions(parts):
69 parts_files = {}
70 for part in parts:
71
72=== modified file 'snapcraft/common.py'
73--- snapcraft/common.py 2015-08-28 20:26:41 +0000
74+++ snapcraft/common.py 2015-09-17 18:08:11 +0000
75@@ -67,6 +67,10 @@
76 return _arch_triplet
77
78
79+def get_partsdir():
80+ return os.path.join(os.getcwd(), 'parts')
81+
82+
83 def get_stagedir():
84 return os.path.join(os.getcwd(), 'stage')
85
86
87=== modified file 'snapcraft/main.py'
88--- snapcraft/main.py 2015-07-30 14:45:01 +0000
89+++ snapcraft/main.py 2015-09-17 18:08:11 +0000
90@@ -48,6 +48,9 @@
91 parser = subparsers.add_parser('run', help='run snap in kvm', add_help=False)
92 parser.set_defaults(func=snapcraft.cmds.run)
93
94+ parser = subparsers.add_parser('clean', help='clean up the environment (to start from scratch)')
95+ parser.set_defaults(func=snapcraft.cmds.clean)
96+
97 parser = subparsers.add_parser('pull', help='get sources', parents=[cmd_parser])
98 parser.set_defaults(func=snapcraft.cmds.cmd)
99
100
101=== modified file 'snapcraft/plugin.py'
102--- snapcraft/plugin.py 2015-09-17 13:10:10 +0000
103+++ snapcraft/plugin.py 2015-09-17 18:08:11 +0000
104@@ -63,7 +63,8 @@
105 self.deps = []
106 self.plugin_name = name
107
108- parts_dir = os.path.join(os.getcwd(), 'parts')
109+ parts_dir = common.get_partsdir()
110+ self.partdir = os.path.join(parts_dir, part_name)
111 self.sourcedir = os.path.join(parts_dir, part_name, 'src')
112 self.builddir = os.path.join(parts_dir, part_name, 'build')
113 self.ubuntudir = os.path.join(parts_dir, part_name, 'ubuntu')
114
115=== modified file 'snapcraft/tests/test_cmds.py'
116--- snapcraft/tests/test_cmds.py 2015-09-17 12:41:20 +0000
117+++ snapcraft/tests/test_cmds.py 2015-09-17 18:08:11 +0000
118@@ -23,6 +23,7 @@
119
120 from snapcraft import (
121 cmds,
122+ common,
123 tests
124 )
125
126@@ -78,6 +79,116 @@
127 fake_logger.output)
128
129
130+class CleanTestCase(tests.TestCase):
131+
132+ def setUp(self):
133+ super().setUp()
134+
135+ patcher = mock.patch('shutil.rmtree')
136+ self.mock_rmtree = patcher.start()
137+ self.addCleanup(patcher.stop)
138+
139+ patcher = mock.patch('os.path.exists')
140+ self.mock_exists = patcher.start()
141+ self.addCleanup(patcher.stop)
142+
143+ patcher = mock.patch('os.listdir')
144+ self.mock_listdir = patcher.start()
145+ self.mock_listdir.return_value = []
146+ self.addCleanup(patcher.stop)
147+
148+ patcher = mock.patch('os.rmdir')
149+ self.mock_rmdir = patcher.start()
150+ self.addCleanup(patcher.stop)
151+
152+ class FakePart:
153+
154+ def __init__(self, name, partdir):
155+ self.name = name
156+ self.partdir = partdir
157+
158+ def names(self):
159+ return [self.name, ]
160+
161+ class FakeConfig:
162+ all_parts = [
163+ FakePart('part1', 'partdir1'),
164+ FakePart('part2', 'partdir2'),
165+ FakePart('part3', 'partdir3'),
166+ ]
167+
168+ self.fake_config = FakeConfig()
169+
170+ patcher = mock.patch('snapcraft.cmds._load_config')
171+ self.mock_load_config = patcher.start()
172+ self.mock_load_config.return_value = self.fake_config
173+ self.addCleanup(patcher.stop)
174+
175+ def test_clean_all(self):
176+ cmds.clean({})
177+
178+ self.mock_exists.assert_has_calls([
179+ mock.call('partdir1'),
180+ mock.call().__bool__(),
181+ mock.call('partdir2'),
182+ mock.call().__bool__(),
183+ mock.call('partdir3'),
184+ mock.call().__bool__(),
185+ mock.call(common.get_stagedir()),
186+ mock.call().__bool__(),
187+ mock.call(common.get_snapdir()),
188+ mock.call().__bool__(),
189+ ])
190+
191+ self.mock_rmtree.assert_has_calls([
192+ mock.call('partdir1'),
193+ mock.call('partdir2'),
194+ mock.call('partdir3'),
195+ mock.call(common.get_stagedir()),
196+ mock.call(common.get_snapdir()),
197+ ])
198+
199+ self.mock_rmdir.assert_called_once_with(common.get_partsdir())
200+
201+ def test_everything_is_clean(self):
202+ self.mock_exists.return_value = False
203+
204+ cmds.clean({})
205+
206+ self.mock_exists.assert_has_calls([
207+ mock.call('partdir1'),
208+ mock.call('partdir2'),
209+ mock.call('partdir3'),
210+ mock.call(common.get_stagedir()),
211+ mock.call(common.get_snapdir()),
212+ ])
213+
214+ self.mock_rmdir.assert_called_once_with(common.get_partsdir())
215+
216+ self.assertFalse(self.mock_rmtree.called)
217+
218+ def test_no_parts_defined(self):
219+ self.fake_config.all_parts = []
220+
221+ self.mock_load_config.return_value = self.fake_config
222+
223+ cmds.clean({})
224+
225+ self.mock_exists.assert_has_calls([
226+ mock.call(common.get_stagedir()),
227+ mock.call().__bool__(),
228+ mock.call(common.get_snapdir()),
229+ mock.call().__bool__(),
230+ ])
231+
232+ self.mock_rmtree.assert_has_calls([
233+ mock.call(common.get_stagedir()),
234+ mock.call(common.get_snapdir()),
235+ ])
236+
237+ self.mock_rmdir.assert_called_once_with(common.get_partsdir())
238+
239+
240 class InitTestCase(tests.TestCase):
241
242 def test_init_with_existing_snapcraft_yaml_must_fail(self):

Subscribers

People subscribed via source and target branches