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
1=== modified file 'lib/devscripts/sourcecode.py'
2--- lib/devscripts/sourcecode.py 2009-09-19 01:11:00 +0000
3+++ lib/devscripts/sourcecode.py 2009-09-26 22:37:16 +0000
4@@ -10,6 +10,7 @@
5 'plan_update',
6 ]
7
8+import optparse
9 import os
10 import shutil
11 import sys
12@@ -39,17 +40,23 @@
13
14 def interpret_config_entry(entry):
15 """Interpret a single parsed line from the config file."""
16- return (entry[0], (entry[1], len(entry) > 2))
17-
18-
19-def interpret_config(config_entries):
20+ return entry[0], entry[1], len(entry) > 2
21+
22+
23+def interpret_config(config_entries, public_only):
24 """Interpret a configuration stream, as parsed by 'parse_config_file'.
25
26 :param configuration: A sequence of parsed configuration entries.
27+ :param public_only: If true, ignore private/optional branches.
28 :return: A dict mapping the names of the sourcecode dependencies to a
29 2-tuple of their branches and whether or not they are optional.
30 """
31- return dict(map(interpret_config_entry, config_entries))
32+ config = {}
33+ for entry in config_entries:
34+ branch_name, branch_url, optional = interpret_config_entry(entry)
35+ if not optional or not public_only:
36+ config[branch_name] = (branch_url, optional)
37+ return config
38
39
40 def _subset_dict(d, keys):
41@@ -156,17 +163,23 @@
42 os.unlink(destination)
43
44
45-def update_sourcecode(sourcecode_directory, config_filename):
46+def update_sourcecode(sourcecode_directory, config_filename, public_only,
47+ dry_run):
48 """Update the sourcecode."""
49 config_file = open(config_filename)
50- config = interpret_config(parse_config_file(config_file))
51+ config = interpret_config(parse_config_file(config_file), public_only)
52 config_file.close()
53 branches = find_branches(sourcecode_directory)
54 new, updated, removed = plan_update(branches, config)
55 possible_transports = []
56- get_branches(sourcecode_directory, new, possible_transports)
57- update_branches(sourcecode_directory, updated, possible_transports)
58- remove_branches(sourcecode_directory, removed)
59+ if dry_run:
60+ print 'Branches to fetch:', new.keys()
61+ print 'Branches to update:', updated.keys()
62+ print 'Branches to remove:', list(removed)
63+ else:
64+ get_branches(sourcecode_directory, new, possible_transports)
65+ update_branches(sourcecode_directory, updated, possible_transports)
66+ remove_branches(sourcecode_directory, removed)
67
68
69 def get_launchpad_root():
70@@ -185,6 +198,14 @@
71
72
73 def main(args):
74+ parser = optparse.OptionParser("usage: %prog [options] [root [conffile]]")
75+ parser.add_option(
76+ '--public-only', action='store_true',
77+ help='Only fetch/update the public sourcecode branches.')
78+ parser.add_option(
79+ '--dry-run', action='store_true',
80+ help='Only fetch/update the public sourcecode branches.')
81+ options, args = parser.parse_args(args)
82 root = get_launchpad_root()
83 if len(args) > 1:
84 sourcecode_directory = args[1]
85@@ -194,8 +215,12 @@
86 config_filename = args[2]
87 else:
88 config_filename = os.path.join(root, 'utilities', 'sourcedeps.conf')
89+ if len(args) > 3:
90+ parser.error("Too many arguments.")
91 print 'Sourcecode: %s' % (sourcecode_directory,)
92 print 'Config: %s' % (config_filename,)
93 load_plugins()
94- update_sourcecode(sourcecode_directory, config_filename)
95+ update_sourcecode(
96+ sourcecode_directory, config_filename,
97+ options.public_only, options.dry_run)
98 return 0
99
100=== modified file 'lib/devscripts/tests/test_sourcecode.py'
101--- lib/devscripts/tests/test_sourcecode.py 2009-09-11 07:02:38 +0000
102+++ lib/devscripts/tests/test_sourcecode.py 2009-09-26 22:37:16 +0000
103@@ -64,22 +64,36 @@
104
105 def test_empty(self):
106 # An empty configuration stream means no configuration.
107- config = interpret_config([])
108+ config = interpret_config([], False)
109 self.assertEqual({}, config)
110
111 def test_key_value(self):
112 # A (key, value) pair without a third optional value is returned in
113 # the configuration as a dictionary entry under 'key' with '(value,
114 # False)' as its value.
115- config = interpret_config([['key', 'value']])
116+ config = interpret_config([['key', 'value']], False)
117+ self.assertEqual({'key': ('value', False)}, config)
118+
119+ def test_key_value_public_only(self):
120+ # A (key, value) pair without a third optional value is returned in
121+ # the configuration as a dictionary entry under 'key' with '(value,
122+ # False)' as its value when public_only is true.
123+ config = interpret_config([['key', 'value']], True)
124 self.assertEqual({'key': ('value', False)}, config)
125
126 def test_key_value_optional(self):
127 # A (key, value, optional) entry is returned in the configuration as a
128 # dictionary entry under 'key' with '(value, True)' as its value.
129- config = interpret_config([['key', 'value', 'optional']])
130+ config = interpret_config([['key', 'value', 'optional']], False)
131 self.assertEqual({'key': ('value', True)}, config)
132
133+ def test_key_value_optional_public_only(self):
134+ # A (key, value, optional) entry is not returned in the configuration
135+ # when public_only is true.
136+ config = interpret_config([['key', 'value', 'optional']], True)
137+ self.assertEqual({}, config)
138+
139+
140
141 class TestPlanUpdate(unittest.TestCase):
142 """Tests for how to plan the update."""
143@@ -125,7 +139,7 @@
144 root = get_launchpad_root()
145 config_filename = os.path.join(root, 'utilities', 'sourcedeps.conf')
146 config_file = open(config_filename)
147- config = interpret_config(parse_config_file(config_file))
148+ config = interpret_config(parse_config_file(config_file), False)
149 config_file.close()
150 plan_update([], config)
151