8
8
from py_utils .emu_utils import OPENPILOT_PATH , FORK_PARAM_PATH , COLORS
9
9
10
10
GIT_OPENPILOT_URL = 'https://github.com/commaai/openpilot'
11
- COMMA_ORIGIN_NAME = 'commaai'
12
- COMMA_DEFAULT_BRANCH = 'release2'
13
-
14
11
REMOTE_ALREADY_EXISTS = 'already exists'
15
12
DEFAULT_BRANCH_START = 'HEAD branch: '
16
13
REMOTE_BRANCHES_START = 'Remote branches:\n '
@@ -63,14 +60,26 @@ def _write(self):
63
60
f .write (json .dumps (self .params , indent = 2 ))
64
61
65
62
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
+
66
71
class Fork (CommandBase ):
67
72
def __init__ (self ):
68
73
super ().__init__ ()
69
74
self .name = 'fork'
70
75
self .description = '🍴 Manage installed forks, or install a new one'
71
76
72
77
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
74
83
75
84
self .commands = {'switch' : Command (description = '🍴 Switch between any openpilot fork' ,
76
85
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):
82
91
if not self ._init ():
83
92
return
84
93
flags , e = self .parse_flags (self .commands ['list' ].parser )
94
+ specified_fork = flags .fork
85
95
if e is not None :
86
96
error (e )
87
97
self ._help ('list' )
88
98
return
89
99
90
100
installed_forks = self .fork_params .get ('installed_forks' )
91
- if flags . fork is None :
101
+ if specified_fork is None :
92
102
max_branches = 4 # max branches to display per fork when listing all forks
93
103
success ('Installed forks:' )
94
104
for idi , fork in enumerate (installed_forks ):
@@ -118,52 +128,56 @@ def _list(self):
118
128
break
119
129
print ()
120
130
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 ))
127
137
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 ))
130
140
for branch in installed_branches :
131
141
print (' - {}{}{}' .format (COLORS .RED , branch , COLORS .ENDC ))
132
142
133
-
134
143
def _switch (self ):
135
144
if not self ._init ():
136
145
return
137
146
flags , e = self .parse_flags (self .commands ['switch' ].parser )
147
+ username = flags .username
148
+ branch = flags .branch
138
149
if e is not None :
139
150
error (e )
140
151
self ._help ('switch' )
141
152
return
142
153
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 :
144
155
error ('You must supply either username or branch or both!' )
145
156
self ._help ('switch' )
146
157
return
147
158
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
149
160
_current_fork = self .fork_params .get ('current_fork' )
150
161
if _current_fork is not None : # ...if available
151
162
info ('Assuming current fork for username: {}' .format (COLORS .SUCCESS + _current_fork + COLORS .ENDC ))
152
- flags . username = _current_fork
163
+ username = _current_fork
153
164
else :
154
165
error ('Current fork is unknown, please switch to a fork first before switching between branches!' )
155
166
return
156
167
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
161
172
162
173
installed_forks = self .fork_params .get ('installed_forks' )
163
174
fork_in_params = True
164
175
if username not in installed_forks :
165
176
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'
167
181
168
182
if not valid_fork_url (remote_url ):
169
183
error ('Invalid username! {} does not exist' .format (remote_url ))
@@ -182,9 +196,9 @@ def _switch(self):
182
196
183
197
# fork has been added as a remote, switch to it
184
198
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 ))
186
200
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 ))
188
202
189
203
r = run (['git' , '-C' , OPENPILOT_PATH , 'fetch' , username ])
190
204
if not r :
@@ -202,51 +216,52 @@ def _switch(self):
202
216
error ('Error: Cannot find default branch from fork!' )
203
217
return
204
218
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 )
209
223
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 :
216
230
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
218
232
return
219
233
else :
220
234
error ('Error with branch!' )
221
235
return
222
236
223
237
# 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 } ' ])
228
241
if not r :
229
242
error ('Error while checking out branch, please try again' )
230
243
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 ])
234
247
if not r .success :
235
248
error (r .output )
236
249
return
237
250
# 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 } ' ])
239
252
if not r .success :
240
253
error (r .output )
241
254
return
242
255
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 ))
245
258
246
- def __add_fork (self , username ):
259
+ def __add_fork (self , username , branch = None ):
247
260
installed_forks = self .fork_params .get ('installed_forks' )
248
261
if username not in installed_forks :
249
262
installed_forks [username ] = {'installed_branches' : []}
263
+ if branch is not None :
264
+ installed_forks [username ]['installed_branches' ].append (branch )
250
265
self .fork_params .put ('installed_forks' , installed_forks )
251
266
252
267
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
285
300
error ('Please try again, something went wrong:' )
286
301
print (r .output )
287
302
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
+
288
312
def __get_remote_branches (self , r ):
289
313
# get remote's branches to verify from output of command in parent function
290
314
if not r .success :
@@ -330,7 +354,7 @@ def _init(self):
330
354
if self .fork_params .get ('setup_complete' ):
331
355
if os .path .exists (OPENPILOT_PATH ):
332
356
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
334
358
return True
335
359
self .fork_params .put ('setup_complete' , False ) # renamed origin -> commaai does not exist, restart setup
336
360
self .fork_params .reset ()
@@ -353,21 +377,23 @@ def _init(self):
353
377
success ('Backed up your current openpilot install to {}' .format (bak_dir ))
354
378
355
379
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
357
381
if not r :
358
382
error ('Error while cloning, please try again' )
359
383
return
360
384
361
385
# 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 ])
363
387
if not r .success :
364
388
error (r .output )
365
389
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 } ' ])
366
392
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 ))
368
394
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 )
369
396
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 )
373
399
return True
0 commit comments