Skip to content
This repository was archived by the owner on Dec 12, 2022. It is now read-only.

Commit 2bccfbb

Browse files
authored
Merge pull request #6 from ubports/xenial_-_qa-mount-on-install
Accidentally modify the whole script accidentally
2 parents 8fdb197 + b8ff6ae commit 2bccfbb

File tree

3 files changed

+171
-68
lines changed

3 files changed

+171
-68
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,8 @@ optional arguments:
3434
| `sudo ubports-qa remove xenial_-_somebranch` | Remove the `xenial_-_somebranch` ppa and upgrade all packages |
3535
| `ubports-qa list` | List all installed testing-PPAs |
3636
| `sudo ubports-qa update` | Upgrade all packages |
37+
38+
39+
### Contributing
40+
41+
When modifying the ubports-qa script, run [black](https://github.com/ambv/black) before you commit. This helps to reduce the diffs between commits and keeps formatting simple.

debian/changelog

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
ubports-qa-scripts (0.2) xenial; urgency=medium
2+
3+
* Update code style
4+
* Fix script not mounting root filesystem read-write on several subcommands
5+
6+
-- Dalton Durst <dalton@ubports.com> Fri, 7 Sep 2018 14:09:03 -0500
7+
18
ubports-qa-scripts (0.1) xenial; urgency=medium
29

310
* Update to unified script mode

ubports-qa

Lines changed: 159 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -5,150 +5,241 @@ The UBports QA scripts allow you to efficiently manage PPAs from repo.ubports.co
55
Copyright 2018 UBports Foundation
66
Licensed GPL v. 3 or later
77
"""
8-
9-
import requests, subprocess, os, argparse
8+
import subprocess
9+
import os
10+
import argparse
1011
from enum import Enum
12+
import requests
13+
14+
GITHUB_API_PULLREQUEST = "https://api.github.com/repos/ubports/{repo}/pulls/{num}"
15+
JENKINS_API_BUILD = "https://ci.ubports.com/blue/rest/organizations/jenkins/pipelines/{repo}/branches/{ref}"
1116

12-
GITHUB_API_PULLREQUEST="https://api.github.com/repos/ubports/%s/pulls/%s"
13-
JENKINS_API_BUILD="https://ci.ubports.com/blue/rest/organizations/jenkins/pipelines/%s/branches/%s"
14-
REPO="http://repo.ubports.com/dists/%s/main/binary-armhf/Packages"
17+
IS_ROOT = os.geteuid() == 0
1518

16-
is_root = (os.geteuid() == 0)
1719

1820
class Status(Enum):
1921
SUCCESS = 1
2022
BULDING = 2
2123
FAILED = 3
2224

25+
26+
class WritableRootFS:
27+
"""
28+
A class to be used with the `with` statement to mount `/` read-write, for example::
29+
30+
with WritableRootFS():
31+
write_file(/good_file)
32+
33+
`/` will be remounted read-only on close, unless the file /userdata/.writable_image
34+
exists.
35+
"""
36+
37+
def __enter__(self):
38+
self.attempt_writable_mount()
39+
40+
def __exit__(self, exc_type, value, traceback):
41+
self.attempt_unmount()
42+
43+
@classmethod
44+
def attempt_writable_mount(cls):
45+
"""Tries to mount the rootfs read-write"""
46+
ensure_root()
47+
subprocess.run(["mount", "-o", "rw,remount", "/"])
48+
49+
@classmethod
50+
def attempt_unmount(cls):
51+
if not os.path.exists("/userdata/.writable_image"):
52+
ensure_root()
53+
os.sync()
54+
try:
55+
subprocess.run(["mount", "-o", "ro,remount", "/"], check=True)
56+
except subprocess.CalledProcessError:
57+
print_error("Failed to remount root filesystem read-only.")
58+
print_error("Please consider rebooting your device.")
59+
60+
2361
def ensure_root():
24-
if not is_root:
62+
if not IS_ROOT:
2563
die("Insufficient permissions, please run with sudo.")
2664

27-
def mount():
28-
subprocess.call(["mount", "-o", "rw,remount", "/"])
29-
30-
def unmount():
31-
if not os.path.exists("/userdata/.writable_image"):
32-
subprocess.call(["mount", "-o", "ro,remount", "/"])
3365

3466
def apt_update():
35-
subprocess.call(["apt", "update"])
67+
try:
68+
subprocess.run(["apt", "update"], check=True)
69+
except subprocess.CalledProcessError:
70+
print_error("Failed to run 'apt update'. See the output above for details.")
71+
3672

3773
def apt_upgrade():
38-
subprocess.call(["apt", "upgrade"])
74+
try:
75+
subprocess.run(["apt", "upgrade"], check=True)
76+
except subprocess.CalledProcessError:
77+
print_error("Failed to run 'apt upgrade'. See the output above for details.")
78+
3979

4080
def get_list_file(branch):
41-
return "/etc/apt/sources.list.d/ubports-%s.list" % branch
81+
return "/etc/apt/sources.list.d/ubports-{}.list".format(branch)
82+
4283

4384
def get_pref_file(branch):
44-
return "/etc/apt/preferences.d/ubports-%s.pref" % branch
85+
return "/etc/apt/preferences.d/ubports-{}.pref".format(branch)
86+
4587

4688
def list_exists(branch):
4789
return os.path.isfile(get_list_file(branch))
4890

91+
4992
def list_lists():
50-
return [f.split("ubports-")[1].split(".list")[0]
51-
for f in os.listdir("/etc/apt/preferences.d")
52-
if os.path.isfile(f) and f.startswith("ubports-")]
93+
return [
94+
f.split("ubports-")[1].split(".list")[0]
95+
for f in os.listdir("/etc/apt/preferences.d")
96+
if os.path.isfile(f) and f.startswith("ubports-")
97+
]
98+
5399

54100
def add_list(branch):
55101
if list_exists(branch):
56102
return
57103
if requests.get("http://repo.ubports.com/dists/" + branch).status_code != 200:
58104
die("PPA not found")
59-
with open(get_list_file(branch),"w+") as list:
60-
list.write("deb http://repo.ubports.com/ %s main" % branch)
105+
with open(get_list_file(branch), "w+") as repo_list:
106+
repo_list.write("deb http://repo.ubports.com/ {} main".format(branch))
107+
61108

62109
def remove_list(branch):
63110
# If it does not exist, just ignore
64111
if not list_exists(branch):
65112
return
66113
os.remove(get_list_file(branch))
67114

115+
68116
def get_github_pr(repo, num):
69-
ret = requests.get(GITHUB_API_PULLREQUEST % (repo, num))
117+
ret = requests.get(GITHUB_API_PULLREQUEST.format(repo=repo, num=num))
70118
if ret.status_code != 200:
71119
die("Pull-Request not found")
72120
return ret.json()
73121

122+
74123
def get_jenkins_build(repo, ref):
75-
ret = requests.get(JENKINS_API_BUILD % (repo, ref))
124+
ret = requests.get(JENKINS_API_BUILD.format(repo=repo, ref=ref))
76125
if ret.status_code != 200:
77126
die("Jenkins build not found")
78127
return ret.json()
79128

129+
80130
def get_issue_status(repo, ref):
81131
build = get_jenkins_build(repo, ref)["latestRun"]
82132
print(build)
83133
if build["result"] == "SUCCESS":
84134
return Status.SUCCESS
85135
elif build["result"] == "BULDING":
86136
return Status.BULDING
87-
else:
88-
return Status.FAILED
137+
138+
return Status.FAILED
139+
89140

90141
def get_issue_branch(repo, num):
91142
return get_github_pr(repo, num)["head"]["ref"]
92143

93-
def die(m):
94-
print(m)
95-
exit()
96144

97-
def install(args):
98-
ensure_root()
145+
def print_error(error_message):
146+
"""Prints error_message in red"""
147+
print("\033[91m" + error_message + "\033[0m")
148+
149+
150+
def die(error_message):
151+
"""Prints error_message in red and exits with status 3"""
152+
print_error(error_message)
153+
exit(3)
154+
155+
156+
def install_command(args):
157+
"""Install a PPA or Pull Request"""
99158
if args.pr != -1:
100159
args.repo.replace("ubports/", "")
101-
ref = get_issue_branch(args.repo, args.pr);
102-
status = get_issue_status(args.repo, ref);
160+
ref = get_issue_branch(args.repo, args.pr)
161+
status = get_issue_status(args.repo, ref)
103162
if status == Status.FAILED:
104163
die("Issue failed to build")
105164
if status == Status.BUILDING:
106165
die("Issue is currently building")
107-
add_list(args.repo)
108-
apt_update()
109-
apt_upgrade()
166+
with WritableRootFS():
167+
add_list(args.repo)
168+
apt_update()
169+
apt_upgrade()
110170

111-
def remove(args):
112-
ensure_root()
113-
if not list_exists(args.repo):
114-
die("Repo %s is not installed" % args.repo)
115-
remove_list(args.repo)
116-
update(args)
117-
118-
def list(args):
119-
print(" ".join(list_lists()))
120171

121-
def update(args):
122-
ensure_root()
123-
mount()
124-
apt_update()
125-
apt_upgrade()
126-
unmount()
127-
128-
parser = argparse.ArgumentParser(description='The UBports QA scripts allow you to efficiently manage PPAs from repo.ubports.com for testing deb components. See http://docs.ubports.com/en/latest/about/process/ppa.html.')
129-
subparsers = parser.add_subparsers(help='')
172+
def remove_command(args):
173+
"""Remove and uninstall a PPA"""
174+
if not list_exists(args.repo):
175+
die("Repo {} is not installed".format(args.repo))
176+
with WritableRootFS():
177+
remove_list(args.repo)
178+
apt_update()
179+
apt_upgrade()
130180

131-
parser_install = subparsers.add_parser('install', help='Install a ppa or pull-request', description='Install a ppa or pull-request. See http://docs.ubports.com/en/latest/about/process/ppa.html.')
132-
parser_install.add_argument('repo', type=str, help='Name of a PPA on repo.ubports.com. Alternatively, if the \'pr\' argument is provided, the name of a git repository can be specified to automatically add the PPA from a pull-request.')
133-
parser_install.add_argument('pr', type=int, help='Numeric ID of a pull-request on the git repository specified in the \'repo\' argument. If \'repo\' is supposed to be the name of a ppa, the \'pr\' argument should not be specified.', nargs='?', default=-1)
134-
parser_install.set_defaults(func=install)
135181

136-
parser_remove = subparsers.add_parser('remove', help='Remove and uninstall a PPA', description='Remove and uninstall a ppa')
137-
parser_remove.add_argument('repo', type=str, help='Name of the ppa')
138-
parser_remove.set_defaults(func=remove)
182+
def list_command(args):
183+
"""List installed PPAs"""
184+
print(" ".join(list_lists()))
139185

140-
parser_list = subparsers.add_parser('list', help='List installed PPAs', description='List installed PPAs')
141-
parser_list.set_defaults(func=list)
142186

143-
parser_update = subparsers.add_parser('update', help='Update all packages using apt', description='Update all packages using apt')
144-
parser_update.set_defaults(func=update)
187+
def update_command(args):
188+
"""Update all packages using apt"""
189+
with WritableRootFS():
190+
apt_update()
191+
apt_upgrade()
192+
193+
194+
parser = argparse.ArgumentParser(
195+
description="The UBports QA scripts allow you to efficiently manage PPAs from repo.ubports.com for testing deb components. See http://docs.ubports.com/en/latest/about/process/ppa.html."
196+
)
197+
subparsers = parser.add_subparsers(help="")
198+
199+
parser_install = subparsers.add_parser(
200+
"install",
201+
help=install_command.__doc__,
202+
description="Install a ppa or pull-request. See http://docs.ubports.com/en/latest/about/process/ppa.html.",
203+
)
204+
parser_install.add_argument(
205+
"repo",
206+
type=str,
207+
help="Name of a PPA on repo.ubports.com. Alternatively, if the 'pr' argument is provided, the name of a git repository can be specified to automatically add the PPA from a pull-request.",
208+
)
209+
parser_install.add_argument(
210+
"pr",
211+
type=int,
212+
help="Numeric ID of a pull-request on the git repository specified in the 'repo' argument. If 'repo' is supposed to be the name of a ppa, the 'pr' argument should not be specified.",
213+
nargs="?",
214+
default=-1,
215+
)
216+
parser_install.set_defaults(func=install_command)
217+
218+
parser_remove = subparsers.add_parser(
219+
"remove", help=remove_command.__doc__, description="Remove and uninstall a ppa"
220+
)
221+
parser_remove.add_argument("repo", type=str, help="Name of the ppa")
222+
parser_remove.set_defaults(func=remove_command)
223+
224+
parser_list = subparsers.add_parser(
225+
"list", help=list_command.__doc__, description="List installed PPAs"
226+
)
227+
parser_list.set_defaults(func=list_command)
228+
229+
parser_update = subparsers.add_parser(
230+
"update", help=update_command.__doc__, description="Update all packages using apt"
231+
)
232+
parser_update.set_defaults(func=update_command)
145233

146234
try:
147-
args = parser.parse_args()
148-
args.func(args)
235+
ARGS = parser.parse_args()
236+
ARGS.func(ARGS)
149237
except IOError as e:
238+
# We weren't allowed to do something with a file.
239+
# Either we aren't root or the disk is read-only.
150240
ensure_root()
151241
die(e)
152242
except AttributeError as e:
243+
# The user typed an incorrect command
153244
parser.print_help()
154-
exit()
245+
exit(4)

0 commit comments

Comments
 (0)