Merge ~cjwatson/launchpad:remove-sourcedeps into launchpad:master
- Git
- lp:~cjwatson/launchpad
- remove-sourcedeps
- Merge into master
Proposed by
Colin Watson
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Colin Watson | ||||
Approved revision: | 61619cac1ea8f9823ab2677ac4b5b346427bb8b9 | ||||
Merge reported by: | Otto Co-Pilot | ||||
Merged at revision: | not available | ||||
Proposed branch: | ~cjwatson/launchpad:remove-sourcedeps | ||||
Merge into: | launchpad:master | ||||
Prerequisite: | ~cjwatson/launchpad:brz-loom-3.0.0 | ||||
Diff against target: |
1054 lines (+24/-124) 12 files modified
.pre-commit-config.yaml (+0/-4) Makefile (+7/-8) dev/null (+0/-3) doc/explanation/navigating.rst (+0/-5) doc/explanation/running-details.rst (+0/-1) lib/lp/scripts/utilities/test.py (+1/-1) setup.cfg (+1/-1) utilities/link-external-sourcecode (+4/-27) utilities/rocketfuel-get (+3/-58) utilities/rocketfuel-setup (+0/-5) utilities/snakefood/Makefile (+1/-1) utilities/update-sourcecode (+7/-10) |
||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jürgen Gmach | Approve | ||
Review via email: mp+428729@code.launchpad.net |
Commit message
Remove the obsolete sourcedeps mechanism
Description of the change
All our Python dependencies are now either in the virtualenv or symlinked into the virtualenv from system-level packages.
`utilities/
To post a comment you must log in.
Revision history for this message
Jürgen Gmach (jugmac00) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml |
2 | index ddb984f..d1b37f1 100644 |
3 | --- a/.pre-commit-config.yaml |
4 | +++ b/.pre-commit-config.yaml |
5 | @@ -31,9 +31,7 @@ repos: |
6 | exclude: | |
7 | (?x)^( |
8 | lib/contrib/.* |
9 | - |lib/devscripts/.* |
10 | |utilities/community-contributions\.py |
11 | - |utilities/update-sourcecode |
12 | )$ |
13 | - repo: https://github.com/psf/black |
14 | rev: 22.3.0 |
15 | @@ -42,9 +40,7 @@ repos: |
16 | exclude: | |
17 | (?x)^( |
18 | lib/contrib/.* |
19 | - |lib/devscripts/.* |
20 | |utilities/community-contributions\.py |
21 | - |utilities/update-sourcecode |
22 | )$ |
23 | - repo: https://github.com/PyCQA/isort |
24 | rev: 5.9.2 |
25 | diff --git a/Makefile b/Makefile |
26 | index af03cce..b2e2be3 100644 |
27 | --- a/Makefile |
28 | +++ b/Makefile |
29 | @@ -190,8 +190,8 @@ inplace: build logs clean_logs codehosting-dir |
30 | .PHONY: build |
31 | build: compile apidoc jsbuild css_combine |
32 | |
33 | -# Bootstrap download-cache and sourcecode. Useful for CI jobs that want to |
34 | -# set these up from scratch. |
35 | +# Bootstrap download-cache. Useful for CI jobs that want to set this up |
36 | +# from scratch. |
37 | .PHONY: bootstrap |
38 | bootstrap: |
39 | if [ -d download-cache/.git ]; then \ |
40 | @@ -199,14 +199,13 @@ bootstrap: |
41 | else \ |
42 | git clone --depth=1 $(DEPENDENCY_REPO) download-cache; \ |
43 | fi |
44 | - utilities/update-sourcecode |
45 | |
46 | -# LP_SOURCEDEPS_PATH should point to the sourcecode directory, but we |
47 | -# want the parent directory where the download-cache and env directories |
48 | -# are. We re-use the variable that is using for the rocketfuel-get script. |
49 | +# LP_PROJECT_ROOT/LP_SOURCEDEPS_DIR points to the parent directory where the |
50 | +# download-cache and env directories are. We reuse the variables that are |
51 | +# used for the rocketfuel-get script. |
52 | download-cache: |
53 | -ifdef LP_SOURCEDEPS_PATH |
54 | - utilities/link-external-sourcecode $(LP_SOURCEDEPS_PATH)/.. |
55 | +ifneq (,$(LP_PROJECT_ROOT)$(LP_SOURCEDEPS_DIR)) |
56 | + utilities/link-external-sourcecode $(LP_PROJECT_ROOT)/$(LP_SOURCEDEPS_DIR) |
57 | else |
58 | @echo "Missing ./download-cache." |
59 | @echo "Developers: please run utilities/link-external-sourcecode." |
60 | diff --git a/doc/explanation/navigating.rst b/doc/explanation/navigating.rst |
61 | index 277d452..b4fd90f 100644 |
62 | --- a/doc/explanation/navigating.rst |
63 | +++ b/doc/explanation/navigating.rst |
64 | @@ -58,10 +58,5 @@ of the ones that come up from time to time. |
65 | ``brzplugins/`` |
66 | Breezy plugins used in running Launchpad. |
67 | |
68 | -``sourcecode/`` |
69 | - A directory into which we symlink branches of some of Launchpad's |
70 | - dependencies that haven't yet been turned into proper Python |
71 | - dependencies. |
72 | - |
73 | ``zcml/`` |
74 | Various configuration files for the Zope services. |
75 | diff --git a/doc/explanation/running-details.rst b/doc/explanation/running-details.rst |
76 | index aad600b..09c62db 100644 |
77 | --- a/doc/explanation/running-details.rst |
78 | +++ b/doc/explanation/running-details.rst |
79 | @@ -52,6 +52,5 @@ Get the code: |
80 | |
81 | $ git clone https://git.launchpad.net/launchpad |
82 | $ cd launchpad |
83 | - $ utilities/update-sourcecode |
84 | $ git clone --depth=1 https://git.launchpad.net/lp-source-dependencies download-cache |
85 | $ make |
86 | diff --git a/lib/devscripts/__init__.py b/lib/devscripts/__init__.py |
87 | deleted file mode 100644 |
88 | index 748fe27..0000000 |
89 | --- a/lib/devscripts/__init__.py |
90 | +++ /dev/null |
91 | @@ -1,10 +0,0 @@ |
92 | -# Copyright 2009 Canonical Ltd. This software is licensed under the |
93 | -# GNU Affero General Public License version 3 (see the file LICENSE). |
94 | - |
95 | -"""Scripts that are used in developing Launchpad.""" |
96 | - |
97 | -import os |
98 | - |
99 | - |
100 | -def get_launchpad_root(): |
101 | - return os.path.dirname(os.path.dirname(os.path.dirname(__file__))) |
102 | diff --git a/lib/devscripts/sourcecode.py b/lib/devscripts/sourcecode.py |
103 | deleted file mode 100644 |
104 | index 7293245..0000000 |
105 | --- a/lib/devscripts/sourcecode.py |
106 | +++ /dev/null |
107 | @@ -1,425 +0,0 @@ |
108 | -# Copyright 2009 Canonical Ltd. This software is licensed under the |
109 | -# GNU Affero General Public License version 3 (see the file LICENSE). |
110 | - |
111 | -"""Tools for maintaining the Launchpad source code.""" |
112 | - |
113 | -from __future__ import absolute_import, print_function |
114 | - |
115 | -__all__ = [ |
116 | - 'interpret_config', |
117 | - 'parse_config_file', |
118 | - 'plan_update', |
119 | -] |
120 | - |
121 | -import errno |
122 | -import json |
123 | -import optparse |
124 | -import os |
125 | -import shutil |
126 | -import sys |
127 | - |
128 | -try: |
129 | - from breezy import ui |
130 | - from breezy.branch import Branch |
131 | - from breezy.errors import ( |
132 | - BzrError, |
133 | - IncompatibleRepositories, |
134 | - NotBranchError, |
135 | - ) |
136 | - from breezy.plugin import load_plugins |
137 | - from breezy.revisionspec import RevisionSpec |
138 | - from breezy.trace import enable_default_logging, report_exception |
139 | - from breezy.upgrade import upgrade |
140 | - from breezy.workingtree import WorkingTree |
141 | -except ImportError: |
142 | - from bzrlib import ui |
143 | - from bzrlib.branch import Branch |
144 | - from bzrlib.errors import ( |
145 | - BzrError, |
146 | - IncompatibleRepositories, |
147 | - NotBranchError, |
148 | - ) |
149 | - from bzrlib.plugin import load_plugins |
150 | - from bzrlib.revisionspec import RevisionSpec |
151 | - from bzrlib.trace import enable_default_logging, report_exception |
152 | - from bzrlib.upgrade import upgrade |
153 | - from bzrlib.workingtree import WorkingTree |
154 | - |
155 | -from devscripts import get_launchpad_root |
156 | - |
157 | - |
158 | -def parse_config_file(file_handle): |
159 | - """Parse the source code config file 'file_handle'. |
160 | - |
161 | - :param file_handle: A file-like object containing sourcecode |
162 | - configuration. |
163 | - :return: A sequence of lines of either '[key, value]' or |
164 | - '[key, value, optional]'. |
165 | - """ |
166 | - for line in file_handle: |
167 | - if line == '\n' or line.startswith('#'): |
168 | - continue |
169 | - yield line.split() |
170 | - |
171 | - |
172 | -def interpret_config_entry(entry, use_http=False): |
173 | - """Interpret a single parsed line from the config file.""" |
174 | - branch_name = entry[0] |
175 | - components = entry[1].split(';revno=') |
176 | - branch_url = components[0] |
177 | - if use_http: |
178 | - branch_url = branch_url.replace('lp:', 'http://bazaar.launchpad.net/') |
179 | - if len(components) == 1: |
180 | - revision = None |
181 | - else: |
182 | - assert len(components) == 2, 'Bad branch URL: ' + entry[1] |
183 | - revision = components[1] or None |
184 | - if len(entry) > 2: |
185 | - assert len(entry) == 3 and entry[2].lower() == 'optional', ( |
186 | - 'Bad configuration line: should be space delimited values of ' |
187 | - 'sourcecode directory name, branch URL [, "optional"]\n' + |
188 | - ' '.join(entry)) |
189 | - optional = True |
190 | - else: |
191 | - optional = False |
192 | - return branch_name, branch_url, revision, optional |
193 | - |
194 | - |
195 | -def load_cache(cache_filename): |
196 | - try: |
197 | - cache_file = open(cache_filename, 'r') |
198 | - except IOError as e: |
199 | - if e.errno == errno.ENOENT: |
200 | - return {} |
201 | - else: |
202 | - raise |
203 | - with cache_file: |
204 | - return json.load(cache_file) |
205 | - |
206 | - |
207 | -def interpret_config(config_entries, public_only, use_http=False): |
208 | - """Interpret a configuration stream, as parsed by 'parse_config_file'. |
209 | - |
210 | - :param configuration: A sequence of parsed configuration entries. |
211 | - :param public_only: If true, ignore private/optional branches. |
212 | - :param use_http: If True, force all branch URLs to use http:// |
213 | - :return: A dict mapping the names of the sourcecode dependencies to a |
214 | - 2-tuple of their branches and whether or not they are optional. |
215 | - """ |
216 | - config = {} |
217 | - for entry in config_entries: |
218 | - branch_name, branch_url, revision, optional = interpret_config_entry( |
219 | - entry, use_http) |
220 | - if not optional or not public_only: |
221 | - config[branch_name] = (branch_url, revision, optional) |
222 | - return config |
223 | - |
224 | - |
225 | -def _subset_dict(d, keys): |
226 | - """Return a dict that's a subset of 'd', based on the keys in 'keys'.""" |
227 | - return {key: d[key] for key in keys} |
228 | - |
229 | - |
230 | -def plan_update(existing_branches, configuration): |
231 | - """Plan the update to existing branches based on 'configuration'. |
232 | - |
233 | - :param existing_branches: A sequence of branches that already exist. |
234 | - :param configuration: A dictionary of sourcecode configuration, such as is |
235 | - returned by `interpret_config`. |
236 | - :return: (new_branches, update_branches, removed_branches), where |
237 | - 'new_branches' are the branches in the configuration that don't exist |
238 | - yet, 'update_branches' are the branches in the configuration that do |
239 | - exist, and 'removed_branches' are the branches that exist locally, but |
240 | - not in the configuration. 'new_branches' and 'update_branches' are |
241 | - dicts of the same form as 'configuration', 'removed_branches' is a |
242 | - set of the same form as 'existing_branches'. |
243 | - """ |
244 | - existing_branches = set(existing_branches) |
245 | - config_branches = set(configuration.keys()) |
246 | - new_branches = config_branches - existing_branches |
247 | - removed_branches = existing_branches - config_branches |
248 | - update_branches = config_branches.intersection(existing_branches) |
249 | - return ( |
250 | - _subset_dict(configuration, new_branches), |
251 | - _subset_dict(configuration, update_branches), |
252 | - removed_branches) |
253 | - |
254 | - |
255 | -def find_branches(directory): |
256 | - """List the directory names in 'directory' that are branches.""" |
257 | - branches = [] |
258 | - for name in os.listdir(directory): |
259 | - if name in ('.', '..'): |
260 | - continue |
261 | - try: |
262 | - Branch.open(os.path.join(directory, name)) |
263 | - branches.append(name) |
264 | - except NotBranchError: |
265 | - pass |
266 | - return branches |
267 | - |
268 | - |
269 | -def get_revision_id(revision, from_branch, tip=False): |
270 | - """Return revision id for a revision number and a branch. |
271 | - |
272 | - If the revision is empty, the revision_id will be None. |
273 | - |
274 | - If ``tip`` is True, the revision value will be ignored. |
275 | - """ |
276 | - if not tip and revision: |
277 | - spec = RevisionSpec.from_string(revision) |
278 | - return spec.as_revision_id(from_branch) |
279 | - # else return None |
280 | - |
281 | - |
282 | -def _format_revision_name(revision, tip=False): |
283 | - """Formatting helper to return human-readable identifier for revision. |
284 | - |
285 | - If ``tip`` is True, the revision value will be ignored. |
286 | - """ |
287 | - if not tip and revision: |
288 | - return 'revision %s' % (revision,) |
289 | - else: |
290 | - return 'tip' |
291 | - |
292 | - |
293 | -def get_controldir(branch): |
294 | - try: |
295 | - # Breezy |
296 | - return branch.controldir |
297 | - except AttributeError: |
298 | - # Bazaar |
299 | - return branch.bzrdir |
300 | - |
301 | - |
302 | -def get_branches(sourcecode_directory, new_branches, |
303 | - possible_transports=None, tip=False, quiet=False): |
304 | - """Get the new branches into sourcecode.""" |
305 | - for project, (branch_url, revision, optional) in new_branches.items(): |
306 | - destination = os.path.join(sourcecode_directory, project) |
307 | - try: |
308 | - remote_branch = Branch.open( |
309 | - branch_url, possible_transports=possible_transports) |
310 | - except BzrError: |
311 | - if optional: |
312 | - report_exception(sys.exc_info(), sys.stderr) |
313 | - continue |
314 | - else: |
315 | - raise |
316 | - possible_transports.append( |
317 | - get_controldir(remote_branch).root_transport) |
318 | - if not quiet: |
319 | - print('Getting %s from %s at %s' % |
320 | - (project, branch_url, _format_revision_name(revision, tip))) |
321 | - # If the 'optional' flag is set, then it's a branch that shares |
322 | - # history with Launchpad, so we should share repositories. Otherwise, |
323 | - # we should avoid sharing repositories to avoid format |
324 | - # incompatibilities. |
325 | - force_new_repo = not optional |
326 | - revision_id = get_revision_id(revision, remote_branch, tip) |
327 | - get_controldir(remote_branch).sprout( |
328 | - destination, revision_id=revision_id, create_tree_if_local=True, |
329 | - source_branch=remote_branch, force_new_repo=force_new_repo, |
330 | - possible_transports=possible_transports) |
331 | - |
332 | - |
333 | -def find_stale(updated, cache, sourcecode_directory, quiet): |
334 | - """Find branches whose revision info doesn't match the cache.""" |
335 | - new_updated = dict(updated) |
336 | - for project, (branch_url, revision, optional) in updated.items(): |
337 | - cache_revision_info = cache.get(project) |
338 | - if cache_revision_info is None: |
339 | - continue |
340 | - cache_revno = cache_revision_info[0] |
341 | - cache_revision_id = cache_revision_info[1].encode('ASCII') |
342 | - if cache_revno != int(revision): |
343 | - continue |
344 | - destination = os.path.join(sourcecode_directory, project) |
345 | - try: |
346 | - branch = Branch.open(destination) |
347 | - except BzrError: |
348 | - continue |
349 | - last_revno, last_revision_id = branch.last_revision_info() |
350 | - if last_revno != cache_revno or last_revision_id != cache_revision_id: |
351 | - continue |
352 | - if not quiet: |
353 | - print('%s is already up to date.' % project) |
354 | - del new_updated[project] |
355 | - return new_updated |
356 | - |
357 | - |
358 | -def update_cache(cache, cache_filename, changed, sourcecode_directory, quiet): |
359 | - """Update the cache with the changed branches.""" |
360 | - old_cache = dict(cache) |
361 | - for project, (branch_url, revision, optional) in changed.items(): |
362 | - destination = os.path.join(sourcecode_directory, project) |
363 | - branch = Branch.open(destination) |
364 | - last_revno, last_revision_id = branch.last_revision_info() |
365 | - if not isinstance(last_revision_id, str): # Python 3 |
366 | - last_revision_id = last_revision_id.decode('ASCII') |
367 | - cache[project] = [last_revno, last_revision_id] |
368 | - if cache == old_cache: |
369 | - return |
370 | - with open(cache_filename, 'w') as cache_file: |
371 | - # XXX cjwatson 2020-01-21: Stop explicitly specifying separators |
372 | - # once we require Python >= 3.4 (where this is the default). |
373 | - json.dump( |
374 | - cache, cache_file, indent=4, separators=(',', ': '), |
375 | - sort_keys=True) |
376 | - if not quiet: |
377 | - print('Cache updated. Please commit "%s".' % cache_filename) |
378 | - |
379 | - |
380 | -def update_branches(sourcecode_directory, update_branches, |
381 | - possible_transports=None, tip=False, quiet=False): |
382 | - """Update the existing branches in sourcecode.""" |
383 | - if possible_transports is None: |
384 | - possible_transports = [] |
385 | - # XXX: JonathanLange 2009-11-09: Rather than updating one branch after |
386 | - # another, we could instead try to get them in parallel. |
387 | - for project, (branch_url, revision, optional) in update_branches.items(): |
388 | - # Update project from branch_url. |
389 | - destination = os.path.join(sourcecode_directory, project) |
390 | - if not quiet: |
391 | - print('Updating %s to %s' % |
392 | - (project, _format_revision_name(revision, tip))) |
393 | - local_tree = WorkingTree.open(destination) |
394 | - try: |
395 | - remote_branch = Branch.open( |
396 | - branch_url, possible_transports=possible_transports) |
397 | - except BzrError: |
398 | - if optional: |
399 | - report_exception(sys.exc_info(), sys.stderr) |
400 | - continue |
401 | - else: |
402 | - raise |
403 | - possible_transports.append( |
404 | - get_controldir(remote_branch).root_transport) |
405 | - revision_id = get_revision_id(revision, remote_branch, tip) |
406 | - try: |
407 | - result = local_tree.pull( |
408 | - remote_branch, stop_revision=revision_id, overwrite=True, |
409 | - possible_transports=possible_transports) |
410 | - except IncompatibleRepositories: |
411 | - # XXX JRV 20100407: Ideally get_controldir(remote_branch)._format |
412 | - # should be passed into upgrade() to ensure the format is the same |
413 | - # locally and remotely. Unfortunately smart server branches |
414 | - # have their _format set to RemoteFormat rather than an actual |
415 | - # format instance. |
416 | - upgrade(destination) |
417 | - # Upgraded, repoen working tree |
418 | - local_tree = WorkingTree.open(destination) |
419 | - result = local_tree.pull( |
420 | - remote_branch, stop_revision=revision_id, overwrite=True, |
421 | - possible_transports=possible_transports) |
422 | - if result.old_revid == result.new_revid: |
423 | - if not quiet: |
424 | - print(' (No change)') |
425 | - else: |
426 | - if result.old_revno < result.new_revno: |
427 | - change = 'Updated' |
428 | - else: |
429 | - change = 'Reverted' |
430 | - if not quiet: |
431 | - print(' (%s from %s to %s)' % ( |
432 | - change, result.old_revno, result.new_revno)) |
433 | - |
434 | - |
435 | -def remove_branches(sourcecode_directory, removed_branches, quiet=False): |
436 | - """Remove sourcecode that's no longer there.""" |
437 | - for project in removed_branches: |
438 | - destination = os.path.join(sourcecode_directory, project) |
439 | - if not quiet: |
440 | - print('Removing %s' % project) |
441 | - try: |
442 | - shutil.rmtree(destination) |
443 | - except OSError: |
444 | - os.unlink(destination) |
445 | - |
446 | - |
447 | -def update_sourcecode(sourcecode_directory, config_filename, cache_filename, |
448 | - public_only, tip, dry_run, quiet=False, use_http=False): |
449 | - """Update the sourcecode.""" |
450 | - config_file = open(config_filename) |
451 | - config = interpret_config( |
452 | - parse_config_file(config_file), public_only, use_http) |
453 | - config_file.close() |
454 | - cache = load_cache(cache_filename) |
455 | - if not os.path.exists(sourcecode_directory): |
456 | - os.makedirs(sourcecode_directory) |
457 | - branches = find_branches(sourcecode_directory) |
458 | - new, updated, removed = plan_update(branches, config) |
459 | - possible_transports = [] |
460 | - if dry_run: |
461 | - print('Branches to fetch:', new.keys()) |
462 | - print('Branches to update:', updated.keys()) |
463 | - print('Branches to remove:', list(removed)) |
464 | - else: |
465 | - get_branches( |
466 | - sourcecode_directory, new, possible_transports, tip, quiet) |
467 | - updated = find_stale(updated, cache, sourcecode_directory, quiet) |
468 | - update_branches( |
469 | - sourcecode_directory, updated, possible_transports, tip, quiet) |
470 | - changed = dict(updated) |
471 | - changed.update(new) |
472 | - update_cache( |
473 | - cache, cache_filename, changed, sourcecode_directory, quiet) |
474 | - remove_branches(sourcecode_directory, removed, quiet) |
475 | - |
476 | - |
477 | -# XXX: JonathanLange 2009-09-11: By default, the script will operate on the |
478 | -# current checkout. Most people only have symlinks to sourcecode in their |
479 | -# checkouts. This is fine for updating, but breaks for removing (you can't |
480 | -# shutil.rmtree a symlink) and breaks for adding, since it adds the new branch |
481 | -# to the checkout, rather than to the shared sourcecode area. Ideally, the |
482 | -# script would see that the sourcecode directory is full of symlinks and then |
483 | -# follow these symlinks to find the shared source directory. If the symlinks |
484 | -# differ from each other (because of developers fiddling with things), we can |
485 | -# take a survey of all of them, and choose the most popular. |
486 | - |
487 | - |
488 | -def main(args): |
489 | - parser = optparse.OptionParser("usage: %prog [options] [root [conffile]]") |
490 | - parser.add_option( |
491 | - '--public-only', action='store_true', |
492 | - help='Only fetch/update the public sourcecode branches.') |
493 | - parser.add_option( |
494 | - '--tip', action='store_true', |
495 | - help='Ignore revision constraints for all branches and pull tip') |
496 | - parser.add_option( |
497 | - '--dry-run', action='store_true', |
498 | - help='Do nothing, but report what would have been done.') |
499 | - parser.add_option( |
500 | - '--quiet', action='store_true', |
501 | - help="Don't print informational messages.") |
502 | - parser.add_option( |
503 | - '--use-http', action='store_true', |
504 | - help="Force bzr to use http to get the sourcecode branches " |
505 | - "rather than using bzr+ssh.") |
506 | - options, args = parser.parse_args(args) |
507 | - root = get_launchpad_root() |
508 | - if len(args) > 1: |
509 | - sourcecode_directory = args[1] |
510 | - else: |
511 | - sourcecode_directory = os.path.join(root, 'sourcecode') |
512 | - if len(args) > 2: |
513 | - config_filename = args[2] |
514 | - else: |
515 | - config_filename = os.path.join(root, 'utilities', 'sourcedeps.conf') |
516 | - cache_filename = os.path.join( |
517 | - root, 'utilities', 'sourcedeps.cache') |
518 | - if len(args) > 3: |
519 | - parser.error("Too many arguments.") |
520 | - if not options.quiet: |
521 | - print('Sourcecode: %s' % (sourcecode_directory,)) |
522 | - print('Config: %s' % (config_filename,)) |
523 | - enable_default_logging() |
524 | - # Tell bzr to use the terminal (if any) to show progress bars |
525 | - ui.ui_factory = ui.make_ui_for_terminal( |
526 | - sys.stdin, sys.stdout, sys.stderr) |
527 | - load_plugins() |
528 | - update_sourcecode( |
529 | - sourcecode_directory, config_filename, cache_filename, |
530 | - options.public_only, options.tip, options.dry_run, options.quiet, |
531 | - options.use_http) |
532 | - return 0 |
533 | diff --git a/lib/devscripts/tests/__init__.py b/lib/devscripts/tests/__init__.py |
534 | deleted file mode 100644 |
535 | index 62d7904..0000000 |
536 | --- a/lib/devscripts/tests/__init__.py |
537 | +++ /dev/null |
538 | @@ -1,4 +0,0 @@ |
539 | -# Copyright 2009 Canonical Ltd. This software is licensed under the |
540 | -# GNU Affero General Public License version 3 (see the file LICENSE). |
541 | - |
542 | -"""Tests for devscripts.""" |
543 | diff --git a/lib/devscripts/tests/test_sourcecode.py b/lib/devscripts/tests/test_sourcecode.py |
544 | deleted file mode 100644 |
545 | index e4c122c..0000000 |
546 | --- a/lib/devscripts/tests/test_sourcecode.py |
547 | +++ /dev/null |
548 | @@ -1,226 +0,0 @@ |
549 | -# Copyright 2009 Canonical Ltd. This software is licensed under the |
550 | -# GNU Affero General Public License version 3 (see the file LICENSE). |
551 | - |
552 | -"""Module docstring goes here.""" |
553 | - |
554 | -from __future__ import absolute_import, print_function |
555 | - |
556 | -import io |
557 | -import os |
558 | -import shutil |
559 | -import tempfile |
560 | -import unittest |
561 | - |
562 | -try: |
563 | - from breezy.bzr.bzrdir import BzrDir |
564 | - from breezy.tests import TestCase |
565 | - from breezy.transport import get_transport |
566 | -except ImportError: |
567 | - from bzrlib.bzrdir import BzrDir |
568 | - from bzrlib.tests import TestCase |
569 | - from bzrlib.transport import get_transport |
570 | - |
571 | -from devscripts import get_launchpad_root |
572 | -from devscripts.sourcecode import ( |
573 | - find_branches, |
574 | - interpret_config, |
575 | - parse_config_file, |
576 | - plan_update, |
577 | -) |
578 | - |
579 | - |
580 | -class TestParseConfigFile(unittest.TestCase): |
581 | - """Tests for the config file parser.""" |
582 | - |
583 | - def makeFile(self, contents): |
584 | - return io.StringIO(contents) |
585 | - |
586 | - def test_empty(self): |
587 | - # Parsing an empty config file returns an empty sequence. |
588 | - empty_file = self.makeFile("") |
589 | - self.assertEqual([], list(parse_config_file(empty_file))) |
590 | - |
591 | - def test_single_value(self): |
592 | - # Parsing a file containing a single key=value pair returns a sequence |
593 | - # containing the (key, value) as a list. |
594 | - config_file = self.makeFile("key value") |
595 | - self.assertEqual( |
596 | - [['key', 'value']], list(parse_config_file(config_file))) |
597 | - |
598 | - def test_comment_ignored(self): |
599 | - # If a line begins with a '#', then its a comment. |
600 | - comment_only = self.makeFile('# foo') |
601 | - self.assertEqual([], list(parse_config_file(comment_only))) |
602 | - |
603 | - def test_optional_value(self): |
604 | - # Lines in the config file can have a third optional entry. |
605 | - config_file = self.makeFile('key value optional') |
606 | - self.assertEqual( |
607 | - [['key', 'value', 'optional']], |
608 | - list(parse_config_file(config_file))) |
609 | - |
610 | - def test_whitespace_stripped(self): |
611 | - # Any whitespace around any of the tokens in the config file are |
612 | - # stripped out. |
613 | - config_file = self.makeFile(' key value optional ') |
614 | - self.assertEqual( |
615 | - [['key', 'value', 'optional']], |
616 | - list(parse_config_file(config_file))) |
617 | - |
618 | - |
619 | -class TestInterpretConfiguration(unittest.TestCase): |
620 | - """Tests for the configuration interpreter.""" |
621 | - |
622 | - def test_empty(self): |
623 | - # An empty configuration stream means no configuration. |
624 | - config = interpret_config([], False) |
625 | - self.assertEqual({}, config) |
626 | - |
627 | - def test_key_value(self): |
628 | - # A (key, value) pair without a third optional value is returned in |
629 | - # the configuration as a dictionary entry under 'key' with '(value, |
630 | - # None, False)' as its value. |
631 | - config = interpret_config([['key', 'value']], False) |
632 | - self.assertEqual({'key': ('value', None, False)}, config) |
633 | - |
634 | - def test_key_value_public_only(self): |
635 | - # A (key, value) pair without a third optional value is returned in |
636 | - # the configuration as a dictionary entry under 'key' with '(value, |
637 | - # None, False)' as its value when public_only is true. |
638 | - config = interpret_config([['key', 'value']], True) |
639 | - self.assertEqual({'key': ('value', None, False)}, config) |
640 | - |
641 | - def test_key_value_optional(self): |
642 | - # A (key, value, optional) entry is returned in the configuration as a |
643 | - # dictionary entry under 'key' with '(value, True)' as its value. |
644 | - config = interpret_config([['key', 'value', 'optional']], False) |
645 | - self.assertEqual({'key': ('value', None, True)}, config) |
646 | - |
647 | - def test_key_value_optional_public_only(self): |
648 | - # A (key, value, optional) entry is not returned in the configuration |
649 | - # when public_only is true. |
650 | - config = interpret_config([['key', 'value', 'optional']], True) |
651 | - self.assertEqual({}, config) |
652 | - |
653 | - def test_key_value_revision(self): |
654 | - # A (key, value) pair without a third optional value when the |
655 | - # value has a suffix of ``;revno=[REVISION]`` is returned in the |
656 | - # configuration as a dictionary entry under 'key' with '(value, |
657 | - # None, False)' as its value. |
658 | - config = interpret_config([['key', 'value;revno=45']], False) |
659 | - self.assertEqual({'key': ('value', '45', False)}, config) |
660 | - |
661 | - def test_key_value_revision_with_multiple_revnos_raises_error(self): |
662 | - # A (key, value) pair without a third optional value when the |
663 | - # value has multiple suffixes of ``;revno=[REVISION]`` raises an |
664 | - # error. |
665 | - self.assertRaises( |
666 | - AssertionError, |
667 | - interpret_config, [['key', 'value;revno=45;revno=47']], False) |
668 | - |
669 | - def test_too_many_values(self): |
670 | - # A line with too many values raises an error. |
671 | - self.assertRaises( |
672 | - AssertionError, |
673 | - interpret_config, [['key', 'value', 'optional', 'extra']], False) |
674 | - |
675 | - def test_bad_optional_value(self): |
676 | - # A third value that is not the "optional" string raises an error. |
677 | - self.assertRaises( |
678 | - AssertionError, |
679 | - interpret_config, [['key', 'value', 'extra']], False) |
680 | - |
681 | - def test_use_http(self): |
682 | - # If use_http=True is passed to interpret_config, all lp: branch |
683 | - # URLs will be transformed into http:// URLs. |
684 | - config = interpret_config( |
685 | - [['key', 'lp:~sabdfl/foo/trunk']], False, use_http=True) |
686 | - expected_url = 'http://bazaar.launchpad.net/~sabdfl/foo/trunk' |
687 | - self.assertEqual(expected_url, config['key'][0]) |
688 | - |
689 | - |
690 | -class TestPlanUpdate(unittest.TestCase): |
691 | - """Tests for how to plan the update.""" |
692 | - |
693 | - def test_trivial(self): |
694 | - # In the trivial case, there are no existing branches and no |
695 | - # configured branches, so there are no branches to add, none to |
696 | - # update, and none to remove. |
697 | - new, existing, removed = plan_update([], {}) |
698 | - self.assertEqual({}, new) |
699 | - self.assertEqual({}, existing) |
700 | - self.assertEqual(set(), removed) |
701 | - |
702 | - def test_all_new(self): |
703 | - # If there are no existing branches, then the all of the configured |
704 | - # branches are new, none are existing and none have been removed. |
705 | - new, existing, removed = plan_update([], {'a': ('b', False)}) |
706 | - self.assertEqual({'a': ('b', False)}, new) |
707 | - self.assertEqual({}, existing) |
708 | - self.assertEqual(set(), removed) |
709 | - |
710 | - def test_all_old(self): |
711 | - # If there configuration is now empty, but there are existing |
712 | - # branches, then that means all the branches have been removed from |
713 | - # the configuration, none are new and none are updated. |
714 | - new, existing, removed = plan_update(['a', 'b', 'c'], {}) |
715 | - self.assertEqual({}, new) |
716 | - self.assertEqual({}, existing) |
717 | - self.assertEqual({'a', 'b', 'c'}, removed) |
718 | - |
719 | - def test_all_same(self): |
720 | - # If the set of existing branches is the same as the set of |
721 | - # non-existing branches, then they all need to be updated. |
722 | - config = {'a': ('b', False), 'c': ('d', True)} |
723 | - new, existing, removed = plan_update(config.keys(), config) |
724 | - self.assertEqual({}, new) |
725 | - self.assertEqual(config, existing) |
726 | - self.assertEqual(set(), removed) |
727 | - |
728 | - def test_smoke_the_default_config(self): |
729 | - # Make sure we can parse, interpret and plan based on the default |
730 | - # config file. |
731 | - root = get_launchpad_root() |
732 | - config_filename = os.path.join(root, 'utilities', 'sourcedeps.conf') |
733 | - config_file = open(config_filename) |
734 | - config = interpret_config(parse_config_file(config_file), False) |
735 | - config_file.close() |
736 | - plan_update([], config) |
737 | - |
738 | - |
739 | -class TestFindBranches(TestCase): |
740 | - """Tests the way that we find branches.""" |
741 | - |
742 | - def setUp(self): |
743 | - TestCase.setUp(self) |
744 | - self.disable_directory_isolation() |
745 | - |
746 | - def makeBranch(self, path): |
747 | - transport = get_transport(path) |
748 | - transport.ensure_base() |
749 | - BzrDir.create_branch_convenience( |
750 | - transport.base, possible_transports=[transport]) |
751 | - |
752 | - def makeDirectory(self): |
753 | - directory = tempfile.mkdtemp() |
754 | - self.addCleanup(shutil.rmtree, directory) |
755 | - return directory |
756 | - |
757 | - def test_empty_directory_has_no_branches(self): |
758 | - # An empty directory has no branches. |
759 | - empty = self.makeDirectory() |
760 | - self.assertEqual([], list(find_branches(empty))) |
761 | - |
762 | - def test_directory_with_branches(self): |
763 | - # find_branches finds branches in the directory. |
764 | - directory = self.makeDirectory() |
765 | - self.makeBranch('%s/a' % directory) |
766 | - self.assertEqual(['a'], list(find_branches(directory))) |
767 | - |
768 | - def test_ignores_files(self): |
769 | - # find_branches ignores any files in the directory. |
770 | - directory = self.makeDirectory() |
771 | - some_file = open('%s/a' % directory, 'w') |
772 | - some_file.write('hello\n') |
773 | - some_file.close() |
774 | - self.assertEqual([], list(find_branches(directory))) |
775 | diff --git a/lib/lp/scripts/utilities/test.py b/lib/lp/scripts/utilities/test.py |
776 | index f0d5f7f..bb852f0 100755 |
777 | --- a/lib/lp/scripts/utilities/test.py |
778 | +++ b/lib/lp/scripts/utilities/test.py |
779 | @@ -179,7 +179,7 @@ defaults = { |
780 | # Find tests in the tests and ftests directories |
781 | "tests_pattern": "^f?tests$", |
782 | "test_path": [os.path.join(config.root, "lib")], |
783 | - "package": ["canonical", "lp", "devscripts", "launchpad_loggerhead"], |
784 | + "package": ["canonical", "lp", "launchpad_loggerhead"], |
785 | "layer": ["!(YUIAppServerLayer)"], |
786 | "require_unique_ids": True, |
787 | } |
788 | diff --git a/setup.cfg b/setup.cfg |
789 | index e1a8c8f..367bb34 100644 |
790 | --- a/setup.cfg |
791 | +++ b/setup.cfg |
792 | @@ -212,7 +212,7 @@ ignore = |
793 | |
794 | [isort] |
795 | # database/* have some implicit relative imports. |
796 | -known_first_party = canonical,lp,launchpad_loggerhead,devscripts,fti,replication,preflight,security,upgrade,dbcontroller |
797 | +known_first_party = canonical,lp,launchpad_loggerhead,fti,replication,preflight,security,upgrade,dbcontroller |
798 | known_pythonpath = _pythonpath |
799 | line_length = 79 |
800 | sections = FUTURE,PYTHONPATH,STDLIB,THIRDPARTY,FIRSTPARTY,LOCALFOLDER |
801 | diff --git a/utilities/link-external-sourcecode b/utilities/link-external-sourcecode |
802 | index bc2a58b..06af63f 100755 |
803 | --- a/utilities/link-external-sourcecode |
804 | +++ b/utilities/link-external-sourcecode |
805 | @@ -1,11 +1,11 @@ |
806 | #!/usr/bin/python3 |
807 | # |
808 | -# Copyright 2009-2017 Canonical Ltd. This software is licensed under the GNU |
809 | +# Copyright 2009-2023 Canonical Ltd. This software is licensed under the GNU |
810 | # Affero General Public License version 3 (see the file LICENSE). |
811 | |
812 | import optparse |
813 | import subprocess |
814 | -from os import curdir, listdir, makedirs, symlink, unlink |
815 | +from os import curdir, symlink, unlink |
816 | from os.path import abspath, basename, exists, islink, join, realpath, relpath |
817 | from sys import stderr, stdout |
818 | |
819 | @@ -21,18 +21,6 @@ def get_main_worktree(branch_dir): |
820 | return None |
821 | |
822 | |
823 | -def gen_missing_files(source, destination): |
824 | - """Generate info on every file in source not in destination. |
825 | - |
826 | - Yields `(source, destination)` tuples. |
827 | - """ |
828 | - for name in listdir(source): |
829 | - destination_file = join(destination, name) |
830 | - if not exists(destination_file): |
831 | - source_file = join(source, name) |
832 | - yield source_file, destination_file, |
833 | - |
834 | - |
835 | def link(source, destination): |
836 | """Symlink source to destination. |
837 | |
838 | @@ -55,8 +43,8 @@ if __name__ == "__main__": |
839 | parser = optparse.OptionParser( |
840 | usage="%prog [options] [parent]", |
841 | description=( |
842 | - "Add a symlink in <target>/sourcecode for each corresponding " |
843 | - "file in <parent>/sourcecode." |
844 | + "Add a symlink from <target>/download-cache to " |
845 | + "<parent>/download-cache." |
846 | ), |
847 | epilog=( |
848 | "Most of the time this does the right thing if run " |
849 | @@ -119,17 +107,6 @@ if __name__ == "__main__": |
850 | if options.parent is None: |
851 | parser.error("Parent tree not specified.") |
852 | |
853 | - if not exists(join(options.target, "sourcecode")): |
854 | - makedirs(join(options.target, "sourcecode")) |
855 | - |
856 | - missing_files = gen_missing_files( |
857 | - abspath(join(options.parent, "sourcecode")), |
858 | - abspath(join(options.target, "sourcecode")), |
859 | - ) |
860 | - |
861 | - for source, destination in missing_files: |
862 | - link(source, destination) |
863 | - |
864 | for folder_name in ("download-cache",): |
865 | source = abspath(join(options.parent, folder_name)) |
866 | destination = abspath(join(options.target, folder_name)) |
867 | diff --git a/utilities/rocketfuel-get b/utilities/rocketfuel-get |
868 | index 678ccb6..2c51408 100755 |
869 | --- a/utilities/rocketfuel-get |
870 | +++ b/utilities/rocketfuel-get |
871 | @@ -1,24 +1,13 @@ |
872 | #! /bin/bash |
873 | # |
874 | -# Copyright 2009-2017 Canonical Ltd. This software is licensed under the |
875 | +# Copyright 2009-2022 Canonical Ltd. This software is licensed under the |
876 | # GNU Affero General Public License version 3 (see the file LICENSE). |
877 | # |
878 | -# Update your copy of master and the necessary source dependencies, and make |
879 | -# sure all source dependencies are properly linked in to all the branches you |
880 | -# are working on. |
881 | +# Update your copy of master and the necessary source dependencies. |
882 | |
883 | # Stop if there's an error, and treat unset variables as errors. |
884 | set -eu |
885 | |
886 | -# A rough measure of how much stuff we can do in parallel. |
887 | -CPU_COUNT="$(grep -Ec '^processor\b' /proc/cpuinfo)" |
888 | - |
889 | -# Helper function to run a child process, indenting stdout to aid |
890 | -# readability. |
891 | -run-child() { |
892 | - "$@" | sed -e "s/^/ /" |
893 | -} |
894 | - |
895 | # Load local settings. |
896 | if [ -e "$HOME/.rocketfuel-env.sh" ] |
897 | then |
898 | @@ -39,7 +28,7 @@ git -C "$LP_TRUNK_PATH" pull |
899 | FINAL_REV=$(git -C "$LP_TRUNK_PATH" rev-parse HEAD) |
900 | |
901 | # Make sure our directories are around. |
902 | -mkdir -p "$LP_SOURCEDEPS_PATH" "$YUI_PATH" |
903 | +mkdir -p "$(dirname "$LP_DOWNLOAD_CACHE_PATH")" "$YUI_PATH" |
904 | |
905 | # Get/update the download cache. |
906 | if [ -d "$LP_DOWNLOAD_CACHE_PATH" ] |
907 | @@ -49,50 +38,6 @@ else |
908 | git clone --depth=1 lp:lp-source-dependencies "$LP_DOWNLOAD_CACHE_PATH" |
909 | fi |
910 | |
911 | -# Add or update sourcepackages. |
912 | -sourcedeps_conf="$(dirname "$0")/sourcedeps.conf" |
913 | -if [ ! -e "$sourcedeps_conf" ] |
914 | -then |
915 | - # Use the global deps which are stable. |
916 | - echo "Could not find $sourcedeps_conf" >&2 |
917 | - sourcedeps_conf="$LP_TRUNK_PATH/utilities/sourcedeps.conf" |
918 | -fi |
919 | - |
920 | -echo "Updating sourcecode dependencies in rocketfuel:" |
921 | -run-child \ |
922 | - "$LP_TRUNK_PATH/utilities/update-sourcecode" \ |
923 | - "$LP_SOURCEDEPS_PATH" "$sourcedeps_conf" |
924 | - |
925 | -# Update the current trees in the repo. |
926 | -echo "Updating sourcecode dependencies in current local branches:" |
927 | - |
928 | -# Find directories among local branches containing "sourcecode" directories. |
929 | -# Prints each as a null-terminated record (since Unix filenames may contain |
930 | -# newlines). |
931 | -find_branches_to_relink() { |
932 | - find "$LP_PROJECT_ROOT" \ |
933 | - -mindepth 2 -maxdepth 2 -type d -name sourcecode -printf '%h\0' |
934 | -} |
935 | - |
936 | -# Some setups may have lp-sourcedeps mixed in with the local branches. Echo |
937 | -# stdin to stdout, with these filenames filtered out. Filenames must be |
938 | -# null-terminated on input, and remain null-terminated on output. |
939 | -filter_branches_to_relink() { |
940 | - grep -vz '/lp-sourcedeps$' |
941 | -} |
942 | - |
943 | -# Re-link the sourcecode directories for local branches. Takes the branch |
944 | -# paths from stdin, as null-terminated records. |
945 | -relink_branches() { |
946 | - run-child xargs --no-run-if-empty \ |
947 | - --max-procs="${CPU_COUNT}" --max-args=1 --null \ |
948 | - "$LP_TRUNK_PATH/utilities/link-external-sourcecode" \ |
949 | - --parent "$LP_PROJECT_ROOT/$LP_SOURCEDEPS_DIR" --target |
950 | -} |
951 | - |
952 | -# Actually do it: |
953 | -find_branches_to_relink | filter_branches_to_relink | relink_branches |
954 | - |
955 | |
956 | # Build launchpad if there were changes. |
957 | if [ "$FINAL_REV" != "$INITIAL_REV" ] |
958 | diff --git a/utilities/rocketfuel-setup b/utilities/rocketfuel-setup |
959 | index e03e8be..e4e1237 100755 |
960 | --- a/utilities/rocketfuel-setup |
961 | +++ b/utilities/rocketfuel-setup |
962 | @@ -190,7 +190,6 @@ of the following steps: |
963 | $ git clone lp:launchpad |
964 | $ cd launchpad |
965 | $ git clone --depth=1 lp:lp-source-dependencies download-cache |
966 | -$ utilities/update-sourcecode |
967 | $ utilities/launchpad-database-setup |
968 | $ make schema |
969 | $ sudo make install |
970 | @@ -220,10 +219,6 @@ LP_TRUNK_NAME=\${LP_TRUNK_NAME:=launchpad} |
971 | LP_TRUNK_PATH=\$LP_PROJECT_ROOT/\$LP_TRUNK_NAME |
972 | |
973 | LP_SOURCEDEPS_DIR=\${LP_SOURCEDEPS_DIR:=lp-sourcedeps} |
974 | -LP_SOURCEDEPS_PATH=\$LP_PROJECT_ROOT/\$LP_SOURCEDEPS_DIR/sourcecode |
975 | - |
976 | -# Force tilde expansion |
977 | -LP_SOURCEDEPS_PATH=\$(eval echo \${LP_SOURCEDEPS_PATH}) |
978 | " > "$HOME/.rocketfuel-env.sh" |
979 | fi |
980 | |
981 | diff --git a/utilities/snakefood/Makefile b/utilities/snakefood/Makefile |
982 | index f3bbec7..06d92cc 100644 |
983 | --- a/utilities/snakefood/Makefile |
984 | +++ b/utilities/snakefood/Makefile |
985 | @@ -5,7 +5,7 @@ default: lp-clustered.svg |
986 | # Generate import dependency graph |
987 | lp.sfood: |
988 | sfood -i -u -I $(LIB_DIR)/sqlobject -I $(LIB_DIR)/schoolbell \ |
989 | - -I $(LIB_DIR)/devscripts -I $(LIB_DIR)/contrib \ |
990 | + -I $(LIB_DIR)/contrib \ |
991 | -I $(LIB_DIR)/canonical/not-used $(LIB_DIR)/canonical \ |
992 | $(LIB_DIR)/lp 2>/dev/null | grep -v contrib/ \ |
993 | | grep -v sqlobject | egrep -v 'BeautifulSoup|bs4' | grep -v psycopg \ |
994 | diff --git a/utilities/sourcedeps.cache b/utilities/sourcedeps.cache |
995 | deleted file mode 100644 |
996 | index 9e26dfe..0000000 |
997 | --- a/utilities/sourcedeps.cache |
998 | +++ /dev/null |
999 | @@ -1 +0,0 @@ |
1000 | -{} |
1001 | \ No newline at end of file |
1002 | diff --git a/utilities/sourcedeps.conf b/utilities/sourcedeps.conf |
1003 | deleted file mode 100644 |
1004 | index e37f376..0000000 |
1005 | --- a/utilities/sourcedeps.conf |
1006 | +++ /dev/null |
1007 | @@ -1,8 +0,0 @@ |
1008 | -# If you're adding items to this file you _must_ use the full path to |
1009 | -# the branch after lp: rather than just trusting that bzr/lp will expand |
1010 | -# the series for you. If you don't, update-sourcecode will break when |
1011 | -# running parallelised tests inside lxc containers. |
1012 | - |
1013 | -######################################################### |
1014 | -#### DEPRECATED. NO NEW ITEMS. NO NO NO NO NO NONONONONO |
1015 | -######################################################### |
1016 | diff --git a/utilities/sourcedeps.filter b/utilities/sourcedeps.filter |
1017 | deleted file mode 100644 |
1018 | index d81ca05..0000000 |
1019 | --- a/utilities/sourcedeps.filter |
1020 | +++ /dev/null |
1021 | @@ -1,3 +0,0 @@ |
1022 | -P *.o |
1023 | -P *.pyc |
1024 | -P *.so |
1025 | diff --git a/utilities/update-sourcecode b/utilities/update-sourcecode |
1026 | index 1f2189a..8ea9e06 100755 |
1027 | --- a/utilities/update-sourcecode |
1028 | +++ b/utilities/update-sourcecode |
1029 | @@ -1,18 +1,15 @@ |
1030 | -#!/usr/bin/python2 -u |
1031 | +#!/usr/bin/python3 |
1032 | # |
1033 | # Copyright 2009 Canonical Ltd. This software is licensed under the |
1034 | # GNU Affero General Public License version 3 (see the file LICENSE). |
1035 | |
1036 | -"""Update the sourcecode managed in sourcecode/.""" |
1037 | +"""Update the sourcecode managed in sourcecode/. |
1038 | |
1039 | -import os |
1040 | -import sys |
1041 | - |
1042 | -sys.path.insert( |
1043 | - 0, os.path.join(os.path.dirname(os.path.dirname(__file__)), "lib") |
1044 | -) |
1045 | +This script is now a no-op, and will be removed once no deployment machinery |
1046 | +uses it any more. |
1047 | +""" |
1048 | |
1049 | -from devscripts import sourcecode # noqa: E402 |
1050 | +import sys |
1051 | |
1052 | if __name__ == "__main__": |
1053 | - sys.exit(sourcecode.main(sys.argv)) |
1054 | + sys.exit(0) |