Merge lp:~johnf-inodes/autoppa/version_template into lp:autoppa

Proposed by John Ferlito
Status: Merged
Merged at revision: not available
Proposed branch: lp:~johnf-inodes/autoppa/version_template
Merge into: lp:autoppa
Diff against target: 446 lines
8 files modified
README (+25/-1)
autoppa/application.py (+16/-5)
autoppa/commands.py (+6/-2)
autoppa/configuration.py (+4/-3)
autoppa/help_topics.py (+43/-0)
autoppa/target.py (+30/-13)
autoppa/tests/test_configuration.py (+2/-0)
autoppa/tests/test_target.py (+29/-5)
To merge this branch: bzr merge lp:~johnf-inodes/autoppa/version_template
Reviewer Review Type Date Requested Status
Jamu Kakar Approve
John Ferlito (community) Abstain
Review via email: mp+13782@code.launchpad.net
To post a comment you must log in.
Revision history for this message
John Ferlito (johnf-inodes) wrote :

Version templates

Revision history for this message
John Ferlito (johnf-inodes) wrote :

Not 100% happy with the template variables but I couldn't come up with anything better.

Revision history for this message
John Ferlito (johnf-inodes) wrote :

Not 100% happy with the template variables but I couldn't come up with anything better.

Revision history for this message
John Ferlito (johnf-inodes) wrote :

Not 100% happy with the template variables but I couldn't come up with anything better.

review: Abstain
Revision history for this message
Jamu Kakar (jkakar) wrote :
Download full text (3.8 KiB)

[1]

+ file = open(filename, "r")
+ try:
+ expected = "version = 'AUTOPPA_VERSION(1.3.11-upside1~dapper~ppa1)'"
+ self.assertEquals(file.read(), expected)
+ finally:
+ file.close()
+ self.builder.version_template = original_version_template

The try/finally isn't really necessary here. If it leaks, the file
will be closed when it gets garbage collected. Also, the final line
isn't necessary since self.builder is created afresh for each test
case.

[2]

+ def _get_version(self, release_name):
+
+ version = self.version_template
+ version = re.sub("\${version}", self.version, version)
+ version = re.sub("\${release_number}", self._get_release_number(release_name), version)
+ version = re.sub("\${release_name}", release_name, version)
+
+ return version

The standard library provides builtin string template interpolation
functionality that will simplify this a bit:

    def _get_version(self, release_name):
        version_template = Template(self.version_template)
        release_number = self._get_release_number(release_name, self.version)
        data = {"version": self.version, "release_name": release_name,
                "release_number": release_number}
        return version_template.substitute(data)

You'll need to add the following import:

from string import Template

[3]

What do you think about expanding the version variables to include
everything in this list:

version 'version' in the diff
revision The revision of the source branch
dist_codename 'release_name' in the diff
dist_version 'release_number' in the diff
now The current time in UTC formatted as YYYYMMDDHHMMSS
today Today's date formatted as YYYYMMDD
user The name from the USER environment variable

Is there anything else that should be included?

[4]

+version_template = ${version}~ppa1~${codename}

+${version} - The version passed on the command line
+${release_number} - 6.04, 6.10, etc
+${release_name} - dapper, gutsy, etc

'codename' should be 'release_name' above, in the README.

[5]

It'd be cool to add a help topic describing the functionality. If
you look at autoppa.help_topics you'll see an example of a topic.
If you implement a class following the same pattern called
topic_version_templates it will be included in the list of topics
you see when you run 'bin/autoppa help topics' and can be viewed by
running 'bin/autoppa help version-templates'.

[6]

+ build_target = self._configuration[build_target]
+ if "version_template" not in build_target:
+ build_target["version_template"] = DEFAULT_VERSION_TEMPLATE
+ return build_target

I think this logic is a bit dangerous, because it will end up
injecting data into user configuration that wasn't actually provided
by the user. I recommend you revert this change and deal with the
default version template in autoppa.application. I would move the
definition of DEFAULT_VERSION_TEMPLATE there, too.

+ version_template = version_template or data["version_template"]

Then the above line in AutoPPA._create_build...

Read more...

review: Needs Fixing
Revision history for this message
John Ferlito (johnf-inodes) wrote :
Download full text (5.0 KiB)

On Thu, Oct 22, 2009 at 07:03:12PM -0000, Jamu Kakar wrote:
> Review: Needs Fixing
> [1]
>
> + file = open(filename, "r")
> + try:
> + expected = "version = 'AUTOPPA_VERSION(1.3.11-upside1~dapper~ppa1)'"
> + self.assertEquals(file.read(), expected)
> + finally:
> + file.close()
> + self.builder.version_template = original_version_template
>
> The try/finally isn't really necessary here. If it leaks, the file
> will be closed when it gets garbage collected. Also, the final line
> isn't necessary since self.builder is created afresh for each test
> case.

OK. I'll fix that up. I pretty much copied this test case from the
one above which does something similar.

> [2]
>
> + def _get_version(self, release_name):
> +
> + version = self.version_template
> + version = re.sub("\${version}", self.version, version)
> + version = re.sub("\${release_number}", self._get_release_number(release_name), version)
> + version = re.sub("\${release_name}", release_name, version)
> +
> + return version
>
> The standard library provides builtin string template interpolation
> functionality that will simplify this a bit:
>
> def _get_version(self, release_name):
> version_template = Template(self.version_template)
> release_number = self._get_release_number(release_name, self.version)
> data = {"version": self.version, "release_name": release_name,
> "release_number": release_number}
> return version_template.substitute(data)
>
> You'll need to add the following import:
>
> from string import Template

Ahh that is very cool. Much more elegant. Thanks!

> [3]
>
> What do you think about expanding the version variables to include
> everything in this list:
>
> version 'version' in the diff
> revision The revision of the source branch
> dist_codename 'release_name' in the diff
> dist_version 'release_number' in the diff
> now The current time in UTC formatted as YYYYMMDDHHMMSS
> today Today's date formatted as YYYYMMDD
> user The name from the USER environment variable
>
> Is there anything else that should be included?

Can't think of anything else right now.
There are a couple of TODOs and FIXMEs regarding this change.

Testing ${revision} is painful since FakeExpect doesn't deal with
grabbing output. I'll implement it after I redo the bzrlib stuff since
then we shouldn't need expect any more.

Also I'm not sure how to stub/mock time and date so that we can test
$today so I left it out for now.

> [4]
>
> +version_template = ${version}~ppa1~${codename}
>
> +${version} - The version passed on the command line
> +${release_number} - 6.04, 6.10, etc
> +${release_name} - dapper, gutsy, etc
>
> 'codename' should be 'release_name' above, in the README.

Done.

> [5]
>
> It'd be cool to add a help topic describing the functionality. If
> you look at autoppa.help_topics you'll see an example of a topic.
> If you implement a class following the same pattern called
> topic_version_templates it will be included in the list of topics
> you see when you r...

Read more...

31. By John Ferlito

Use string template

32. By John Ferlito

Move default version template

33. By John Ferlito

Add extra substitutions to version_template

34. By John Ferlito

Add a help topic for version templates

Revision history for this message
John Ferlito (johnf-inodes) wrote :

OK. All those changes have been pushed

35. By John Ferlito

merge in trunk

Revision history for this message
Jamu Kakar (jkakar) wrote :

[9]

+ def _get_revno(self):
+ # FIXME Can't use this until we move to using bzrlib
+ # directly as it causes to much hassle with FakeExpect
+ revno = self.expect.run("bzr revno %s" % self.working_tree,
+ logfile=file,
+ timeout=None)
+ print revno
+ return revno

I would remove this. We can add it when its necessary. Thanks for
adding the TODO about it in _get_version.

[10]

+ "now": time.strftime("%Y%m%d%H%M%S"),
+ "today": datetime.date.today().strftime("%Y%m%d"),

These should be changed to:

        now = datetime.utcnow()
...
            "now": now.strftime("%Y%m%d%H%M%S"),
            "today": now.strftime("%Y%m%d"),

[11]

I have a test failure:

[FAIL]: autoppa.tests.test_target.BuildTargetTest.test_prepare_custom_files_with_custom_version_content

Traceback (most recent call last):
  File "/usr/lib/python2.6/unittest.py", line 279, in run
    testMethod()
  File "/home/jkakar/src/johnf-inodes/autoppa/version-template/autoppa/tests/test_target.py", line 280, in test_prepare_custom_files_with_custom_version_content
    self.assertEquals(file.read(), expected)
exceptions.AssertionError: "version = 'AUTOPPA_VERSION(1.3.11-upside1~dapper~6.06~20091027~user_from_env)'" != "version = 'AUTOPPA_VERSION(1.3.11-upside1~dapper~6.06~20091024~user_from_env)'"

Looking great, +1 considering these comments. Have you had a chance
to sign the Canonical contributor agreement yet?

review: Approve
Revision history for this message
John Ferlito (johnf-inodes) wrote :

On Wed, Oct 28, 2009 at 04:36:59AM -0000, Jamu Kakar wrote:
> Review: Approve
> [9]
>
> + def _get_revno(self):
> + # FIXME Can't use this until we move to using bzrlib
> + # directly as it causes to much hassle with FakeExpect
> + revno = self.expect.run("bzr revno %s" % self.working_tree,
> + logfile=file,
> + timeout=None)
> + print revno
> + return revno
>
> I would remove this. We can add it when its necessary. Thanks for
> adding the TODO about it in _get_version.

Done.

>
>
> [10]
>
> + "now": time.strftime("%Y%m%d%H%M%S"),
> + "today": datetime.date.today().strftime("%Y%m%d"),
>
> These should be changed to:
>
> now = datetime.utcnow()
> ...
> "now": now.strftime("%Y%m%d%H%M%S"),
> "today": now.strftime("%Y%m%d"),
>
>
> [11]

Done, with changes in next comment.

> I have a test failure:
>
> [FAIL]: autoppa.tests.test_target.BuildTargetTest.test_prepare_custom_files_with_custom_version_content
>
> Traceback (most recent call last):
> File "/usr/lib/python2.6/unittest.py", line 279, in run
> testMethod()
> File "/home/jkakar/src/johnf-inodes/autoppa/version-template/autoppa/tests/test_target.py", line 280, in test_prepare_custom_files_with_custom_version_content
> self.assertEquals(file.read(), expected)
> exceptions.AssertionError: "version = 'AUTOPPA_VERSION(1.3.11-upside1~dapper~6.06~20091027~user_from_env)'" != "version = 'AUTOPPA_VERSION(1.3.11-upside1~dapper~6.06~20091024~user_from_env)'"

Fixed. It was because it was a different day. I noticed you had some
datetime_factory code in there. I've moved that up into the
BuildTarget itself so that all date related code has access to it.

> Looking great, +1 considering these comments. Have you had a chance
> to sign the Canonical contributor agreement yet?

Yes, you should have been CC'd on the email.

36. By John Ferlito

* Remove unused _get_revision code
* Use UTC time for ${now} and ${today}
* Add a datetime_factory to BuildTarget so we can test date stuff properly.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'README'
--- README 2009-09-21 03:13:54 +0000
+++ README 2009-10-28 06:25:19 +0000
@@ -105,7 +105,7 @@
105105
106AutoPPA automatically inserts a release version into package version106AutoPPA automatically inserts a release version into package version
107numbers. The conventions specified by Ubuntu's SRU [1] policy107numbers. The conventions specified by Ubuntu's SRU [1] policy
108should be followed when generating version numbers. In the above108are followed by default when generating version numbers. In the above
109example, the smart-0.51-landscape12 would build packages with the109example, the smart-0.51-landscape12 would build packages with the
110following versions:110following versions:
111111
@@ -114,6 +114,30 @@
1140.51-landscape12.7.041140.51-landscape12.7.04
1150.51-landscape12.7.101150.51-landscape12.7.10
116116
117A version_template configuration can be set in the autoppa configuration file
118or on the command line using the --version-template flag. For example:
119
120[landscape-client]
121version_template = ${version}~ppa1~${dist_codename}
122
123would produce:
124
1250.51-landscape12~ppa1~dapper
1260.51-landscape12~ppa1~edgy
1270.51-landscape12~ppa1~feisty
1280.51-landscape12~ppa1~gutsy
129
130The following environment variables are available:
131
132${version} - The version passed on the command line
133${revision} - The revision of the source branch
134${dist_codename} - dapper, gutsy, etc
135${dist_version} - 6.04, 6.10, etc
136${now} - The current time in UTC formatted as YYYYMMDDHHMMSS
137${today} - Today's date formatted as YYYYMMDD
138${user} - The name from the USER environment variable
139
140
117[1] https://wiki.ubuntu.com/MOTU/SRU141[1] https://wiki.ubuntu.com/MOTU/SRU
118142
119143
120144
=== modified file 'autoppa/application.py'
--- autoppa/application.py 2009-09-21 01:35:24 +0000
+++ autoppa/application.py 2009-10-28 06:25:19 +0000
@@ -23,6 +23,9 @@
23from autoppa.errors import BuildTargetError23from autoppa.errors import BuildTargetError
24from autoppa.target import BuildTarget24from autoppa.target import BuildTarget
2525
26from autoppa import configuration
27
28DEFAULT_VERSION_TEMPLATE = "${version}.${dist_version}"
2629
27class AutoPPA(object):30class AutoPPA(object):
2831
@@ -36,7 +39,7 @@
36 self.log_file.write("%s\n" % (message,))39 self.log_file.write("%s\n" % (message,))
3740
38 def build(self, build_target, version, no_upload=None, no_merge=None,41 def build(self, build_target, version, no_upload=None, no_merge=None,
39 no_tag=None, no_cleanup=None):42 no_tag=None, no_cleanup=None, version_template=None):
40 """Process sources for C{built_target} using the current settings.43 """Process sources for C{built_target} using the current settings.
4144
42 @param build_target: The target to build. This should correspond to45 @param build_target: The target to build. This should correspond to
@@ -44,7 +47,7 @@
44 @param version: The version to for the new build.47 @param version: The version to for the new build.
45 """48 """
46 self._log_info("AutoPPA %s" % (VERSION,))49 self._log_info("AutoPPA %s" % (VERSION,))
47 build_target = self._create_build_target(build_target, version)50 build_target = self._create_build_target(build_target, version, version_template)
48 build_target.prepare_changelog()51 build_target.prepare_changelog()
49 build_target.prepare_working_tree()52 build_target.prepare_working_tree()
50 for release in build_target.releases:53 for release in build_target.releases:
@@ -66,17 +69,20 @@
66 """Switch files to use a version and Ubuntu code name."""69 """Switch files to use a version and Ubuntu code name."""
67 build_target = BuildTarget("unused-name", version, "unused@email",70 build_target = BuildTarget("unused-name", version, "unused@email",
68 "unused-branch", "unused-repository",71 "unused-branch", "unused-repository",
69 "unused-ppa", [code_name])72 "unused-ppa", [code_name],
73 DEFAULT_VERSION_TEMPLATE)
70 build_target.working_tree = path74 build_target.working_tree = path
71 build_target._prepare_custom_autoppa_files(code_name)75 build_target._prepare_custom_autoppa_files(code_name)
72 build_target._prepare_custom_autoppa_version(code_name)76 build_target._prepare_custom_autoppa_version(code_name)
7377
74 def _create_build_target(self, build_target, version, expect=pexpect):78 def _create_build_target(self, build_target, version, version_template,
79 expect=pexpect):
75 """Create a L{BuildTarget} instance for C{build_target}.80 """Create a L{BuildTarget} instance for C{build_target}.
7681
77 @param build_target: The target to build. This should correspond to82 @param build_target: The target to build. This should correspond to
78 the name of the Debian source package being built.83 the name of the Debian source package being built.
79 @param version: The version to for the new build.84 @param version: The version to for the new build.
85 @param version_template: The template to use to create the version.
80 @param expect: Optionally, a L{pexpect} like object. Defaults to86 @param expect: Optionally, a L{pexpect} like object. Defaults to
81 L{pexpect}.87 L{pexpect}.
82 @raises BuildTargetError: Raised when a build target is specified that88 @raises BuildTargetError: Raised when a build target is specified that
@@ -88,10 +94,15 @@
88 if not data:94 if not data:
89 raise BuildTargetError("'%s' is not a known build target."95 raise BuildTargetError("'%s' is not a known build target."
90 % build_target)96 % build_target)
97 if version_template is None:
98 version_template = data.get("version_template",
99 DEFAULT_VERSION_TEMPLATE)
100
91 builder = BuildTarget(build_target, version, data["email"],101 builder = BuildTarget(build_target, version, data["email"],
92 data["branch"], data["repository"],102 data["branch"], data["repository"],
93 data["ppa"], data["releases"].split(),103 data["ppa"], data["releases"].split(),
94 expect=expect, log_file=self.log_file)104 version_template, expect=expect,
105 log_file=self.log_file)
95 if "options" in data:106 if "options" in data:
96 options = set(data["options"].split())107 options = set(data["options"].split())
97 if "no-version-replacement" in options:108 if "no-version-replacement" in options:
98109
=== modified file 'autoppa/commands.py'
--- autoppa/commands.py 2009-09-21 01:20:28 +0000
+++ autoppa/commands.py 2009-10-28 06:25:19 +0000
@@ -46,10 +46,13 @@
46 Option("no-cleanup",46 Option("no-cleanup",
47 help="Don't automatically cleanup signed sources and the "47 help="Don't automatically cleanup signed sources and the "
48 "release branch created during a build."),48 "release branch created during a build."),
49 Option("version-template", type=str,
50 help="The version template to use when creating the version "
51 "for each PPA."),
49 ]52 ]
5053
51 def run(self, build_target, version, config=None, log=None, no_upload=None,54 def run(self, build_target, version, config=None, log=None, no_upload=None,
52 no_merge=None, no_tag=None, no_cleanup=None):55 no_merge=None, no_tag=None, no_cleanup=None, version_template=None):
53 """Run command."""56 """Run command."""
54 if not config:57 if not config:
55 config = os.path.join(os.environ["HOME"], ".autoppa.conf")58 config = os.path.join(os.environ["HOME"], ".autoppa.conf")
@@ -57,7 +60,8 @@
57 log_file = get_log_file(log, self.outf)60 log_file = get_log_file(log, self.outf)
58 autoppa = AutoPPA(configuration, log_file)61 autoppa = AutoPPA(configuration, log_file)
59 autoppa.build(build_target, version, no_upload=no_upload,62 autoppa.build(build_target, version, no_upload=no_upload,
60 no_merge=no_merge, no_tag=no_tag, no_cleanup=no_cleanup)63 no_merge=no_merge, no_tag=no_tag, no_cleanup=no_cleanup,
64 version_template=version_template)
6165
6266
63class cmd_switch(Command):67class cmd_switch(Command):
6468
=== modified file 'autoppa/configuration.py'
--- autoppa/configuration.py 2009-10-21 22:40:23 +0000
+++ autoppa/configuration.py 2009-10-28 06:25:19 +0000
@@ -21,7 +21,6 @@
2121
22from autoppa.lib.configobj import ConfigObj22from autoppa.lib.configobj import ConfigObj
2323
24
25class Configuration(object):24class Configuration(object):
26 """Get configuration details for named build targets.25 """Get configuration details for named build targets.
2726
@@ -63,6 +62,7 @@
63 repository = /home/jkakar/src/canonical/landscape-client62 repository = /home/jkakar/src/canonical/landscape-client
64 ppa = landscape-client-ppa63 ppa = landscape-client-ppa
65 releases = dapper edgy feisty gutsy64 releases = dapper edgy feisty gutsy
65 version_template = ~${release_name}
6666
67 [smart]67 [smart]
68 email = Jamshed Kakar <jamshed.kakar@canonical.com>68 email = Jamshed Kakar <jamshed.kakar@canonical.com>
@@ -71,7 +71,7 @@
71 ppa = landscape-client-ppa71 ppa = landscape-client-ppa
72 releases = dapper edgy feisty gutsy72 releases = dapper edgy feisty gutsy
73 """73 """
7474
75 def __init__(self, configuration):75 def __init__(self, configuration):
76 self._configuration = configuration76 self._configuration = configuration
7777
@@ -93,7 +93,8 @@
93 def get_build_target(self, build_target):93 def get_build_target(self, build_target):
94 """Get a C{dict}-like object with data related to C{build_target}."""94 """Get a C{dict}-like object with data related to C{build_target}."""
95 try:95 try:
96 return self._configuration[build_target]96 build_target = self._configuration[build_target]
97 return build_target
97 except KeyError:98 except KeyError:
98 pass99 pass
99 return None100 return None
100101
=== modified file 'autoppa/help_topics.py'
--- autoppa/help_topics.py 2009-09-21 03:13:54 +0000
+++ autoppa/help_topics.py 2009-10-28 06:25:19 +0000
@@ -59,3 +59,46 @@
5959
60 options = no-version-replacement60 options = no-version-replacement
61 """61 """
62
63class topic_version_template(DocstringHelpTopic):
64 """Information about version templating functionality.
65
66 AutoPPA automatically inserts a release version into package version
67 numbers. The conventions specified by Ubuntu's SRU [1] policy
68 are followed by default when generating version numbers. For example
69 if you built a package which had a version of 0.51-landscape12, then you
70 would get the following versions for each release:
71
72 0.51-landscape12.6.06
73 0.51-landscape12.6.10
74 0.51-landscape12.7.04
75 0.51-landscape12.7.10
76
77 A version_template configuration can be set in the autoppa configuration
78 file or on the command line using the --version-template flag. For example
79 you could add the following to the configuration file for the
80 landscape-client package:
81
82 [landscape-client]
83 version_template = ${version}~ppa1~${dist_codename}
84
85 This would produce versions like:
86
87 0.51-landscape12~ppa1~dapper
88 0.51-landscape12~ppa1~edgy
89 0.51-landscape12~ppa1~feisty
90 0.51-landscape12~ppa1~gutsy
91
92 The following environment variables are available:
93
94 ${version} - The version passed on the command line
95 ${revision} - The revision of the source branch
96 ${dist_codename} - dapper, gutsy, etc
97 ${dist_version} - 6.04, 6.10, etc
98 ${now} - The current time in UTC formatted as YYYYMMDDHHMMSS
99 ${today} - Today's date formatted as YYYYMMDD
100 ${user} - The name from the USER environment variable
101
102
103 [1] https://wiki.ubuntu.com/MOTU/SRU
104 """
62105
=== modified file 'autoppa/target.py'
--- autoppa/target.py 2009-10-22 18:06:19 +0000
+++ autoppa/target.py 2009-10-28 06:25:19 +0000
@@ -18,10 +18,12 @@
18# along with this program. If not, see <http://www.gnu.org/licenses/>.18# along with this program. If not, see <http://www.gnu.org/licenses/>.
1919
20from datetime import datetime20from datetime import datetime
21import time
21import tempfile22import tempfile
22import os23import os
2324
24import pexpect25import pexpect
26from string import Template
2527
26from autoppa.errors import ChangelogError, EditorError28from autoppa.errors import ChangelogError, EditorError
27from autoppa.file import ReleaseSpecificInclude, VersionReplacement29from autoppa.file import ReleaseSpecificInclude, VersionReplacement
@@ -41,7 +43,8 @@
41 """43 """
4244
43 def __init__(self, name, version, email, branch, repository, ppa, releases,45 def __init__(self, name, version, email, branch, repository, ppa, releases,
44 expect=pexpect, system=os.system, log_file=None):46 version_template, expect=pexpect, system=os.system,
47 datetime_factory=None, log_file=None):
45 """48 """
46 @param name: The package name. Note that multiple .deb files may be49 @param name: The package name. Note that multiple .deb files may be
47 produced for this package.50 produced for this package.
@@ -56,10 +59,14 @@
56 @param ppa: The name of the PPA to use, as defined in C{~/.dput.cf}.59 @param ppa: The name of the PPA to use, as defined in C{~/.dput.cf}.
57 @param releases: A list of Ubuntu releases, such as60 @param releases: A list of Ubuntu releases, such as
58 C{['hardy', 'karmic']}.61 C{['hardy', 'karmic']}.
62 @param version_template: A template for adding PPA sepecific version.
59 @param expect: Optionally, a L{pexpect}-like object. Defaults to63 @param expect: Optionally, a L{pexpect}-like object. Defaults to
60 L{pexpect}.64 L{pexpect}.
61 @param system: Optionally, an L{os.system}-like function. Defaults to65 @param system: Optionally, an L{os.system}-like function. Defaults to
62 L{os.system}.66 L{os.system}.
67 @param datetime_factory: Optionally, an object that yields a datetime
68 instance to use as the changelog time. Defaults to
69 C{datetime.utcnow}.
63 @param log_file: Optionally, a stream to write log output to.70 @param log_file: Optionally, a stream to write log output to.
64 """71 """
65 self.name = name72 self.name = name
@@ -69,11 +76,13 @@
69 self.repository = repository76 self.repository = repository
70 self.ppa = ppa77 self.ppa = ppa
71 self.releases = releases78 self.releases = releases
79 self.version_template = version_template
72 self.working_tree = None80 self.working_tree = None
73 self.changelog = None81 self.changelog = None
74 self.log_file = log_file82 self.log_file = log_file
75 self.expect = expect83 self.expect = expect
76 self.system = system84 self.system = system
85 self.datetime_factory = datetime_factory or datetime.utcnow()
77 self.version_replacement = True86 self.version_replacement = True
78 self._prepared_files = set()87 self._prepared_files = set()
7988
@@ -166,7 +175,7 @@
166 def _get_working_tree(self):175 def _get_working_tree(self):
167 return "%s_%s" % (self.name, self.version)176 return "%s_%s" % (self.name, self.version)
168177
169 def prepare_custom_files(self, release, datetime_factory=None):178 def prepare_custom_files(self, release):
170 """Prepare the release-specific files for the new release.179 """Prepare the release-specific files for the new release.
171180
172 Packages often require release-specific content for files such as the181 Packages often require release-specific content for files such as the
@@ -187,17 +196,14 @@
187 C{debian/changelog}. A new changelog file is created if necessary.196 C{debian/changelog}. A new changelog file is created if necessary.
188197
189 @param release: The name of the release to prepare package files for.198 @param release: The name of the release to prepare package files for.
190 @param datetime_factory: Optionally, an object that yields a datetime
191 instance to use as the changelog time. Defaults to
192 C{datetime.utcnow}.199 C{datetime.utcnow}.
193 """200 """
194 self._log_info("== Preparing custom files for %s on %s =="201 self._log_info("== Preparing custom files for %s on %s =="
195 % (self.name, release))202 % (self.name, release))
196 datetime_factory = datetime_factory or datetime.utcnow
197 self._prepare_custom_autoppa_files(release)203 self._prepare_custom_autoppa_files(release)
198 if self.version_replacement:204 if self.version_replacement:
199 self._prepare_custom_autoppa_version(release)205 self._prepare_custom_autoppa_version(release)
200 self._prepare_custom_changelog(release, datetime_factory)206 self._prepare_custom_changelog(release)
201207
202 def _prepare_custom_autoppa_files(self, release):208 def _prepare_custom_autoppa_files(self, release):
203 include = ReleaseSpecificInclude(release)209 include = ReleaseSpecificInclude(release)
@@ -245,12 +251,23 @@
245 "lucid": "10.04"}251 "lucid": "10.04"}
246 return numbers[release_name]252 return numbers[release_name]
247253
248 def _get_version(self, release):254 def _get_version(self, release_name):
249 parts = self.version.split("-", 1)255 version_template = Template(self.version_template)
250 return "%s-%s.%s" % (parts[0], parts[1],256 # TODO Implement revision when we move to bzrlib
251 self._get_release_number(release))257 # "revision": self._get_revno(),
252258
253 def _prepare_custom_changelog(self, release, datetime_factory):259 data = {
260 "version": self.version,
261 "dist_codename": release_name,
262 "dist_version": self._get_release_number(release_name),
263 "now": self.datetime_factory.strftime("%Y%m%d%H%M%S"),
264 "today": self.datetime_factory.strftime("%Y%m%d"),
265 "user": os.environ["USER"]
266 }
267
268 return version_template.substitute(data)
269
270 def _prepare_custom_changelog(self, release):
254 try:271 try:
255 path = os.path.join(self.working_tree, "debian/changelog")272 path = os.path.join(self.working_tree, "debian/changelog")
256 file = open(path, "r")273 file = open(path, "r")
@@ -262,7 +279,7 @@
262 old_changelog = ""279 old_changelog = ""
263280
264 version = self._get_version(release)281 version = self._get_version(release)
265 date = datetime_factory().strftime("%a, %-d %b %Y %H:%M:%S +0000")282 date = self.datetime_factory.strftime("%a, %-d %b %Y %H:%M:%S +0000")
266 changelog = """\283 changelog = """\
267%(package)s (%(version)s) %(release)s; urgency=low284%(package)s (%(version)s) %(release)s; urgency=low
268285
269286
=== modified file 'autoppa/tests/test_configuration.py'
--- autoppa/tests/test_configuration.py 2009-10-21 22:40:23 +0000
+++ autoppa/tests/test_configuration.py 2009-10-28 06:25:19 +0000
@@ -57,6 +57,7 @@
57branch = /home/john/src/supertool/production57branch = /home/john/src/supertool/production
58repository = /home/john/src/supertool58repository = /home/john/src/supertool
59releases = dapper edgy gutsy feisty59releases = dapper edgy gutsy feisty
60version-template = ~${release_name}~ppa
60"""61"""
61 path = self.fs.make_path(content=content)62 path = self.fs.make_path(content=content)
62 configuration = Configuration.from_file(path)63 configuration = Configuration.from_file(path)
@@ -65,6 +66,7 @@
65 self.assertEquals(data["branch"], "/home/john/src/supertool/production")66 self.assertEquals(data["branch"], "/home/john/src/supertool/production")
66 self.assertEquals(data["repository"], "/home/john/src/supertool")67 self.assertEquals(data["repository"], "/home/john/src/supertool")
67 self.assertEquals(data["releases"], "dapper edgy gutsy feisty")68 self.assertEquals(data["releases"], "dapper edgy gutsy feisty")
69 self.assertEquals(data["version-template"], "~${release_name}~ppa")
6870
69 def test_get_missing_build_target(self):71 def test_get_missing_build_target(self):
70 """72 """
7173
=== modified file 'autoppa/tests/test_target.py'
--- autoppa/tests/test_target.py 2009-10-21 22:20:53 +0000
+++ autoppa/tests/test_target.py 2009-10-28 06:25:19 +0000
@@ -33,10 +33,12 @@
33 self.expect = FakeExpect()33 self.expect = FakeExpect()
34 self.fs = FilesystemPath()34 self.fs = FilesystemPath()
35 self.branch_path = self.fs.make_dir("production")35 self.branch_path = self.fs.make_dir("production")
36 datetime_factory = datetime(2007, 8, 2, 13, 14, 15)
36 self.builder = BuildTarget(37 self.builder = BuildTarget(
37 "supertool", "1.3.11-upside1", "John Smith <john@upside.com>",38 "supertool", "1.3.11-upside1", "John Smith <john@upside.com>",
38 self.branch_path, self.fs.dirname, "supertool-ppa",39 self.branch_path, self.fs.dirname, "supertool-ppa",
39 ["dapper", "edgy", "feisty"], expect=self.expect,40 ["dapper", "edgy", "feisty"], "${version}.${dist_version}",
41 expect=self.expect, datetime_factory=datetime_factory,
40 system=self.expect.run)42 system=self.expect.run)
4143
42 def tearDown(self):44 def tearDown(self):
@@ -254,6 +256,30 @@
254 finally:256 finally:
255 file.close()257 file.close()
256258
259 def test_prepare_custom_files_with_custom_version_content(self):
260 """
261 L{BuildTarget.prepare_custom_files} replaces the magic
262 C{AUTOPPA_VERSION()} symbol in lines found in processed files
263 with a custom version template.
264 """
265 filename = self.fs.make_path(content="version = 'AUTOPPA_VERSION()'",
266 path="debian/version")
267 original_user = os.environ.get("USER")
268 os.environ["USER"] = "user_from_env"
269 try:
270 self.builder.version_template = ("${version}~${dist_codename}~"
271 "${dist_version}~${now}~${today}~${user}")
272 self.builder.working_tree = self.fs.dirname
273 self.builder.prepare_custom_files("dapper")
274 file = open(filename, "r")
275
276 expected = ("version = 'AUTOPPA_VERSION(1.3.11-upside1~dapper~"
277 "6.06~20070802131415~20070802~user_from_env)'")
278 self.assertEquals(file.read(), expected)
279 file.close()
280 finally:
281 os.environ["USER"] = original_user
282
257 def test_prepare_custom_files_with_version_replacement_suppressed(self):283 def test_prepare_custom_files_with_version_replacement_suppressed(self):
258 """284 """
259 L{BuildTarget.prepare_custom_files} replaces the magic285 L{BuildTarget.prepare_custom_files} replaces the magic
@@ -298,8 +324,7 @@
298 self.builder.changelog = " * Supertool runs 3x faster than before!"324 self.builder.changelog = " * Supertool runs 3x faster than before!"
299 self.builder.working_tree = self.fs.dirname325 self.builder.working_tree = self.fs.dirname
300 self.assertFalse(os.path.exists(changelog_filename))326 self.assertFalse(os.path.exists(changelog_filename))
301 factory = lambda: datetime(2007, 8, 2, 13, 14, 15)327 self.builder.prepare_custom_files("dapper")
302 self.builder.prepare_custom_files("dapper", datetime_factory=factory)
303 file = open(changelog_filename, "r")328 file = open(changelog_filename, "r")
304 try:329 try:
305 changelog = file.read()330 changelog = file.read()
@@ -338,8 +363,7 @@
338363
339 self.builder.changelog = " * Supertool runs 3x faster than before!"364 self.builder.changelog = " * Supertool runs 3x faster than before!"
340 self.builder.working_tree = self.fs.dirname365 self.builder.working_tree = self.fs.dirname
341 factory = lambda: datetime(2007, 8, 2, 13, 14, 15)366 self.builder.prepare_custom_files("dapper")
342 self.builder.prepare_custom_files("dapper", datetime_factory=factory)
343 file = open(changelog_filename, "r")367 file = open(changelog_filename, "r")
344 try:368 try:
345 changelog = file.read()369 changelog = file.read()

Subscribers

People subscribed via source and target branches

to all changes: