Skip to content

Commit d0531a5

Browse files
authored
Support fork username aliases with default branches (#45)
- On first setup we now rename local branch `release2` to `commaai_release2` (removes dangling `release2` branch after setup and switching to stock) - We also now add the `release2` branch to `installed_branches` for the fork so `emu fork list` now shows current branch after immediate set up with no switching - Add `dragonpilot` as an alias to `dragonpilot-community/dragonpilot`
1 parent a943d5e commit d0531a5

File tree

3 files changed

+93
-62
lines changed

3 files changed

+93
-62
lines changed

CHANGELOG.md

+7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
Release 0.1.10 (2020-08-28)
2+
=====
3+
4+
* On first setup we now rename local branch `release2` to `commaai_release2` (removes dangling `release2` branch after setup and switching to stock)
5+
* We also now add the `release2` branch to `installed_branches` for the fork so `emu fork list` now shows current branch after immediate set up with no switching
6+
* Add `dragonpilot` as an alias to `dragonpilot-community/dragonpilot`
7+
18
Release 0.1.9 (2020-08-12)
29
=====
310

commands/fork/__init__.py

+79-53
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@
88
from py_utils.emu_utils import OPENPILOT_PATH, FORK_PARAM_PATH, COLORS
99

1010
GIT_OPENPILOT_URL = 'https://github.com/commaai/openpilot'
11-
COMMA_ORIGIN_NAME = 'commaai'
12-
COMMA_DEFAULT_BRANCH = 'release2'
13-
1411
REMOTE_ALREADY_EXISTS = 'already exists'
1512
DEFAULT_BRANCH_START = 'HEAD branch: '
1613
REMOTE_BRANCHES_START = 'Remote branches:\n'
@@ -63,14 +60,26 @@ def _write(self):
6360
f.write(json.dumps(self.params, indent=2))
6461

6562

63+
class RemoteInfo:
64+
def __init__(self, fork_name, username_aliases, default_branch):
65+
self.username = None # to be added by Fork.__get_remote_info function
66+
self.fork_name = fork_name
67+
self.username_aliases = username_aliases
68+
self.default_branch = default_branch
69+
70+
6671
class Fork(CommandBase):
6772
def __init__(self):
6873
super().__init__()
6974
self.name = 'fork'
7075
self.description = '🍴 Manage installed forks, or install a new one'
7176

7277
self.fork_params = ForkParams()
73-
self.stock_aliases = ['stock', COMMA_ORIGIN_NAME, 'origin']
78+
self.remote_defaults = {'commaai': RemoteInfo('openpilot', ['stock', 'origin'], 'release2'),
79+
'dragonpilot-community': RemoteInfo('dragonpilot', ['dragonpilot'], 'devel-i18n')} # devel-i18n isn't most stable, but its name remains the same
80+
81+
self.comma_origin_name = 'commaai'
82+
self.comma_default_branch = self.remote_defaults['commaai'].default_branch
7483

7584
self.commands = {'switch': Command(description='🍴 Switch between any openpilot fork',
7685
flags=[Flag('username', '👤 The username of the fork\'s owner to switch to, will use current fork if not provided', required=False, dtype='str'),
@@ -82,13 +91,14 @@ def _list(self):
8291
if not self._init():
8392
return
8493
flags, e = self.parse_flags(self.commands['list'].parser)
94+
specified_fork = flags.fork
8595
if e is not None:
8696
error(e)
8797
self._help('list')
8898
return
8999

90100
installed_forks = self.fork_params.get('installed_forks')
91-
if flags.fork is None:
101+
if specified_fork is None:
92102
max_branches = 4 # max branches to display per fork when listing all forks
93103
success('Installed forks:')
94104
for idi, fork in enumerate(installed_forks):
@@ -118,52 +128,56 @@ def _list(self):
118128
break
119129
print()
120130
else:
121-
fork = flags.fork.lower()
122-
if fork in self.stock_aliases:
123-
fork = COMMA_ORIGIN_NAME
124-
flags.fork = COMMA_ORIGIN_NAME
125-
if fork not in installed_forks:
126-
error('{} not an installed fork! Try installing it with the {}switch{} command'.format(fork, COLORS.CYAN, COLORS.RED))
131+
specified_fork = specified_fork.lower()
132+
remote_info = self.__get_remote_info(specified_fork)
133+
if remote_info is not None: # there's an overriding default username available
134+
specified_fork = remote_info.username
135+
if specified_fork not in installed_forks:
136+
error('{} not an installed fork! Try installing it with the {}switch{} command'.format(specified_fork, COLORS.CYAN, COLORS.RED))
127137
return
128-
installed_branches = installed_forks[fork]['installed_branches']
129-
success('Installed branches for {}:'.format(flags.fork))
138+
installed_branches = installed_forks[specified_fork]['installed_branches']
139+
success('Installed branches for {}:'.format(specified_fork))
130140
for branch in installed_branches:
131141
print(' - {}{}{}'.format(COLORS.RED, branch, COLORS.ENDC))
132142

133-
134143
def _switch(self):
135144
if not self._init():
136145
return
137146
flags, e = self.parse_flags(self.commands['switch'].parser)
147+
username = flags.username
148+
branch = flags.branch
138149
if e is not None:
139150
error(e)
140151
self._help('switch')
141152
return
142153
else: # since both are non-required we need custom logic to check user supplied sufficient args/flags
143-
if flags.username is flags.branch is None:
154+
if username is branch is None:
144155
error('You must supply either username or branch or both!')
145156
self._help('switch')
146157
return
147158

148-
if flags.username is None: # branch is specified, so use current checked out fork/username
159+
if username is None: # branch is specified, so use current checked out fork/username
149160
_current_fork = self.fork_params.get('current_fork')
150161
if _current_fork is not None: # ...if available
151162
info('Assuming current fork for username: {}'.format(COLORS.SUCCESS + _current_fork + COLORS.ENDC))
152-
flags.username = _current_fork
163+
username = _current_fork
153164
else:
154165
error('Current fork is unknown, please switch to a fork first before switching between branches!')
155166
return
156167

157-
username = flags.username.lower()
158-
if username in self.stock_aliases:
159-
username = COMMA_ORIGIN_NAME
160-
flags.username = COMMA_ORIGIN_NAME
168+
username = username.lower()
169+
remote_info = self.__get_remote_info(username)
170+
if remote_info is not None: # user entered an alias (ex. stock, dragonpilot)
171+
username = remote_info.username
161172

162173
installed_forks = self.fork_params.get('installed_forks')
163174
fork_in_params = True
164175
if username not in installed_forks:
165176
fork_in_params = False
166-
remote_url = 'https://github.com/{}/openpilot'.format(username)
177+
if remote_info is not None:
178+
remote_url = f'https://github.com/{username}/{remote_info.fork_name}' # dragonpilot doesn't have a GH redirect
179+
else: # for most forks, GH will redirect from /openpilot if user renames fork
180+
remote_url = f'https://github.com/{username}/openpilot'
167181

168182
if not valid_fork_url(remote_url):
169183
error('Invalid username! {} does not exist'.format(remote_url))
@@ -182,9 +196,9 @@ def _switch(self):
182196

183197
# fork has been added as a remote, switch to it
184198
if fork_in_params:
185-
info('Fetching {}\'s latest changes...'.format(COLORS.SUCCESS + flags.username + COLORS.WARNING))
199+
info('Fetching {}\'s latest changes...'.format(COLORS.SUCCESS + username + COLORS.WARNING))
186200
else:
187-
info('Fetching {}\'s fork, this may take a sec...'.format(COLORS.SUCCESS + flags.username + COLORS.WARNING))
201+
info('Fetching {}\'s fork, this may take a sec...'.format(COLORS.SUCCESS + username + COLORS.WARNING))
188202

189203
r = run(['git', '-C', OPENPILOT_PATH, 'fetch', username])
190204
if not r:
@@ -202,51 +216,52 @@ def _switch(self):
202216
error('Error: Cannot find default branch from fork!')
203217
return
204218

205-
if flags.branch is None: # user hasn't specified a branch, use remote's default branch
206-
if username == COMMA_ORIGIN_NAME: # todo: use a dict for default branches if we end up needing default branches for multiple forks
207-
branch = COMMA_DEFAULT_BRANCH # use release2 and default branch for stock
208-
fork_branch = 'commaai_{}'.format(branch)
219+
if branch is None: # user hasn't specified a branch, use remote's default branch
220+
if remote_info is not None: # there's an overriding default branch specified
221+
remote_branch = remote_info.default_branch
222+
local_branch = '{}_{}'.format(remote_info.username, remote_branch)
209223
else:
210-
fork_branch = '{}_{}'.format(username, default_remote_branch)
211-
branch = default_remote_branch # for command to checkout correct branch from remote, branch is previously None since user didn't specify
212-
elif len(flags.branch) > 0:
213-
fork_branch = f'{username}_{flags.branch}'
214-
branch = flags.branch
215-
if branch not in remote_branches:
224+
local_branch = '{}_{}'.format(username, default_remote_branch)
225+
remote_branch = default_remote_branch # for command to checkout correct branch from remote, branch is previously None since user didn't specify
226+
elif len(branch) > 0:
227+
local_branch = f'{username}_{branch}'
228+
remote_branch = branch
229+
if remote_branch not in remote_branches:
216230
error('The branch you specified does not exist!')
217-
self.__show_similar_branches(branch, remote_branches) # if possible
231+
self.__show_similar_branches(remote_branch, remote_branches) # if possible
218232
return
219233
else:
220234
error('Error with branch!')
221235
return
222236

223237
# checkout remote branch and prepend username so we can have multiple forks with same branch names locally
224-
remote_branch = f'{username}/{branch}'
225-
if branch not in installed_forks[username]['installed_branches']:
226-
info('New branch! Tracking and checking out {} from {}'.format(fork_branch, remote_branch))
227-
r = run(['git', '-C', OPENPILOT_PATH, 'checkout', '--track', '-b', fork_branch, remote_branch])
238+
if remote_branch not in installed_forks[username]['installed_branches']:
239+
info('New branch! Tracking and checking out {} from {}'.format(local_branch, f'{username}/{remote_branch}'))
240+
r = run(['git', '-C', OPENPILOT_PATH, 'checkout', '--track', '-b', local_branch, f'{username}/{remote_branch}'])
228241
if not r:
229242
error('Error while checking out branch, please try again')
230243
return
231-
self.__add_branch(username, branch) # we can deduce fork branch from username and original branch f({username}_{branch})
232-
else: # already installed branch, checking out fork_branch from remote_branch
233-
r = check_output(['git', '-C', OPENPILOT_PATH, 'checkout', fork_branch])
244+
self.__add_branch(username, remote_branch) # we can deduce fork branch from username and original branch f({username}_{branch})
245+
else: # already installed branch, checking out fork_branch from f'{username}/{branch}'
246+
r = check_output(['git', '-C', OPENPILOT_PATH, 'checkout', local_branch])
234247
if not r.success:
235248
error(r.output)
236249
return
237250
# reset to remote/branch just to ensure we checked out fully. if remote branch has been force pushed, this will also reset local to remote
238-
r = check_output(['git', '-C', OPENPILOT_PATH, 'reset', '--hard', remote_branch])
251+
r = check_output(['git', '-C', OPENPILOT_PATH, 'reset', '--hard', f'{username}/{remote_branch}'])
239252
if not r.success:
240253
error(r.output)
241254
return
242255
self.fork_params.put('current_fork', username)
243-
self.fork_params.put('current_branch', branch)
244-
success('Successfully checked out {}/{} as {}'.format(flags.username, branch, fork_branch))
256+
self.fork_params.put('current_branch', remote_branch)
257+
success('Successfully checked out {}/{} as {}'.format(username, remote_branch, local_branch))
245258

246-
def __add_fork(self, username):
259+
def __add_fork(self, username, branch=None):
247260
installed_forks = self.fork_params.get('installed_forks')
248261
if username not in installed_forks:
249262
installed_forks[username] = {'installed_branches': []}
263+
if branch is not None:
264+
installed_forks[username]['installed_branches'].append(branch)
250265
self.fork_params.put('installed_forks', installed_forks)
251266

252267
def __add_branch(self, username, branch): # assumes fork exists in params
@@ -285,6 +300,15 @@ def __prune_remote_branches(self, username): # remove deleted remote branches l
285300
error('Please try again, something went wrong:')
286301
print(r.output)
287302

303+
def __get_remote_info(self, username):
304+
for default_username in self.remote_defaults:
305+
remote_info = self.remote_defaults[default_username]
306+
remote_info.username = default_username # add dict key to class instance so we don't have to return a tuple
307+
remote_info.username_aliases.append(default_username) # so default branch works when user enters the actual name
308+
if username in remote_info.username_aliases:
309+
return remote_info
310+
return None
311+
288312
def __get_remote_branches(self, r):
289313
# get remote's branches to verify from output of command in parent function
290314
if not r.success:
@@ -330,7 +354,7 @@ def _init(self):
330354
if self.fork_params.get('setup_complete'):
331355
if os.path.exists(OPENPILOT_PATH):
332356
r = check_output(['git', '-C', OPENPILOT_PATH, 'remote', 'show'])
333-
if COMMA_ORIGIN_NAME in r.output.split('\n'): # sign that we're set up correctly todo: check all forks exist as remotes
357+
if self.comma_origin_name in r.output.split('\n'): # sign that we're set up correctly todo: check all forks exist as remotes
334358
return True
335359
self.fork_params.put('setup_complete', False) # renamed origin -> commaai does not exist, restart setup
336360
self.fork_params.reset()
@@ -353,21 +377,23 @@ def _init(self):
353377
success('Backed up your current openpilot install to {}'.format(bak_dir))
354378

355379
info('Cloning commaai/openpilot into {}, please wait...'.format(OPENPILOT_PATH))
356-
r = run(['git', 'clone', '-b', COMMA_DEFAULT_BRANCH, GIT_OPENPILOT_URL, OPENPILOT_PATH]) # default to r2 for stock
380+
r = run(['git', 'clone', '-b', self.comma_default_branch, GIT_OPENPILOT_URL, OPENPILOT_PATH]) # default to stock/release2 for setup
357381
if not r:
358382
error('Error while cloning, please try again')
359383
return
360384

361385
# rename origin to commaai so it's easy to switch to stock without any extra logic for url checking, etc
362-
r = check_output(['git', '-C', OPENPILOT_PATH, 'remote', 'rename', 'origin', COMMA_ORIGIN_NAME])
386+
r = check_output(['git', '-C', OPENPILOT_PATH, 'remote', 'rename', 'origin', self.comma_origin_name])
363387
if not r.success:
364388
error(r.output)
365389
return
390+
# rename release2 to commaai_release2 to align with emu fork standards
391+
check_output(['git', '-C', OPENPILOT_PATH, 'branch', '-m', f'{self.comma_origin_name}_{self.comma_default_branch}'])
366392

367-
success('Fork management set up successfully! You\'re on {}/{}'.format(COMMA_ORIGIN_NAME, COMMA_DEFAULT_BRANCH))
393+
success('Fork management set up successfully! You\'re on {}/{}'.format(self.comma_origin_name, self.comma_default_branch))
368394
success('To get started, try running: {}emu fork switch (username) [-b BRANCH]{}'.format(COLORS.RED, COLORS.ENDC))
395+
self.__add_fork(self.comma_origin_name, self.comma_default_branch)
369396
self.fork_params.put('setup_complete', True)
370-
self.fork_params.put('current_fork', COMMA_ORIGIN_NAME)
371-
self.fork_params.put('current_branch', COMMA_DEFAULT_BRANCH)
372-
self.__add_fork(COMMA_ORIGIN_NAME)
397+
self.fork_params.put('current_fork', self.comma_origin_name)
398+
self.fork_params.put('current_branch', self.comma_default_branch)
373399
return True

install.sh

+7-9
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,9 @@
1616

1717
# This is the install script for https://emu.sh/
1818
# Located on git at https://github.com/emu-sh/.oh-my-comma
19-
# To install this, ssh into your comma device and paste: '
20-
'
21-
bash <(curl -fsSL install.emu.sh) # the brain of the bird
22-
source /home/.bashrc
23-
'
19+
# To install this, ssh into your comma device and paste:
20+
# bash <(curl -fsSL install.emu.sh) # the brain of the bird
21+
# source /home/.bashrc
2422

2523
SYSTEM_BASHRC_PATH=/home/.bashrc
2624
COMMUNITY_PATH=/data/community
@@ -60,7 +58,7 @@ if [ ! -x "$(command -v powerline-shell)" ] && [ $update = false ]; then
6058
fi
6159

6260
if [ $update = true ]; then
63-
echo "Installing emu utilities..."
61+
echo "\nInstalling emu utilities..."
6462
fi
6563

6664
echo "Remounting /system as rewritable (until NEOS 15)"
@@ -143,7 +141,7 @@ fi
143141

144142
printf "\033[92m"
145143
if [ $update = true ]; then
146-
printf "\nSuccessfully updated emu utilities!\n"
144+
printf "Successfully updated emu utilities!\n"
147145
else
148146
echo "Sourcing /home/.bashrc to apply the changes made during installation"
149147
source /home/.bashrc
@@ -152,11 +150,11 @@ fi
152150

153151
CURRENT_BRANCH=$(cd ${OH_MY_COMMA_PATH} && git rev-parse --abbrev-ref HEAD)
154152
if [ ${CURRENT_BRANCH} != "master" ]; then
155-
printf "\n\033[0;31mWarning:\033[0m your current .oh-my-comma git branch is ${CURRENT_BRANCH}. Run git -C /data/community/.oh-my-comma checkout master if this is unintentional\n"
153+
printf "\n\033[0;31mWarning:\033[0m your current .oh-my-comma git branch is ${CURRENT_BRANCH}. If this is unintentional, run:\n\033[92mgit -C /data/community/.oh-my-comma checkout master\033[0m\n\n"
156154
fi
157155

158156
echo "Current version: $OMC_VERSION"
159-
printf "\033[0mYou may need to run the following to reflect the update:\n \033[92msource ${OH_MY_COMMA_PATH}/emu.sh"
157+
printf "\033[0mYou may need to run the following to reflect the update:\n\033[92msource ${OH_MY_COMMA_PATH}/emu.sh"
160158
printf "\033[0m\n\n"
161159

162160
if [ $update = false ]; then

0 commit comments

Comments
 (0)