Merge lp:~mwhudson/launchpad/public-only-update-sourcecode into lp:launchpad

Proposed by Michael Hudson-Doyle
Status: Merged
Merged at revision: not available
Proposed branch: lp:~mwhudson/launchpad/public-only-update-sourcecode
Merge into: lp:launchpad
Diff against target: 150 lines
2 files modified
lib/devscripts/sourcecode.py (+36/-11)
lib/devscripts/tests/test_sourcecode.py (+18/-4)
To merge this branch: bzr merge lp:~mwhudson/launchpad/public-only-update-sourcecode
Reviewer Review Type Date Requested Status
Tim Penhey (community) Approve
Review via email: mp+12394@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Michael Hudson-Doyle (mwhudson) wrote :

Hi,

When reviewing my "ami from scratch" branch, Jono pointed out that the decision of whether to include the private branches in the sourcecode directory was something that should live in the update-sourcecode script not the update-image ec2 command. This makes sense, so this branch introduces a "--public-only" flag to the script (and a --dry-run flag, because I managed to get very confused writing this somehow).

Cheers,
mwh

Revision history for this message
Tim Penhey (thumper) wrote :

Looks good to me.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/devscripts/sourcecode.py'
--- lib/devscripts/sourcecode.py 2009-09-19 01:11:00 +0000
+++ lib/devscripts/sourcecode.py 2009-09-26 22:37:16 +0000
@@ -10,6 +10,7 @@
10 'plan_update',10 'plan_update',
11 ]11 ]
1212
13import optparse
13import os14import os
14import shutil15import shutil
15import sys16import sys
@@ -39,17 +40,23 @@
3940
40def interpret_config_entry(entry):41def interpret_config_entry(entry):
41 """Interpret a single parsed line from the config file."""42 """Interpret a single parsed line from the config file."""
42 return (entry[0], (entry[1], len(entry) > 2))43 return entry[0], entry[1], len(entry) > 2
4344
4445
45def interpret_config(config_entries):46def interpret_config(config_entries, public_only):
46 """Interpret a configuration stream, as parsed by 'parse_config_file'.47 """Interpret a configuration stream, as parsed by 'parse_config_file'.
4748
48 :param configuration: A sequence of parsed configuration entries.49 :param configuration: A sequence of parsed configuration entries.
50 :param public_only: If true, ignore private/optional branches.
49 :return: A dict mapping the names of the sourcecode dependencies to a51 :return: A dict mapping the names of the sourcecode dependencies to a
50 2-tuple of their branches and whether or not they are optional.52 2-tuple of their branches and whether or not they are optional.
51 """53 """
52 return dict(map(interpret_config_entry, config_entries))54 config = {}
55 for entry in config_entries:
56 branch_name, branch_url, optional = interpret_config_entry(entry)
57 if not optional or not public_only:
58 config[branch_name] = (branch_url, optional)
59 return config
5360
5461
55def _subset_dict(d, keys):62def _subset_dict(d, keys):
@@ -156,17 +163,23 @@
156 os.unlink(destination)163 os.unlink(destination)
157164
158165
159def update_sourcecode(sourcecode_directory, config_filename):166def update_sourcecode(sourcecode_directory, config_filename, public_only,
167 dry_run):
160 """Update the sourcecode."""168 """Update the sourcecode."""
161 config_file = open(config_filename)169 config_file = open(config_filename)
162 config = interpret_config(parse_config_file(config_file))170 config = interpret_config(parse_config_file(config_file), public_only)
163 config_file.close()171 config_file.close()
164 branches = find_branches(sourcecode_directory)172 branches = find_branches(sourcecode_directory)
165 new, updated, removed = plan_update(branches, config)173 new, updated, removed = plan_update(branches, config)
166 possible_transports = []174 possible_transports = []
167 get_branches(sourcecode_directory, new, possible_transports)175 if dry_run:
168 update_branches(sourcecode_directory, updated, possible_transports)176 print 'Branches to fetch:', new.keys()
169 remove_branches(sourcecode_directory, removed)177 print 'Branches to update:', updated.keys()
178 print 'Branches to remove:', list(removed)
179 else:
180 get_branches(sourcecode_directory, new, possible_transports)
181 update_branches(sourcecode_directory, updated, possible_transports)
182 remove_branches(sourcecode_directory, removed)
170183
171184
172def get_launchpad_root():185def get_launchpad_root():
@@ -185,6 +198,14 @@
185198
186199
187def main(args):200def main(args):
201 parser = optparse.OptionParser("usage: %prog [options] [root [conffile]]")
202 parser.add_option(
203 '--public-only', action='store_true',
204 help='Only fetch/update the public sourcecode branches.')
205 parser.add_option(
206 '--dry-run', action='store_true',
207 help='Only fetch/update the public sourcecode branches.')
208 options, args = parser.parse_args(args)
188 root = get_launchpad_root()209 root = get_launchpad_root()
189 if len(args) > 1:210 if len(args) > 1:
190 sourcecode_directory = args[1]211 sourcecode_directory = args[1]
@@ -194,8 +215,12 @@
194 config_filename = args[2]215 config_filename = args[2]
195 else:216 else:
196 config_filename = os.path.join(root, 'utilities', 'sourcedeps.conf')217 config_filename = os.path.join(root, 'utilities', 'sourcedeps.conf')
218 if len(args) > 3:
219 parser.error("Too many arguments.")
197 print 'Sourcecode: %s' % (sourcecode_directory,)220 print 'Sourcecode: %s' % (sourcecode_directory,)
198 print 'Config: %s' % (config_filename,)221 print 'Config: %s' % (config_filename,)
199 load_plugins()222 load_plugins()
200 update_sourcecode(sourcecode_directory, config_filename)223 update_sourcecode(
224 sourcecode_directory, config_filename,
225 options.public_only, options.dry_run)
201 return 0226 return 0
202227
=== modified file 'lib/devscripts/tests/test_sourcecode.py'
--- lib/devscripts/tests/test_sourcecode.py 2009-09-11 07:02:38 +0000
+++ lib/devscripts/tests/test_sourcecode.py 2009-09-26 22:37:16 +0000
@@ -64,22 +64,36 @@
6464
65 def test_empty(self):65 def test_empty(self):
66 # An empty configuration stream means no configuration.66 # An empty configuration stream means no configuration.
67 config = interpret_config([])67 config = interpret_config([], False)
68 self.assertEqual({}, config)68 self.assertEqual({}, config)
6969
70 def test_key_value(self):70 def test_key_value(self):
71 # A (key, value) pair without a third optional value is returned in71 # A (key, value) pair without a third optional value is returned in
72 # the configuration as a dictionary entry under 'key' with '(value,72 # the configuration as a dictionary entry under 'key' with '(value,
73 # False)' as its value.73 # False)' as its value.
74 config = interpret_config([['key', 'value']])74 config = interpret_config([['key', 'value']], False)
75 self.assertEqual({'key': ('value', False)}, config)
76
77 def test_key_value_public_only(self):
78 # A (key, value) pair without a third optional value is returned in
79 # the configuration as a dictionary entry under 'key' with '(value,
80 # False)' as its value when public_only is true.
81 config = interpret_config([['key', 'value']], True)
75 self.assertEqual({'key': ('value', False)}, config)82 self.assertEqual({'key': ('value', False)}, config)
7683
77 def test_key_value_optional(self):84 def test_key_value_optional(self):
78 # A (key, value, optional) entry is returned in the configuration as a85 # A (key, value, optional) entry is returned in the configuration as a
79 # dictionary entry under 'key' with '(value, True)' as its value.86 # dictionary entry under 'key' with '(value, True)' as its value.
80 config = interpret_config([['key', 'value', 'optional']])87 config = interpret_config([['key', 'value', 'optional']], False)
81 self.assertEqual({'key': ('value', True)}, config)88 self.assertEqual({'key': ('value', True)}, config)
8289
90 def test_key_value_optional_public_only(self):
91 # A (key, value, optional) entry is not returned in the configuration
92 # when public_only is true.
93 config = interpret_config([['key', 'value', 'optional']], True)
94 self.assertEqual({}, config)
95
96
8397
84class TestPlanUpdate(unittest.TestCase):98class TestPlanUpdate(unittest.TestCase):
85 """Tests for how to plan the update."""99 """Tests for how to plan the update."""
@@ -125,7 +139,7 @@
125 root = get_launchpad_root()139 root = get_launchpad_root()
126 config_filename = os.path.join(root, 'utilities', 'sourcedeps.conf')140 config_filename = os.path.join(root, 'utilities', 'sourcedeps.conf')
127 config_file = open(config_filename)141 config_file = open(config_filename)
128 config = interpret_config(parse_config_file(config_file))142 config = interpret_config(parse_config_file(config_file), False)
129 config_file.close()143 config_file.close()
130 plan_update([], config)144 plan_update([], config)
131145