def __show_similar_branches(branch, branches): if len(branches) > 0: info('Did you mean:') close_branches = most_similar(branch, branches)[:5] for idx in range(len(close_branches)): cb = close_branches[idx][0] if idx == 0: cb = COLORS.OKGREEN + cb else: cb = COLORS.CYAN + cb print(' - {}{}'.format(cb, COLORS.ENDC))
def __init_submodules(): r = check_output(['git', '-C', OPENPILOT_PATH, 'submodule', 'status']) if len(r.output): info('Submodules detected, reinitializing!') r0 = check_output([ 'git', '-C', OPENPILOT_PATH, 'submodule', 'deinit', '--all', '-f' ]) r1 = check_output([ 'git', '-C', OPENPILOT_PATH, 'submodule', 'update', '--init', '--recursive' ]) if not r0.success or not r1.success: error('Error reinitializing submodules for this branch!') else: return True return False
def _reload(): info('This will kill the current openpilot tmux session, set up a new one, and relaunch openpilot.') info('Confirm you would like to continue') if not is_affirmative(): error('Aborting!') return r = check_output('tmux kill-session -t comma') if r.success: info('Killed the current openpilot session') else: warning('Error killing current openpilot session, continuing...') # Command below thanks to mlp r = check_output(['tmux', 'new', '-s', 'comma', '-d', "echo $$ > /dev/cpuset/app/tasks;" # add pid of current shell to app cpuset "echo $PPID > /dev/cpuset/app/tasks;" # (our parent, tmux, also gets all the cores) "/data/openpilot/launch_openpilot.sh"]) if r.success: success('Succesfully started a new tmux session for openpilot!') success('Type {}tmux a{} to attach to it'.format(COLORS.FAIL, COLORS.SUCCESS))
def _init(self): if os.path.isdir('/data/community/forks'): shutil.rmtree('/data/community/forks') # remove to save space if self.fork_params.get('setup_complete'): if os.path.exists(OPENPILOT_PATH): r = check_output( ['git', '-C', OPENPILOT_PATH, 'remote', 'show']) if self.comma_origin_name in r.output.split( '\n' ): # sign that we're set up correctly todo: check all forks exist as remotes return True self.fork_params.put( 'setup_complete', False ) # renamed origin -> commaai does not exist, restart setup self.fork_params.reset() warning( 'There was an error with your clone of commaai/openpilot, restarting initialization!' ) info( 'To set up emu fork management we will clone commaai/openpilot into {}' .format(OPENPILOT_PATH)) info('Confirm you would like to continue') if not is_affirmative(): error('Stopping initialization!') return # backup openpilot here to free up /data/openpilot if os.path.exists(OPENPILOT_PATH): bak_dir = '{}.bak'.format(OPENPILOT_PATH) idx = 0 while os.path.exists(bak_dir): bak_dir = '{}{}'.format(bak_dir, idx) idx += 1 shutil.move(OPENPILOT_PATH, bak_dir) success('Backed up your current openpilot install to {}'.format( bak_dir)) info('Cloning commaai/openpilot into {}, please wait...'.format( OPENPILOT_PATH)) r = run([ 'git', 'clone', '-b', self.comma_default_branch, GIT_OPENPILOT_URL, OPENPILOT_PATH ]) # default to stock/release2 for setup if not r: error('Error while cloning, please try again') return # rename origin to commaai so it's easy to switch to stock without any extra logic for url checking, etc r = check_output([ 'git', '-C', OPENPILOT_PATH, 'remote', 'rename', 'origin', self.comma_origin_name ]) if not r.success: error(r.output) return # rename release2 to commaai_release2 to align with emu fork standards r = check_output([ 'git', '-C', OPENPILOT_PATH, 'branch', '-m', f'{self.comma_origin_name}_{self.comma_default_branch}' ]) if not r.success: error(r.output) return # set git config push.default to `upstream` to remove differently named remote branch warning when pushing check_output([ 'git', '-C', OPENPILOT_PATH, 'config', 'push.default', 'upstream' ]) # not game breaking if this fails # remember username and password of user for pushing check_output([ 'git', '-C', OPENPILOT_PATH, 'config', 'credential.helper', 'cache --timeout=1440' ]) # cache for a day success('Fork management set up successfully! You\'re on {}/{}'.format( self.comma_origin_name, self.comma_default_branch)) success( 'To get started, try running: {}emu fork switch (username) [-b BRANCH]{}' .format(COLORS.RED, COLORS.ENDC)) self.__add_fork(self.comma_origin_name, self.comma_default_branch) self.fork_params.put('setup_complete', True) self.fork_params.put('current_fork', self.comma_origin_name) self.fork_params.put('current_branch', self.comma_default_branch) return True
def _switch(self): if not self._init(): return flags = self.get_flags('switch') if flags.username is flags.branch is None: # since both are non-required we need custom logic to check user supplied sufficient args/flags error('You must supply either username or branch or both') self._help('switch') return username = flags.username branch = flags.branch repo_name = flags.repo force_switch = flags.force if username is None: # branch is specified, so use current checked out fork/username _current_fork = self.fork_params.get('current_fork') if _current_fork is not None: # ...if available info('Assuming current fork for username: {}'.format( COLORS.SUCCESS + _current_fork + COLORS.ENDC)) username = _current_fork else: error( 'Current fork is unknown, please switch to a fork first before switching between branches!' ) return username = username.lower() remote_info = self.__get_remote_info(username) if remote_info is not None: # user entered an alias (ex. stock, dragonpilot) username = remote_info.username installed_forks = self.fork_params.get('installed_forks') fork_in_params = True if username not in installed_forks: fork_in_params = False if remote_info is not None: remote_url = f'https://github.com/{username}/{remote_info.fork_name}' # dragonpilot doesn't have a GH redirect else: # for most forks, GH will redirect from /openpilot if user renames fork if repo_name is None: repo_name = DEFAULT_REPO_NAME # openpilot remote_url = f'https://github.com/{username}/{repo_name}' if not valid_fork_url(remote_url): error('Invalid username{}! {} does not exist'.format( '' if flags.repo is None else ' or repository name', remote_url)) return r = check_output([ 'git', '-C', OPENPILOT_PATH, 'remote', 'add', username, remote_url ]) if r.success and r.output == '': success('Remote added successfully!') elif r.success and REMOTE_ALREADY_EXISTS in r.output: # remote already added, update params info('Fork exists but wasn\'t in params, updating now...') self.__add_fork(username) else: error(r.output) return # fork has been added as a remote, switch to it if fork_in_params: info('Fetching {}\'s latest changes...'.format(COLORS.SUCCESS + username + COLORS.WARNING)) else: info('Fetching {}\'s fork, this may take a sec...'.format( COLORS.SUCCESS + username + COLORS.WARNING)) r = run(['git', '-C', OPENPILOT_PATH, 'fetch', username]) if not r: error('Error while fetching remote, please try again') return self.__add_fork(username) self.__prune_remote_branches(username) r = check_output( ['git', '-C', OPENPILOT_PATH, 'remote', 'show', username]) remote_branches, default_remote_branch = self.__get_remote_branches(r) if remote_branches is None: return if DEFAULT_BRANCH_START not in r.output: error('Error: Cannot find default branch from fork!') return if branch is None: # user hasn't specified a branch, use remote's default branch if remote_info is not None: # there's an overriding default branch specified remote_branch = remote_info.default_branch local_branch = '{}_{}'.format(remote_info.username, remote_branch) else: remote_branch = default_remote_branch # for command to checkout correct branch from remote, branch is previously None since user didn't specify local_branch = '{}_{}'.format(username, default_remote_branch) else: if branch not in remote_branches: close_branches = most_similar( branch, remote_branches ) # remote_branches is gauranteed to have at least 1 branch if close_branches[0][1] > 0.5: branch = close_branches[0][0] info( 'Unknown branch, checking out most similar: {}'.format( COLORS.SUCCESS + branch + COLORS.WARNING)) else: error('The branch you specified does not exist!') self.__show_similar_branches( branch, remote_branches) # if possible return remote_branch = branch # branch is now gauranteed to be in remote_branches local_branch = f'{username}_{branch}' # checkout remote branch and prepend username so we can have multiple forks with same branch names locally if remote_branch not in installed_forks[username][ 'installed_branches']: info('New branch! Tracking and checking out {} from {}'.format( local_branch, f'{username}/{remote_branch}')) command = [ 'git', '-C', OPENPILOT_PATH, 'checkout', '--track', '-b', local_branch, f'{username}/{remote_branch}' ] else: # already installed branch, checking out fork_branch from f'{username}/{branch}' command = ['git', '-C', OPENPILOT_PATH, 'checkout', local_branch] if force_switch: command.append('-f') r = run(command) if not r: error( 'Error while checking out branch, please try again or use flag --force' ) return self.__add_branch( username, remote_branch ) # we can deduce fork branch from username and original branch f({username}_{branch}) # 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 r = check_output([ 'git', '-C', OPENPILOT_PATH, 'reset', '--hard', f'{username}/{remote_branch}' ]) if not r.success: error(r.output) return reinit_subs = self.__init_submodules() self.fork_params.put('current_fork', username) self.fork_params.put('current_branch', remote_branch) info('\n✅ Successfully checked out {}/{} as {}'.format( COLORS.SUCCESS + username, remote_branch + COLORS.WARNING, COLORS.SUCCESS + local_branch)) if reinit_subs: success('✅ Successfully reinitialized submodules!')