1
# Copyright 2009 Canonical Ltd. All rights reserved.
3
"""Implementation of the Launchpad script to list modified branches."""
6
__all__ = ['ModifiedBranchesScript']
9
from datetime import datetime, timedelta
11
from time import strptime
14
from zope.component import getUtility
16
from canonical.codehosting.vfs import branch_id_to_path
17
from canonical.config import config
18
from canonical.launchpad.scripts.base import (
19
LaunchpadScript, LaunchpadScriptFailure)
20
from lp.code.interfaces.branch import BranchType
21
from lp.code.interfaces.branchcollection import IAllBranches
24
class ModifiedBranchesScript(LaunchpadScript):
25
"""List branches modified since the specified time.
27
Only branches that have been modified since the specified time will be
28
returned. It is possible that the branch will have been modified only in
29
the web UI and not actually received any more revisions, and will be a
32
If the branch is REMOTE it is ignored.
33
If the branch is HOSTED, both the hosted and mirrored area are returned.
34
If the branch is an IMPORT or MIRROR branch, only the mirrored area is
39
"List branch paths for branches modified since the specified time.")
41
def __init__(self, name, dbuser=None, test_args=None):
42
LaunchpadScript.__init__(self, name, dbuser, test_args)
43
# Cache this on object creation so it can be used in tests.
44
self.now_timestamp = datetime.utcnow()
46
def add_my_options(self):
47
self.parser.add_option(
48
"-s", "--since", metavar="DATE",
49
help="A date in the format YYYY-MM-DD. Branches that "
50
"have been modified since this date will be returned.")
51
self.parser.add_option(
52
"-l", "--last-hours", metavar="HOURS", type="int",
53
help="Return the branches that have been modified in "
54
"the last HOURS number of hours.")
56
def get_last_modified_epoch(self):
57
"""Return the timezone aware datetime for the last modified epoch. """
58
if (self.options.last_hours is not None and
59
self.options.since is not None):
60
raise LaunchpadScriptFailure(
61
"Only one of --since or --last-hours can be specified.")
63
if self.options.last_hours is not None:
65
self.now_timestamp - timedelta(hours=self.options.last_hours))
66
elif self.options.since is not None:
68
parsed_time = strptime(self.options.since, '%Y-%m-%d')
69
last_modified = datetime(*(parsed_time[:3]))
71
raise LaunchpadScriptFailure(str(e))
73
raise LaunchpadScriptFailure(
74
"One of --since or --last-hours needs to be specified.")
76
# Make the datetime timezone aware.
77
return last_modified.replace(tzinfo=pytz.UTC)
79
def branch_locations(self, branch):
80
"""Return a list of branch paths for the given branch."""
81
path = branch_id_to_path(branch.id)
82
yield os.path.join(config.codehosting.mirrored_branches_root, path)
83
if branch.branch_type == BranchType.HOSTED:
84
yield os.path.join(config.codehosting.hosted_branches_root, path)
87
last_modified = self.get_last_modified_epoch()
89
"Looking for branches modified since %s", last_modified)
90
collection = getUtility(IAllBranches)
91
collection = collection.withBranchType(
92
BranchType.HOSTED, BranchType.MIRRORED, BranchType.IMPORTED)
93
collection = collection.scannedSince(last_modified)
94
for branch in collection.getBranches():
95
self.logger.info(branch.unique_name)
96
for location in self.branch_locations(branch):
99
self.logger.info("Done.")