Merge lp:~mterry/quickly/overwrite into lp:quickly

Proposed by Michael Terry
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
Reviewer Review Type Date Requested Status
Didier Roche-Tolomelli Needs Information
Review via email: mp+111315@code.launchpad.net

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.

To post a comment you must log in.
Revision history for this message
Tony Byrne (tony-badwolf) wrote :

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.
https://bugs.launchpad.net/quickly/+bug/976817/comments/9
https://bugs.launchpad.net/quickly/+bug/976817/comments/10

As thing stand he can no longer upgrade without difficulty.

Revision history for this message
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

Revision history for this message
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.exists(filename):
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_nameconfig.py file will always be different as we bump it with the versionning, but we will maybe want to add some more configuration later on?
Maybe we should have a Config.py in private_lib, which define some kind of class, and python_nameconfig.py in the python/ directory, which inherit from it. That way, we can still upgrade Config.py, add new attributes, and let the user override them?

(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?

review: Needs Information
Revision history for this message
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_nameconfig.py file is a good point. I can fix it much the same way that I fixed the desktop file in the ARB branch: by modifying that file after we install it in debian/tmp. That way the original file always stays pristine, and we don't have duplicate copies of the version number in the code (setup.py and the config.py file). Will fix soon.

Revision history for this message
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_nameconfig.py file is a good point. I can fix it much the same way that I fixed the desktop file in the ARB branch: by modifying that file after we install it in debian/tmp. That way the original file always stays pristine, and we don't have duplicate copies of the version number in the code (setup.py and the config.py file). Will fix soon.

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).

Revision history for this message
Michael Terry (mterry) wrote :

Whoops, sorry for double messages. I've fixed it. Please re-review.

Revision history for this message
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.

Revision history for this message
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://code.launchpad.net/~didrocks/quickly/dont-licence-private-lib/+merge/122842

Thanks for the quick fixes! Looking good :)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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.

Subscribers

People subscribed via source and target branches