Merge lp:~mterry/quickly/overwrite into lp:quickly
- overwrite
- Merge into trunk
Status: | Merged |
---|---|
Merge reported by: | Didier Roche-Tolomelli |
Merged at revision: | not available |
Proposed branch: | lp:~mterry/quickly/overwrite |
Merge into: | lp:quickly |
Prerequisite: | lp:~robert-ancell/quickly/drop-lpi |
Diff against target: |
858 lines (+317/-166) 21 files modified
data/templates/ubuntu-application/create.py (+2/-34) data/templates/ubuntu-application/project_root/bin/project_name (+2/-0) data/templates/ubuntu-application/project_root/python_lib/AboutDialog.py (+2/-0) data/templates/ubuntu-application/project_root/python_lib/Builder.py (+2/-0) data/templates/ubuntu-application/project_root/python_lib/PreferencesDialog.py (+2/-0) data/templates/ubuntu-application/project_root/python_lib/Window.py (+2/-0) data/templates/ubuntu-application/project_root/python_lib/__init__.py (+2/-0) data/templates/ubuntu-application/project_root/python_lib/helpers.py (+2/-0) data/templates/ubuntu-application/project_root/python_lib/python_nameconfig.py (+1/-4) data/templates/ubuntu-application/project_root/setup.py (+18/-13) data/templates/ubuntu-application/test/apport/apport.sh (+37/-6) data/templates/ubuntu-application/test/gtk3upgrade.sh (+4/-0) data/templates/ubuntu-application/test/overwrite.sh (+85/-0) data/templates/ubuntu-application/test/package.sh (+0/-9) data/templates/ubuntu-application/upgrade.py (+23/-55) data/templates/ubuntu-cli/commandsconfig (+1/-1) data/templates/ubuntu-cli/test/overwrite.sh (+36/-0) data/templates/ubuntu-flash-game/create.py (+3/-31) quickly/templatetools.py (+91/-11) quickly/test/completion.sh (+1/-1) quickly/test/help.sh (+1/-1) |
To merge this branch: | bzr merge lp:~mterry/quickly/overwrite |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Didier Roche-Tolomelli | Needs Information | ||
Review via email: mp+111315@code.launchpad.net |
Commit message
Description of the change
A long while back, for natty, we decided to change the project_root layout to more clearly delineate what was quickly-owned code and what was user-modifiable code.
Specifically, quickly owns bin/, parts of setup.py, and python_lib/.
The intention was to make it easier for us as maintainers, because we didn't need to support user modifications to those files. It is a real problem. Drive-by contributions rarely consider upgrade.py. Even among maintainers, we often forget it or do it wrong.
This branch finally makes the dream a reality. Any quickly-owned code is automatically updated to the latest template version as needed. It's careful to only do it if a new template version is available.
This will let us make more changes and more complicated changes easier. More velocity!
Note that a user that wants to work-around quickly's code can still do so! They get a section in setup.py that they own. And they have a single entry point in python/ where they can do what they want.
Note that we still have to be careful for any changes we make to python/. But at least this gives us a lot more flexibility than before.
Tony Byrne (tony-badwolf) wrote : | # |
Tony Byrne (tony-badwolf) wrote : | # |
A better overwrite algorithm
Use bzr to extract version 1 of project to a temp directory - this contains only files created by quickly
compare file with current version
upgrade can overwrite if no changes
If file changed by user he probably has a good reason so we need a stategy
Write a "Can't upgrade because ..." message
Offer a automatic patch submission to quickly team to look at changes
Or
bzr commit -m 'pre upgrade'
upgrade --force overwrite
bzr commit -m 'post upgrade'
bzr diff
This point is one for the quickly talk list
Didier Roche-Tolomelli (didrocks) wrote : | # |
ok, I agree (see the hangouts on Quickly reboot) that overwriting and owning those files makes totally sense.
I however have some questions/spotted some errors (I guess) in that branch:
So, those files are licensed, I think:
1. they shouldn't
2. this introduces some unecessary diff and unecessary check we need to do. Like this code:
590 + # First, don't write anything if we don't need to
591 + if os.path.
592 + with file(filename, 'r') as ftest:
593 + if ftest.read() == contents:
594 + return
Would never be executed right? Everytime the boiler plate files will be different?
So maybe just putting those files in the public domain and removing the #BEGIN/END license stenzas.
(but in that case, we need to do something to upgade existing projects).
also, the python_
Maybe we should have a Config.py in private_lib, which define some kind of class, and python_
(Basically, that's how I see private_lib/: only super class which defines and automate some code, and then the lib/ itself inheriting from those).
What do you think?
Michael Terry (mterry) wrote : | # |
You're right that the 'should we copy over this file' check is a little pointless for files that are licensed. But it's not really a problem if we copy it over and license it over again. It will end up the same file and won't show any differences in 'bzr diff'.
I could change the license bits of the quickly-owned bits to say public domain and nothing else [you mention needing to do something to upgrade existing projects -- but nope! that's what this branch would do. :)]. But it doesn't seem worth the change just to avoid a bit of file copying during the new-version-upgrade step.
The python_
Michael Terry (mterry) wrote : | # |
You're right that the 'should we copy over this file' check is a little pointless for files that are licensed. But it's not really a problem if we copy it over and license it over again. It will end up the same file and won't show any differences in 'bzr diff'.
I could change the license bits of the quickly-owned bits to say public domain and nothing else [you mention needing to do something to upgrade existing projects -- but nope! that's what this branch would do. :)]. But it doesn't seem worth the change just to avoid a bit of file copying during the new-version-upgrade step.
The python_
That will leave VERSION as the version when running under quickly run. But I think that's OK and actually kind of like it (the idea that doesn't have a version until you release it with one).
Michael Terry (mterry) wrote : | # |
Whoops, sorry for double messages. I've fixed it. Please re-review.
Michael Terry (mterry) wrote : | # |
I just realized that didrocks is on vacation. Well, I wanted to get this in today for busy-during-FF-week reasons, so I'm going to push this in.
Didrocks approved the basic idea and most of the code. The remaining issues can be dealt with as bug fixes after FF.
I'll leave this merge open for further discussion into a real signoff happens.
Didier Roche-Tolomelli (didrocks) wrote : | # |
resetted to "merge", really happy with the branch. I have a stupid idea about how to easy dealing to not update the copyright in this file, https:/
Thanks for the quick fixes! Looking good :)
Preview Diff
1 | === modified file 'data/templates/ubuntu-application/create.py' |
2 | --- data/templates/ubuntu-application/create.py 2012-02-16 07:24:06 +0000 |
3 | +++ data/templates/ubuntu-application/create.py 2012-08-17 20:23:19 +0000 |
4 | @@ -64,40 +64,7 @@ |
5 | |
6 | os.chdir(project_name) |
7 | |
8 | -# get origin path |
9 | -pathname = templatetools.get_template_path_from_project() |
10 | -abs_path_project_root = os.path.join(pathname, 'project_root') |
11 | - |
12 | -python_name = templatetools.python_name(project_name) |
13 | -sentence_name, camel_case_name = templatetools.conventional_names(project_name) |
14 | -substitutions = (("project_name",project_name), |
15 | - ("camel_case_name",camel_case_name), |
16 | - ("python_name",python_name), |
17 | - ("sentence_name",sentence_name),) |
18 | - |
19 | - |
20 | -for root, dirs, files in os.walk(abs_path_project_root): |
21 | - try: |
22 | - relative_dir = root.split('project_root/')[1] |
23 | - except: |
24 | - relative_dir = "" |
25 | - # python dir should be replace by python_name (project "pythonified" name) |
26 | - if relative_dir.startswith('python'): |
27 | - relative_dir = relative_dir.replace('python', python_name) |
28 | - |
29 | - for directory in dirs: |
30 | - if directory.startswith('python'): |
31 | - directory = directory.replace('python', python_name) |
32 | - os.mkdir(os.path.join(relative_dir, directory)) |
33 | - for filename in files: |
34 | - templatetools.file_from_template(root, filename, relative_dir, substitutions) |
35 | - |
36 | -# set the mode to executable for executable file |
37 | -exec_file = os.path.join('bin', project_name) |
38 | -try: |
39 | - os.chmod(exec_file, 0755) |
40 | -except: |
41 | - pass |
42 | +templatetools.copy_dirs_from_template() |
43 | |
44 | # add it to revision control |
45 | print _("Creating bzr repository and committing") |
46 | @@ -120,6 +87,7 @@ |
47 | env['XDG_DATA_DIRS'] = datadir |
48 | |
49 | # run the new application if X display |
50 | +exec_file = os.path.join('bin', project_name) |
51 | if templatetools.is_X_display() and os.path.isfile(exec_file): |
52 | print _("Launching your newly created project!") |
53 | subprocess.call(['./' + project_name], cwd='bin/', env=env) |
54 | |
55 | === modified file 'data/templates/ubuntu-application/project_root/bin/project_name' (properties changed: -x to +x) |
56 | --- data/templates/ubuntu-application/project_root/bin/project_name 2012-05-25 17:48:13 +0000 |
57 | +++ data/templates/ubuntu-application/project_root/bin/project_name 2012-08-17 20:23:19 +0000 |
58 | @@ -4,6 +4,8 @@ |
59 | # This file is in the public domain |
60 | ### END LICENSE |
61 | |
62 | +### DO NOT EDIT THIS FILE ### |
63 | + |
64 | import sys |
65 | import os |
66 | |
67 | |
68 | === modified file 'data/templates/ubuntu-application/project_root/python_lib/AboutDialog.py' |
69 | --- data/templates/ubuntu-application/project_root/python_lib/AboutDialog.py 2011-06-08 19:20:41 +0000 |
70 | +++ data/templates/ubuntu-application/project_root/python_lib/AboutDialog.py 2012-08-17 20:23:19 +0000 |
71 | @@ -3,6 +3,8 @@ |
72 | # This file is in the public domain |
73 | ### END LICENSE |
74 | |
75 | +### DO NOT EDIT THIS FILE ### |
76 | + |
77 | from gi.repository import Gtk # pylint: disable=E0611 |
78 | |
79 | from . helpers import get_builder |
80 | |
81 | === modified file 'data/templates/ubuntu-application/project_root/python_lib/Builder.py' |
82 | --- data/templates/ubuntu-application/project_root/python_lib/Builder.py 2011-12-15 19:49:20 +0000 |
83 | +++ data/templates/ubuntu-application/project_root/python_lib/Builder.py 2012-08-17 20:23:19 +0000 |
84 | @@ -3,6 +3,8 @@ |
85 | # This file is in the public domain |
86 | ### END LICENSE |
87 | |
88 | +### DO NOT EDIT THIS FILE ### |
89 | + |
90 | '''Enhances builder connections, provides object to access glade objects''' |
91 | |
92 | from gi.repository import GObject, Gtk # pylint: disable=E0611 |
93 | |
94 | === modified file 'data/templates/ubuntu-application/project_root/python_lib/PreferencesDialog.py' |
95 | --- data/templates/ubuntu-application/project_root/python_lib/PreferencesDialog.py 2011-11-07 21:55:54 +0000 |
96 | +++ data/templates/ubuntu-application/project_root/python_lib/PreferencesDialog.py 2012-08-17 20:23:19 +0000 |
97 | @@ -3,6 +3,8 @@ |
98 | # This file is in the public domain |
99 | ### END LICENSE |
100 | |
101 | +### DO NOT EDIT THIS FILE ### |
102 | + |
103 | """this dialog adjusts values in gsettings |
104 | """ |
105 | |
106 | |
107 | === modified file 'data/templates/ubuntu-application/project_root/python_lib/Window.py' |
108 | --- data/templates/ubuntu-application/project_root/python_lib/Window.py 2012-08-17 20:23:19 +0000 |
109 | +++ data/templates/ubuntu-application/project_root/python_lib/Window.py 2012-08-17 20:23:19 +0000 |
110 | @@ -3,6 +3,8 @@ |
111 | # This file is in the public domain |
112 | ### END LICENSE |
113 | |
114 | +### DO NOT EDIT THIS FILE ### |
115 | + |
116 | from gi.repository import Gio, Gtk # pylint: disable=E0611 |
117 | import logging |
118 | logger = logging.getLogger('python_name_lib') |
119 | |
120 | === modified file 'data/templates/ubuntu-application/project_root/python_lib/__init__.py' |
121 | --- data/templates/ubuntu-application/project_root/python_lib/__init__.py 2011-11-07 21:55:54 +0000 |
122 | +++ data/templates/ubuntu-application/project_root/python_lib/__init__.py 2012-08-17 20:23:19 +0000 |
123 | @@ -3,6 +3,8 @@ |
124 | # This file is in the public domain |
125 | ### END LICENSE |
126 | |
127 | +### DO NOT EDIT THIS FILE ### |
128 | + |
129 | '''facade - makes python_name_lib package easy to refactor |
130 | |
131 | while keeping its api constant''' |
132 | |
133 | === modified file 'data/templates/ubuntu-application/project_root/python_lib/helpers.py' |
134 | --- data/templates/ubuntu-application/project_root/python_lib/helpers.py 2011-11-08 02:27:24 +0000 |
135 | +++ data/templates/ubuntu-application/project_root/python_lib/helpers.py 2012-08-17 20:23:19 +0000 |
136 | @@ -3,6 +3,8 @@ |
137 | # This file is in the public domain |
138 | ### END LICENSE |
139 | |
140 | +### DO NOT EDIT THIS FILE ### |
141 | + |
142 | """Helpers for an Ubuntu application.""" |
143 | import logging |
144 | import os |
145 | |
146 | === modified file 'data/templates/ubuntu-application/project_root/python_lib/python_nameconfig.py' |
147 | --- data/templates/ubuntu-application/project_root/python_lib/python_nameconfig.py 2011-03-31 15:19:55 +0000 |
148 | +++ data/templates/ubuntu-application/project_root/python_lib/python_nameconfig.py 2012-08-17 20:23:19 +0000 |
149 | @@ -3,10 +3,7 @@ |
150 | # This file is in the public domain |
151 | ### END LICENSE |
152 | |
153 | -# THIS IS camel_case_name CONFIGURATION FILE |
154 | -# YOU CAN PUT THERE SOME GLOBAL VALUE |
155 | -# Do not touch unless you know what you're doing. |
156 | -# you're warned :) |
157 | +### DO NOT EDIT THIS FILE ### |
158 | |
159 | __all__ = [ |
160 | 'project_path_not_found', |
161 | |
162 | === modified file 'data/templates/ubuntu-application/project_root/setup.py' |
163 | --- data/templates/ubuntu-application/project_root/setup.py 2011-03-31 15:19:55 +0000 |
164 | +++ data/templates/ubuntu-application/project_root/setup.py 2012-08-17 20:23:19 +0000 |
165 | @@ -16,12 +16,13 @@ |
166 | sys.exit(1) |
167 | assert DistUtilsExtra.auto.__version__ >= '2.18', 'needs DistUtilsExtra.auto >= 2.18' |
168 | |
169 | -def update_config(values = {}): |
170 | +def update_config(libdir, values = {}): |
171 | |
172 | + filename = os.path.join(libdir, 'python_name_lib/python_nameconfig.py') |
173 | oldvalues = {} |
174 | try: |
175 | - fin = file('python_name_lib/python_nameconfig.py', 'r') |
176 | - fout = file(fin.name + '.new', 'w') |
177 | + fin = file(filename, 'r') |
178 | + fout = file(filename + '.new', 'w') |
179 | |
180 | for line in fin: |
181 | fields = line.split(' = ') # Separate variable from value |
182 | @@ -35,38 +36,42 @@ |
183 | fin.close() |
184 | os.rename(fout.name, fin.name) |
185 | except (OSError, IOError), e: |
186 | - print ("ERROR: Can't find python_name_lib/python_nameconfig.py") |
187 | + print ("ERROR: Can't find %s" % filename) |
188 | sys.exit(1) |
189 | return oldvalues |
190 | |
191 | |
192 | -def update_desktop_file(datadir): |
193 | +def update_desktop_file(installdatadir, prefix): |
194 | |
195 | + filename = os.path.join(installdatadir, 'share', 'applications', |
196 | + 'project_name.desktop') |
197 | try: |
198 | - fin = file('project_name.desktop.in', 'r') |
199 | - fout = file(fin.name + '.new', 'w') |
200 | + fin = file(filename, 'r') |
201 | + fout = file(filename + '.new', 'w') |
202 | |
203 | for line in fin: |
204 | if 'Icon=' in line: |
205 | - line = "Icon=%s\n" % (datadir + 'media/project_name.svg') |
206 | + line = "Icon=%s\n" % os.path.join(prefix, 'share', |
207 | + 'project_name', 'media', |
208 | + 'project_name.svg') |
209 | fout.write(line) |
210 | fout.flush() |
211 | fout.close() |
212 | fin.close() |
213 | os.rename(fout.name, fin.name) |
214 | except (OSError, IOError), e: |
215 | - print ("ERROR: Can't find project_name.desktop.in") |
216 | + print ("ERROR: Can't find %s" % filename) |
217 | sys.exit(1) |
218 | |
219 | |
220 | class InstallAndUpdateDataDirectory(DistUtilsExtra.auto.install_auto): |
221 | def run(self): |
222 | + DistUtilsExtra.auto.install_auto.run(self) |
223 | + |
224 | values = {'__python_name_data_directory__': "'%s'" % (self.prefix + '/share/project_name/'), |
225 | '__version__': "'%s'" % self.distribution.get_version()} |
226 | - previous_values = update_config(values) |
227 | - update_desktop_file(self.prefix + '/share/project_name/') |
228 | - DistUtilsExtra.auto.install_auto.run(self) |
229 | - update_config(previous_values) |
230 | + update_config(self.install_lib, values) |
231 | + update_desktop_file(self.install_data, self.prefix) |
232 | |
233 | |
234 | |
235 | |
236 | === modified file 'data/templates/ubuntu-application/test/apport/apport.sh' |
237 | --- data/templates/ubuntu-application/test/apport/apport.sh 2012-08-17 20:23:19 +0000 |
238 | +++ data/templates/ubuntu-application/test/apport/apport.sh 2012-08-17 20:23:19 +0000 |
239 | @@ -242,6 +242,10 @@ |
240 | # Committed revision 4. |
241 | |
242 | quickly upgrade 0.3 |
243 | +# Note: This is the first time you have run Quickly since it has been updated. |
244 | +# Quickly will now upgrade its files (bin/*, test_project_lib/*, and setup.py). |
245 | +# But first it will save your project. View Quickly's changes by running: |
246 | +# bzr diff |
247 | |
248 | bzr status |
249 | |
250 | @@ -263,13 +267,17 @@ |
251 | # deleted etc/apport/crashdb.conf.d |
252 | # missing etc/apport/crashdb.conf.d/test-project-crashdb.conf |
253 | # deleted etc/apport/crashdb.conf.d/test-project-crashdb.conf |
254 | -# Committed revision 5. |
255 | +# Committed revision 6. |
256 | |
257 | bzr status |
258 | |
259 | quickly upgrade 0.3 |
260 | # Creating new apport crashdb configuration |
261 | # Creating new apport hooks |
262 | +# Note: This is the first time you have run Quickly since it has been updated. |
263 | +# Quickly will now upgrade its files (bin/*, test_project_lib/*, and setup.py). |
264 | +# But first it will save your project. View Quickly's changes by running: |
265 | +# bzr diff |
266 | |
267 | cat etc/apport/crashdb.conf.d/test-project-crashdb.conf |
268 | # ### BEGIN LICENSE |
269 | @@ -307,6 +315,10 @@ |
270 | quickly upgrade 0.3 |
271 | # Creating new apport crashdb configuration |
272 | # Creating new apport hooks |
273 | +# Note: This is the first time you have run Quickly since it has been updated. |
274 | +# Quickly will now upgrade its files (bin/*, test_project_lib/*, and setup.py). |
275 | +# But first it will save your project. View Quickly's changes by running: |
276 | +# bzr diff |
277 | |
278 | cp "$TEST_SCRIPT_DIR/TestProjectWindow.ui.no_gtk-about" ./data/ui/TestProjectWindow.ui |
279 | |
280 | @@ -318,18 +330,37 @@ |
281 | |
282 | bzr commit -m "Committing after removing all lpi integration" |
283 | # Committing to: /tmp/test-project/ |
284 | +# missing apport |
285 | +# deleted apport |
286 | +# missing etc |
287 | +# deleted etc |
288 | +# missing apport/source_test-project.py |
289 | +# deleted apport/source_test-project.py |
290 | # modified data/ui/TestProjectWindow.ui |
291 | -# Committed revision 6. |
292 | +# missing etc/apport |
293 | +# deleted etc/apport |
294 | +# missing etc/apport/crashdb.conf.d |
295 | +# deleted etc/apport/crashdb.conf.d |
296 | +# missing etc/apport/crashdb.conf.d/test-project-crashdb.conf |
297 | +# deleted etc/apport/crashdb.conf.d/test-project-crashdb.conf |
298 | +# Committed revision 9. |
299 | |
300 | quickly upgrade 0.3 |
301 | # Creating new apport crashdb configuration |
302 | # Creating new apport hooks |
303 | +# Note: This is the first time you have run Quickly since it has been updated. |
304 | +# Quickly will now upgrade its files (bin/*, test_project_lib/*, and setup.py). |
305 | +# But first it will save your project. View Quickly's changes by running: |
306 | +# bzr diff |
307 | |
308 | -bzr status |
309 | -# unknown: |
310 | -# apport/ |
311 | -# etc/ |
312 | +ls -dF apport etc |
313 | +# apport/ |
314 | +# etc/ |
315 | |
316 | rm ./data/ui/TestProjectWindow.ui |
317 | |
318 | quickly upgrade 0.3 |
319 | +# Note: This is the first time you have run Quickly since it has been updated. |
320 | +# Quickly will now upgrade its files (bin/*, test_project_lib/*, and setup.py). |
321 | +# But first it will save your project. View Quickly's changes by running: |
322 | +# bzr diff |
323 | |
324 | === modified file 'data/templates/ubuntu-application/test/gtk3upgrade.sh' |
325 | --- data/templates/ubuntu-application/test/gtk3upgrade.sh 2011-12-15 21:32:15 +0000 |
326 | +++ data/templates/ubuntu-application/test/gtk3upgrade.sh 2012-08-17 20:23:19 +0000 |
327 | @@ -34,6 +34,10 @@ |
328 | # version = 11.10 |
329 | |
330 | quickly upgrade |
331 | +# Note: This is the first time you have run Quickly since it has been updated. |
332 | +# Quickly will now upgrade its files (bin/*, test_project_lib/*, and setup.py). |
333 | +# But first it will save your project. View Quickly's changes by running: |
334 | +# bzr diff |
335 | |
336 | grep '11\.10' .quickly |
337 | |
338 | |
339 | === added file 'data/templates/ubuntu-application/test/overwrite.sh' |
340 | --- data/templates/ubuntu-application/test/overwrite.sh 1970-01-01 00:00:00 +0000 |
341 | +++ data/templates/ubuntu-application/test/overwrite.sh 2012-08-17 20:23:19 +0000 |
342 | @@ -0,0 +1,85 @@ |
343 | +#!/bin/sh |
344 | + |
345 | +cd /tmp |
346 | + |
347 | +rm -rf test-project |
348 | + |
349 | +quickly create ubuntu-application test-project |
350 | +# Creating bzr repository and committing |
351 | +# Congrats, your new project is setup! cd /tmp/test-project/ to start hacking. |
352 | +# Creating project directory test-project |
353 | + |
354 | +cd test-project |
355 | + |
356 | +sed -i 's/import os/import os #test-blarg/' setup.py |
357 | + |
358 | +(echo "#test-blarg" >> setup.py) |
359 | + |
360 | +(echo "#test-blarg" >> bin/test-project) |
361 | + |
362 | +(echo "#test-blarg" >> test_project/TestProjectWindow.py) |
363 | + |
364 | +(echo "#test-blarg" >> test_project_lib/Window.py) |
365 | + |
366 | +rm test_project_lib/Builder.py |
367 | + |
368 | +cp -a test_project_lib/helpers.py test_project_lib/helpers.py.test-bak |
369 | + |
370 | +grep -R "#test-blarg" . |
371 | +# ./test_project_lib/Window.py:#test-blarg |
372 | +# ./setup.py:import os #test-blarg |
373 | +# ./setup.py:#test-blarg |
374 | +# ./bin/test-project:#test-blarg |
375 | +# ./test_project/TestProjectWindow.py:#test-blarg |
376 | + |
377 | +quickly upgrade 11.04 |
378 | +# Note: This is the first time you have run Quickly since it has been updated. |
379 | +# Quickly will now upgrade its files (bin/*, test_project_lib/*, and setup.py). |
380 | +# But first it will save your project. View Quickly's changes by running: |
381 | +# bzr diff |
382 | + |
383 | +(test "$(ls --full-time test_project_lib/helpers.py)" = "$(ls --full-time test_project_lib/helpers.py.test-bak | sed 's/\.test-bak//')" && echo "Same") |
384 | +# Same |
385 | + |
386 | +ls test_project_lib/Builder.py |
387 | +# test_project_lib/Builder.py |
388 | + |
389 | +grep -R "#test-blarg" . |
390 | +# ./setup.py:#test-blarg |
391 | +# ./test_project/TestProjectWindow.py:#test-blarg |
392 | + |
393 | +grep python_name setup.py test_project_lib/Builder.py |
394 | + |
395 | +## A run to see if we futz with setup.py when we don't need to |
396 | + |
397 | +cp -a setup.py setup.py.test-bak |
398 | + |
399 | +rm test_project_lib/Builder.py |
400 | + |
401 | +## We also make sure that we correctly keep the wrapper executable |
402 | + |
403 | +rm bin/test-project |
404 | + |
405 | +quickly upgrade 11.04 |
406 | +# Note: This is the first time you have run Quickly since it has been updated. |
407 | +# Quickly will now upgrade its files (bin/*, test_project_lib/*, and setup.py). |
408 | +# But first it will save your project. View Quickly's changes by running: |
409 | +# bzr diff |
410 | + |
411 | +(test "$(ls --full-time setup.py)" = "$(ls --full-time setup.py.test-bak | sed 's/\.test-bak//')" && echo "Same") |
412 | +# Same |
413 | + |
414 | +ls test_project_lib/Builder.py |
415 | +# test_project_lib/Builder.py |
416 | + |
417 | +ls -F bin/test-project |
418 | +# bin/test-project* |
419 | + |
420 | +## A run to see if we change anything when version hasn't changed |
421 | + |
422 | +rm test_project_lib/Builder.py |
423 | + |
424 | +quickly upgrade |
425 | + |
426 | +ls test_project_lib/Builder.py |
427 | +# ls: cannot access test_project_lib/Builder.py: No such file or directory |
428 | |
429 | === modified file 'data/templates/ubuntu-application/test/package.sh' |
430 | --- data/templates/ubuntu-application/test/package.sh 2012-05-25 18:45:02 +0000 |
431 | +++ data/templates/ubuntu-application/test/package.sh 2012-08-17 20:23:19 +0000 |
432 | @@ -21,18 +21,9 @@ |
433 | # Ubuntu package has been successfully created in ../test-project_0.1_all.deb |
434 | |
435 | bzr status |
436 | -# modified: |
437 | -# test-project.desktop.in |
438 | # unknown: |
439 | # po/ |
440 | |
441 | -bzr diff --diff-options="-e" |
442 | -# === modified file 'test-project.desktop.in' |
443 | -# 6c |
444 | -# Icon=/usr/share/test-project/media/test-project.svg |
445 | -# . |
446 | -# |
447 | - |
448 | ls debian |
449 | # changelog |
450 | # compat |
451 | |
452 | === modified file 'data/templates/ubuntu-application/upgrade.py' |
453 | --- data/templates/ubuntu-application/upgrade.py 2012-08-17 20:23:19 +0000 |
454 | +++ data/templates/ubuntu-application/upgrade.py 2012-08-17 20:23:19 +0000 |
455 | @@ -25,6 +25,7 @@ |
456 | |
457 | from internal import quicklyutils |
458 | from quickly import commands, configurationhandler, templatetools |
459 | +import license |
460 | |
461 | import gettext |
462 | from gettext import gettext as _ |
463 | @@ -113,9 +114,9 @@ |
464 | pass |
465 | # update config file to add __license__ |
466 | try: |
467 | - license = quicklyutils.get_setup_value('license') |
468 | + setup_license = quicklyutils.get_setup_value('license') |
469 | except quicklyutils.cant_deal_with_setup_value: |
470 | - license = '' |
471 | + setup_license = '' |
472 | try: |
473 | skip = 0 |
474 | config_file = '%s/%sconfig.py' % (python_name, python_name) |
475 | @@ -134,7 +135,7 @@ |
476 | continue |
477 | if fields[0] == '__%s_data_directory__' % python_name: |
478 | fout.write(line) |
479 | - line = "__license__ = '%s'\n" % license |
480 | + line = "__license__ = '%s'\n" % setup_license |
481 | if "get_data_file(*path_segments):" in line: |
482 | data_file_function_found = True |
483 | skip = 9 |
484 | @@ -173,15 +174,6 @@ |
485 | if lp_project_name is not None: |
486 | internal.apportutils.update_apport(project_name, lp_project_name, lp_project_name) |
487 | |
488 | - # new dialog file needs helpers.py |
489 | - if not os.path.isfile('%s/helpers.py' % python_name) and os.path.isdir(python_name): |
490 | - source_dir = os.path.join(os.path.dirname(__file__), 'project_root', |
491 | - 'python') |
492 | - templatetools.file_from_template(source_dir, |
493 | - "helpers.py", |
494 | - python_name, |
495 | - substitutions) |
496 | - |
497 | if project_version < '0.4.3': |
498 | ## update dependencies format |
499 | if 'dependencies' in configurationhandler.project_config \ |
500 | @@ -196,49 +188,6 @@ |
501 | # Use full modelines for all python files |
502 | sedline = "sed -i 's/-\*- coding: utf-8 -\*-/-*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-/'" |
503 | os.system("find . -name '*.py' -exec %s {} \;" % sedline) |
504 | - os.system("%s bin/%s" % (sedline, project_name)) |
505 | - |
506 | -### 11.03 update |
507 | -if project_version < '11.03': |
508 | - # support /opt installation |
509 | - content_to_update = '''python_path = [] |
510 | -if os.path.abspath(__file__).startswith('/opt'): |
511 | - syspath = sys.path[:] # copy to avoid infinite loop in pending objects |
512 | - for path in syspath: |
513 | - opt_path = path.replace('/usr', '/opt/extras.ubuntu.com/%(project_name)s') |
514 | - python_path.insert(0, opt_path) |
515 | - sys.path.insert(0, opt_path) |
516 | -if (os.path.exists(os.path.join(PROJECT_ROOT_DIRECTORY, '%(python_name)s')) |
517 | - and PROJECT_ROOT_DIRECTORY not in sys.path): |
518 | - python_path.insert(0, PROJECT_ROOT_DIRECTORY) |
519 | - sys.path.insert(0, PROJECT_ROOT_DIRECTORY) |
520 | -if python_path: |
521 | - os.putenv('PYTHONPATH', "%%s:%%s" %% (os.getenv('PYTHONPATH', ''), ':'.join(python_path))) # for subprocesses''' % {'python_name' : python_name, 'project_name' : project_name} |
522 | - |
523 | - # projects based on ~/quickly-projects/template-name have no project_version |
524 | - # so only upgrade if really necessary |
525 | - with open("./bin/%s" % project_name) as project_bin: |
526 | - contents = project_bin.read() |
527 | - if not content_to_update in contents: |
528 | - try: |
529 | - templatetools.update_file_content("./bin/%s" % project_name, |
530 | - 'if (os.path.exists(os.path.join(PROJECT_ROOT_DIRECTORY', |
531 | - " os.putenv('PYTHONPATH', PROJECT_ROOT_DIRECTORY) # for subprocesses", |
532 | - content_to_update) |
533 | - except templatetools.CantUpdateFile, e: |
534 | - print _("WARNING: can't update your project to support /opt. This doesn't matter if you don't plan to submit your project to the application review board. Cause is: %s" % e) |
535 | - |
536 | -### 11.09 update (but only through 11.10; later versions don't want this change) |
537 | -if project_version < '11.09' and template_version <= '11.10': |
538 | - filename = './%s_lib/Builder.py' % python_name |
539 | - try: |
540 | - with open(filename) as fileobj: |
541 | - contents = fileobj.read() |
542 | - contents = contents.replace('from gi.repository import GObject', 'import gobject') |
543 | - contents = contents.replace('GObject.', 'gobject.') |
544 | - templatetools.set_file_contents(filename, contents) |
545 | - except IOError: |
546 | - pass |
547 | |
548 | ### EPOCH CHANGE |
549 | ### This is where we upgraded the default projects to GTK3, PyGI, and GSettings. |
550 | @@ -250,5 +199,24 @@ |
551 | 'quickly upgrade' to get rid of this message.""") |
552 | sys.exit(0) |
553 | |
554 | +# Overwrite quickly-owned files as necessary |
555 | +if project_version < template_version: |
556 | + print _( |
557 | +"""Note: This is the first time you have run Quickly since it has been updated. |
558 | +Quickly will now upgrade its files (bin/*, %s_lib/*, and setup.py). |
559 | +But first it will save your project. View Quickly's changes by running: |
560 | +bzr diff""" % python_name) |
561 | + subprocess.call(["bzr", "add", "-q"]) |
562 | + subprocess.call(["bzr", "commit", "--unchanged", "-q", |
563 | + "-m", "Pre-upgrade checkpoint"]) |
564 | + templatetools.copy_dirs_from_template(dirs = ['bin', 'python_lib']) |
565 | + templatetools.copy_setup_py_from_template() |
566 | + try: |
567 | + # License new files as needed |
568 | + license.licensing() |
569 | + except license.LicenceError as e: |
570 | + pass # Don't worry about it, user may not have set it up yet |
571 | + subprocess.call(["bzr", "add", "-q"]) # bzr diff will show new files |
572 | + |
573 | templatetools.update_version_in_project_file(template_version, 'ubuntu-application') |
574 | sys.exit(0) |
575 | |
576 | === modified file 'data/templates/ubuntu-cli/commandsconfig' |
577 | --- data/templates/ubuntu-cli/commandsconfig 2011-03-02 22:59:32 +0000 |
578 | +++ data/templates/ubuntu-cli/commandsconfig 2012-08-17 20:23:19 +0000 |
579 | @@ -7,4 +7,4 @@ |
580 | #COMMANDS_FOLLOWED_BY_COMMAND = |
581 | |
582 | [ubuntu-application] |
583 | -IMPORT=configure;create;debug;edit;license;package;release;run;save;share;test |
584 | +IMPORT=configure;create;debug;edit;license;package;release;run;save;share;test;upgrade |
585 | |
586 | === added directory 'data/templates/ubuntu-cli/test' |
587 | === added file 'data/templates/ubuntu-cli/test/overwrite.sh' |
588 | --- data/templates/ubuntu-cli/test/overwrite.sh 1970-01-01 00:00:00 +0000 |
589 | +++ data/templates/ubuntu-cli/test/overwrite.sh 2012-08-17 20:23:19 +0000 |
590 | @@ -0,0 +1,36 @@ |
591 | +#!/bin/sh |
592 | + |
593 | +cd /tmp |
594 | + |
595 | +rm -rf test-project |
596 | + |
597 | +quickly create ubuntu-cli test-project |
598 | +# Creating bzr repository and committing |
599 | +# Congrats, your new project is setup! cd /tmp/test-project/ to start hacking. |
600 | +# Creating project directory test-project |
601 | + |
602 | +cd test-project |
603 | + |
604 | +sed -i 's/import os/import os #test-blarg/' setup.py |
605 | + |
606 | +(echo "#test-blarg" >> setup.py) |
607 | + |
608 | +(echo "#test-blarg" >> bin/test-project) |
609 | + |
610 | +(echo "#test-blarg" >> test_project/__init__.py) |
611 | + |
612 | +grep -R "#test-blarg" . |
613 | +# ./setup.py:import os #test-blarg |
614 | +# ./setup.py:#test-blarg |
615 | +# ./bin/test-project:#test-blarg |
616 | +# ./test_project/__init__.py:#test-blarg |
617 | + |
618 | +quickly upgrade 11.04 |
619 | +# Note: This is the first time you have run Quickly since it has been updated. |
620 | +# Quickly will now upgrade its files (bin/*, test_project_lib/*, and setup.py). |
621 | +# But first it will save your project. View Quickly's changes by running: |
622 | +# bzr diff |
623 | + |
624 | +grep -R "#test-blarg" . |
625 | +# ./setup.py:#test-blarg |
626 | +# ./test_project/__init__.py:#test-blarg |
627 | |
628 | === modified file 'data/templates/ubuntu-flash-game/create.py' |
629 | --- data/templates/ubuntu-flash-game/create.py 2011-07-22 10:47:34 +0000 |
630 | +++ data/templates/ubuntu-flash-game/create.py 2012-08-17 20:23:19 +0000 |
631 | @@ -80,13 +80,6 @@ |
632 | |
633 | os.chdir(project_name) |
634 | |
635 | -# get origin path |
636 | -pathname = templatetools.get_template_path_from_project() |
637 | -abs_path_project_root = os.path.join(pathname, 'project_root') |
638 | - |
639 | -python_name = templatetools.python_name(project_name) |
640 | -sentence_name, camel_case_name = templatetools.conventional_names(project_name) |
641 | - |
642 | # Calculate the SWF's dimensions |
643 | try: |
644 | width, height = SWF.dimensions(swf) |
645 | @@ -98,30 +91,9 @@ |
646 | width, height = (640, 480) |
647 | |
648 | |
649 | -substitutions = (("project_name",project_name), |
650 | - ("camel_case_name",camel_case_name), |
651 | - ("python_name",python_name), |
652 | - ("sentence_name",sentence_name), |
653 | - ("swf_height",str(height)), |
654 | - ("swf_width",str(width)), |
655 | - ) |
656 | - |
657 | - |
658 | -for root, dirs, files in os.walk(abs_path_project_root): |
659 | - try: |
660 | - relative_dir = root.split('project_root/')[1] |
661 | - except: |
662 | - relative_dir = "" |
663 | - # python dir should be replace by python_name (project "pythonified" name) |
664 | - if relative_dir.startswith('python'): |
665 | - relative_dir = relative_dir.replace('python', python_name) |
666 | - |
667 | - for directory in dirs: |
668 | - if directory == 'python': |
669 | - directory = python_name |
670 | - os.mkdir(os.path.join(relative_dir, directory)) |
671 | - for filename in files: |
672 | - templatetools.file_from_template(root, filename, relative_dir, substitutions) |
673 | +substitutions = [("swf_height",str(height)), |
674 | + ("swf_width",str(width))] |
675 | +templatetools.copy_dirs_from_template(extra_substitutions = substitutions) |
676 | |
677 | # set the mode to executable for executable file |
678 | exec_file = os.path.join('bin', project_name) |
679 | |
680 | === modified file 'quickly/templatetools.py' |
681 | --- quickly/templatetools.py 2011-06-06 10:14:40 +0000 |
682 | +++ quickly/templatetools.py 2012-08-17 20:23:19 +0000 |
683 | @@ -94,6 +94,13 @@ |
684 | os.chmod(dest_file_name, mode) |
685 | |
686 | def set_file_contents(filename, contents): |
687 | + # First, don't write anything if we don't need to |
688 | + if os.path.exists(filename): |
689 | + with file(filename, 'r') as ftest: |
690 | + if ftest.read() == contents: |
691 | + return |
692 | + |
693 | + # OK, we have novel content, let's write it out |
694 | new_filename = filename + '.new' |
695 | fout = file(new_filename, 'w') |
696 | fout.write(contents) |
697 | @@ -111,33 +118,29 @@ |
698 | try: |
699 | filename = os.path.abspath(filename) |
700 | ftarget_file_name = file(filename, 'r') |
701 | - ftarget_file_name_out = file(ftarget_file_name.name + '.new', 'w') |
702 | + new_content = '' |
703 | for line in ftarget_file_name: |
704 | # seek if we have to add something |
705 | if start_marker in line: |
706 | skip_until_end_found = True |
707 | marker_found = True |
708 | - ftarget_file_name_out.write(replacing_content) |
709 | + new_content = new_content + replacing_content |
710 | |
711 | if end_marker in line: |
712 | skip_until_end_found = False |
713 | |
714 | if not skip_until_end_found: |
715 | - ftarget_file_name_out.write(line) |
716 | + new_content = new_content + line |
717 | |
718 | ftarget_file_name.close() |
719 | - ftarget_file_name_out.close() |
720 | |
721 | if skip_until_end_found: # that means we didn't find the end_tag, don't copy the file |
722 | - os.remove(ftarget_file_name_out.name) |
723 | raise CantUpdateFile(_("%s was not found in the file %s.") % (end_marker, ftarget_file_name.name)) |
724 | |
725 | if not marker_found: |
726 | - os.remove(ftarget_file_name_out.name) |
727 | raise CantUpdateFile(_("%s was not found in the file %s.") % (start_marker, ftarget_file_name.name)) |
728 | |
729 | - apply_file_rights(ftarget_file_name.name, ftarget_file_name_out.name) |
730 | - os.rename(ftarget_file_name_out.name, ftarget_file_name.name) |
731 | + set_file_contents(ftarget_file_name.name, new_content) |
732 | |
733 | except (OSError, IOError), e: |
734 | msg = _("%s file was not found or can't update it") % ftarget_file_name |
735 | @@ -261,7 +264,7 @@ |
736 | camel_case_name = get_camel_case_name(name) |
737 | return sentence_name, camel_case_name |
738 | |
739 | -def file_from_template(template_dir, template_file, target_dir, substitutions=[], rename = True): |
740 | +def file_from_template(template_dir, template_file, target_dir, substitutions=[], rename = True, overwrite = False): |
741 | |
742 | if not os.path.isfile(os.path.join(template_dir, template_file)): |
743 | return |
744 | @@ -278,9 +281,86 @@ |
745 | file_contents = file_contents.replace(pattern,sub) |
746 | |
747 | target_path = os.path.join(target_dir, target_file) |
748 | - if os.path.exists(target_path): |
749 | + if os.path.exists(target_path) and not overwrite: |
750 | print _("Failed to add file to project\n cannot add: %s - this file already exists." % target_path) |
751 | - sys.exit(4) |
752 | + sys.exit(4) |
753 | |
754 | set_file_contents(target_path, file_contents) |
755 | + apply_file_rights(os.path.join(template_dir, template_file), target_path) |
756 | fin.close() |
757 | + |
758 | +def copy_dirs_from_template(dirs = ["."], extra_substitutions = []): |
759 | + if not configurationhandler.project_config: |
760 | + configurationhandler.loadConfig() |
761 | + project_name = configurationhandler.project_config['project'] |
762 | + |
763 | + pathname = get_template_path_from_project() |
764 | + abs_path_project_root = os.path.join(pathname, 'project_root') |
765 | + |
766 | + py_name = python_name(project_name) |
767 | + sentence_name, camel_case_name = conventional_names(project_name) |
768 | + substitutions = [("project_name",project_name), |
769 | + ("camel_case_name",camel_case_name), |
770 | + ("python_name",py_name), |
771 | + ("sentence_name",sentence_name),] + extra_substitutions |
772 | + |
773 | + for top_dir in dirs: |
774 | + full_top_dir = os.path.join(abs_path_project_root, top_dir) |
775 | + for root, subdirs, files in os.walk(full_top_dir): |
776 | + try: |
777 | + relative_dir = root.split('project_root/')[1] |
778 | + except: |
779 | + relative_dir = "" |
780 | + # python dir should be replace by py_name (project "pythonified" |
781 | + # name) |
782 | + if os.path.basename(relative_dir).startswith('python'): |
783 | + relative_dir = relative_dir.replace('python', py_name) |
784 | + |
785 | + for directory in subdirs: |
786 | + if os.path.basename(directory).startswith('python'): |
787 | + directory = directory.replace('python', py_name) |
788 | + if not os.path.exists(os.path.join(relative_dir, directory)): |
789 | + os.mkdir(os.path.join(relative_dir, directory)) |
790 | + for filename in files: |
791 | + file_from_template(root, filename, relative_dir, |
792 | + substitutions, overwrite = True) |
793 | + |
794 | +def copy_setup_py_from_template(extra_substitutions = []): |
795 | + if not configurationhandler.project_config: |
796 | + configurationhandler.loadConfig() |
797 | + project_name = configurationhandler.project_config['project'] |
798 | + |
799 | + pathname = get_template_path_from_project() |
800 | + abs_path_project_root = os.path.join(pathname, 'project_root') |
801 | + |
802 | + py_name = python_name(project_name) |
803 | + sentence_name, camel_case_name = conventional_names(project_name) |
804 | + substitutions = [("project_name",project_name), |
805 | + ("camel_case_name",camel_case_name), |
806 | + ("python_name",py_name), |
807 | + ("sentence_name",sentence_name),] + extra_substitutions |
808 | + |
809 | + template_setup = os.path.join(abs_path_project_root, 'setup.py') |
810 | + project_setup = 'setup.py' |
811 | + |
812 | + # Grab quickly-owned bits in our original and copy them to user's version |
813 | + start_marker = "###################### DO NOT TOUCH THIS (HEAD TO THE SECOND PART) ######################" |
814 | + end_marker = "##################################################################################" |
815 | + try: |
816 | + with file(template_setup, 'r') as template_fd: |
817 | + template_contents = '' |
818 | + for line in template_fd.readlines(): |
819 | + if line == end_marker + '\n': |
820 | + break |
821 | + elif template_contents: |
822 | + template_contents = template_contents + line |
823 | + elif line == start_marker + '\n': |
824 | + template_contents = line |
825 | + for s in substitutions: |
826 | + pattern, sub = s |
827 | + template_contents = template_contents.replace(pattern, sub) |
828 | + update_file_content(project_setup, start_marker, end_marker, template_contents) |
829 | + except Exception as e: |
830 | + print(_("Failed to update setup.py:\n%s" % e)) |
831 | + sys.exit(4) |
832 | + |
833 | |
834 | === modified file 'quickly/test/completion.sh' |
835 | --- quickly/test/completion.sh 2012-04-19 14:30:00 +0000 |
836 | +++ quickly/test/completion.sh 2012-08-17 20:23:19 +0000 |
837 | @@ -130,7 +130,7 @@ |
838 | # add commands configure debug design edit getstarted help license package quickly release run save share submitubuntu test tutorial upgrade |
839 | |
840 | quickly shell-completion quickly -t ubuntu-cli foo |
841 | -# commands configure debug edit getstarted help license package quickly release run save share test |
842 | +# commands configure debug edit getstarted help license package quickly release run save share test upgrade |
843 | |
844 | quickly shell-completion quickly add foo |
845 | # dialog help-guide help-topic indicator |
846 | |
847 | === modified file 'quickly/test/help.sh' |
848 | --- quickly/test/help.sh 2012-04-19 14:30:00 +0000 |
849 | +++ quickly/test/help.sh 2012-08-17 20:23:19 +0000 |
850 | @@ -84,7 +84,7 @@ |
851 | HOME=/ quickly help ubuntu-cli |
852 | # ERROR: No command provided to help command. |
853 | # Usage: quickly help [template] <command> |
854 | -# Candidate commands are: commands, configure, create, debug, edit, getstarted, help, license, package, quickly, release, run, save, share, test |
855 | +# Candidate commands are: commands, configure, create, debug, edit, getstarted, help, license, package, quickly, release, run, save, share, test, upgrade |
856 | |
857 | HOME=/ quickly help foobar |
858 | # ERROR: No foobar command found in ubuntu-application template. |
My unease at overwriting "quickly-owned" files remains, what does a user do when he finds a "quickly-owned" file needs fixing?
Scenario: A user finds a bug in a "quickly-owned" file in his project and fixes it in his project. Later on he quickly upgrades and breaks his project.
Mitigation 1: quickly upgrade bails if the user has made any changes in a "quickly-owned" file.
(might need to introduce quickly upgrade --force ?)
Mitigation 2: When a user changes a "quickly-owned" file warn him of the later overwrite and suggests he submit a bug report.
Mitigation 3: Write a warning do not edit comment into all "quickly-owned" files.
I assume quickly upgrade calls (or should call) bzr commit. Does quickly upgrade bail out if there are any un-commited changes in source tree?
Noticing changes to a "quickly-owned" file eluded me for a while but how about "quickly create" writing a hash of the "quickly-owned" files into .quickly? Then quickly upgrade could compare current files with the hash.
More attention is needed for bug fixes affecting "quickly-owned" files. A practical example has shown up recently.
Before revision 645 "finally merge gtk3 branch" you could do either of these
cd /path_to/foo
quickly run
cd /path_to/foo
./bin/foo
Afterwards .bin/foo no longer works. This affects users who want to use an IDE like pydev. A fix has been tested by Dražen Lučanin and found to work. /bugs.launchpad .net/quickly/ +bug/976817/ comments/ 9 /bugs.launchpad .net/quickly/ +bug/976817/ comments/ 10
https:/
https:/
As thing stand he can no longer upgrade without difficulty.