File: pm-helper

package info (click to toggle)
ubuntu-dev-tools 0.206
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 1,172 kB
  • sloc: python: 9,120; sh: 1,304; perl: 135; makefile: 10
file content (142 lines) | stat: -rwxr-xr-x 4,619 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#!/usr/bin/python3
# Find the next thing to work on for proposed-migration
# Copyright (C) 2023 Canonical Ltd.
# Author: Steve Langasek <steve.langasek@ubuntu.com>

# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License, version 3.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import lzma
import sys
import webbrowser
from argparse import ArgumentParser

import yaml
from launchpadlib.launchpad import Launchpad

from ubuntutools.utils import get_url

# proposed-migration is only concerned with the devel series; unlike other
# tools, don't make this configurable
excuses_url = "https://ubuntu-archive-team.ubuntu.com/proposed-migration/update_excuses.yaml.xz"


def get_proposed_version(excuses, package):
    for k in excuses["sources"]:
        if k["source"] == package:
            return k.get("new-version")
    return None


def claim_excuses_bug(launchpad, bug, package):
    print(f"LP: #{bug.id}: {bug.title}")
    ubuntu = launchpad.distributions["ubuntu"]
    series = ubuntu.current_series.fullseriesname

    for task in bug.bug_tasks:
        # targeting to a series doesn't make the default task disappear,
        # it just makes it useless
        if task.bug_target_name == f"{package} ({series})":
            our_task = task
            break
        if task.bug_target_name == f"{package} (Ubuntu)":
            our_task = task

    if our_task.assignee == launchpad.me:
        print("Bug already assigned to you.")
        return True
    if our_task.assignee:
        print(f"Currently assigned to {our_task.assignee.name}")

    print("""Do you want to claim this bug? [yN] """, end="")
    sys.stdout.flush()
    response = sys.stdin.readline()
    if response.strip().lower().startswith("y"):
        our_task.assignee = launchpad.me
        our_task.lp_save()
        return True

    return False


def create_excuses_bug(launchpad, package, version):
    print("Will open a new bug")
    bug = launchpad.bugs.createBug(
        title=f"proposed-migration for {package} {version}",
        tags=("update-excuse"),
        target=f"https://api.launchpad.net/devel/ubuntu/+source/{package}",
        description=f"{package} {version} is stuck in -proposed.",
    )

    task = bug.bug_tasks[0]
    task.assignee = launchpad.me
    task.lp_save()

    print(f"Opening {bug.web_link} in browser")
    webbrowser.open(bug.web_link)
    return bug


def has_excuses_bugs(launchpad, package):
    ubuntu = launchpad.distributions["ubuntu"]
    pkg = ubuntu.getSourcePackage(name=package)
    if not pkg:
        raise ValueError(f"No such source package: {package}")

    tasks = pkg.searchTasks(tags=["update-excuse"], order_by=["id"])

    bugs = [task.bug for task in tasks]
    if not bugs:
        return False

    if len(bugs) == 1:
        print(f"There is 1 open update-excuse bug against {package}")
    else:
        print(f"There are {len(bugs)} open update-excuse bugs against {package}")

    for bug in bugs:
        if claim_excuses_bug(launchpad, bug, package):
            return True

    return True


def main():
    parser = ArgumentParser()
    parser.add_argument("-l", "--launchpad", dest="launchpad_instance", default="production")
    parser.add_argument(
        "-v", "--verbose", default=False, action="store_true", help="be more verbose"
    )
    parser.add_argument("package", nargs="?", help="act on this package only")
    args = parser.parse_args()

    args.launchpad = Launchpad.login_with("pm-helper", args.launchpad_instance, version="devel")

    f = get_url(excuses_url, False)
    with lzma.open(f) as lzma_f:
        excuses = yaml.load(lzma_f, Loader=yaml.CSafeLoader)

    if args.package:
        try:
            if not has_excuses_bugs(args.launchpad, args.package):
                proposed_version = get_proposed_version(excuses, args.package)
                if not proposed_version:
                    print(f"Package {args.package} not found in -proposed.")
                    sys.exit(1)
                create_excuses_bug(args.launchpad, args.package, proposed_version)
        except ValueError as e:
            sys.stderr.write(f"{e}\n")
    else:
        pass  # for now


if __name__ == "__main__":
    sys.exit(main())