Ejemplo n.º 1
0
    def __prune_remote_branches(
            self, username):  # remove deleted remote branches locally
        last_prune = self.fork_params.get('last_prune')
        if isinstance(last_prune,
                      str) and datetime.now().strftime("%d") == last_prune:
            return
        self.fork_params.put('last_prune', datetime.now().strftime("%d"))

        r = check_output([
            'git', '-C', OPENPILOT_PATH, 'remote', 'prune', username,
            '--dry-run'
        ])
        if r.output == '':  # nothing to prune
            return
        branches_to_prune = [
            b.strip() for b in r.output.split('\n') if 'would prune' in b
        ]
        branches_to_prune = [b[b.index(username):] for b in branches_to_prune]

        error('Deleted remote branches detected:', start='\n')
        for b in branches_to_prune:
            print(COLORS.CYAN + '  - {}'.format(b) + COLORS.ENDC)
        warning('\nWould you like to delete them locally?')
        if is_affirmative():
            r = check_output(
                ['git', '-C', OPENPILOT_PATH, 'remote', 'prune', username])
            if r.success:
                success('Pruned local branches successfully!')
            else:
                error('Please try again, something went wrong:')
                print(r.output)
Ejemplo n.º 2
0
 def _shutdown(self):
     flags = self.get_flags('shutdown')
     if flags.reboot:
         self.__reboot()
         return
     check_output(
         'am start -n android/com.android.internal.app.ShutdownActivity')
     success('🌙 Goodnight!')
Ejemplo n.º 3
0
 def _settings(self):
     flags = self.get_flags('settings')
     if flags.close:
         check_output('kill $(pgrep com.android.settings)', shell=True)
         success('⚙️ Closed settings!')
     else:
         check_output('am start -a android.settings.SETTINGS')
         success('⚙️ Opened settings!')
Ejemplo n.º 4
0
    def _shutdown(self):
        flags, e = self.parse_flags(self.commands['shutdown'].parser)
        if e is not None:
            error(e)
            self._help('shutdown')
            return

        if flags.reboot:
            self.__reboot()
            return
        check_output(
            'am start -n android/com.android.internal.app.ShutdownActivity')
        success('🌙 Goodnight!')
Ejemplo n.º 5
0
  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))
Ejemplo n.º 6
0
    def _list(self):
        if not self._init():
            return
        flags = self.get_flags('list')
        specified_fork = flags.fork

        installed_forks = self.fork_params.get('installed_forks')
        if specified_fork is None:
            max_branches = 4  # max branches to display per fork when listing all forks
            success('Installed forks:')
            for idi, fork in enumerate(installed_forks):
                print('- {}{}{}'.format(COLORS.OKBLUE, fork, COLORS.ENDC),
                      end='')
                current_fork = self.fork_params.get('current_fork')
                if current_fork == fork:
                    print(' (current)')
                else:
                    print()
                branches = installed_forks[fork]['installed_branches']
                current_branch = self.fork_params.get('current_branch')
                if current_branch in branches:
                    branches.remove(current_branch)
                    branches.insert(
                        0, current_branch)  # move cur_branch to beginning

                if len(branches) > 0:
                    success('   Branches:')
                for idx, branch in enumerate(branches):
                    if idx < max_branches:
                        print('   - {}{}{}'.format(COLORS.RED, branch,
                                                   COLORS.ENDC),
                              end='')
                        if branch == current_branch and fork == current_fork:
                            print(' (current)')
                        else:
                            print()
                    else:
                        print(
                            '   - {}...see more branches: {}emu fork list {}{}'
                            .format(COLORS.RED, COLORS.CYAN, fork,
                                    COLORS.ENDC))
                        break
                print()
        else:
            specified_fork = specified_fork.lower()
            remote_info = self.__get_remote_info(specified_fork)
            if remote_info is not None:  # there's an overriding default username available
                specified_fork = remote_info.username
            if specified_fork not in installed_forks:
                error(
                    '{} not an installed fork! Try installing it with the {}switch{} command'
                    .format(specified_fork, COLORS.CYAN, COLORS.RED))
                return
            installed_branches = installed_forks[specified_fork][
                'installed_branches']
            success('Installed branches for {}:'.format(specified_fork))
            for branch in installed_branches:
                print(' - {}{}{}'.format(COLORS.RED, branch, COLORS.ENDC))
Ejemplo n.º 7
0
    def _battery():
        r = check_output('dumpsys batterymanager')
        if not r:
            error('Unable to get battery status!')
            return
        r = r.output.split('\n')
        r = [i.strip() for i in r if i != ''][1:]
        battery_idxs = {'level': 7, 'temperature': 10}
        success('Battery info:')
        for name in battery_idxs:
            idx = battery_idxs[name]
            info = r[idx]

            value = float(info.split(': ')[1])
            if name == 'temperature':
                value /= 10
                value = str(value) + '°C'
            else:
                value = str(value) + '%'

            value = COLORS.SUCCESS + str(value)
            name = COLORS.WARNING + name.title()
            print('- {}: {}{}'.format(name, value, COLORS.ENDC))
Ejemplo n.º 8
0
  def _help(self, cmd, show_description=True, leading=''):
    has_extra_info = False
    description = self.commands[cmd].description
    if show_description:
      print('{}>>  Description 📚: {}{}'.format(COLORS.CYAN, description, COLORS.ENDC))

    flags = self.commands[cmd].flags

    flags_to_print = []
    if flags is not None and len(flags) > 0:
      has_extra_info = True
      usage_req = [f.aliases[0] for f in flags if f.required and len(f.aliases) == 1]  # if required
      usage_non_req = [f.aliases[0] for f in flags if not f.required and len(f.aliases) == 1]  # if non-required non-positional
      usage_flags = [f.aliases for f in flags if not f.required and len(f.aliases) > 1 or f.aliases[0].startswith('-')]  # if flag
      if len(usage_req) > 0 or len(usage_non_req) > 0:  # print usage with proper braces
        usage_req = ['[{}]'.format(u) for u in usage_req]
        usage_non_req = ['({})'.format(u) for u in usage_non_req]
        if len(usage_flags):
          # formats flags to: "[-b BRANCH, -o OUTPUT]"
          usage_flags = ['{} {}'.format(min(u, key=len), max(u, key=len).upper()[2:]) for u in usage_flags]
          usage_flags = ['[{}]'.format(', '.join(usage_flags))]

        usage = ['emu', self.name, cmd] + usage_req + usage_non_req + usage_flags
        print(leading + COLORS.WARNING + '>>  Usage:{} {}'.format(COLORS.OKGREEN, ' '.join(usage)) + COLORS.ENDC)

      print(leading + COLORS.WARNING + '>>  Arguments 💢:' + COLORS.ENDC)
      for flag in flags:
        aliases = COLORS.SUCCESS + ', '.join(flag.aliases) + COLORS.WARNING
        if not flag.required and '-' not in aliases:
          aliases += COLORS.RED + ' (optional)' + COLORS.WARNING
        flags_to_print.append(leading + COLORS.WARNING + '  - {}: {}'.format(aliases, flag.description) + COLORS.ENDC)
      print('\n'.join(flags_to_print))

    commands = self.commands[cmd].commands
    cmds_to_print = []
    if commands is not None and len(commands) > 0:
      print(leading + '{}>>  Commands 💻:{}'.format(COLORS.OKGREEN, COLORS.ENDC))
      for cmd in commands:
        cmds_to_print.append(leading + COLORS.FAIL + '  - {}: {}'.format(cmd, success(commands[cmd].description, ret=True)) + COLORS.ENDC)
      print('\n'.join(cmds_to_print))
    return has_extra_info
Ejemplo n.º 9
0
 def __reboot():
     check_output('am start -a android.intent.action.REBOOT')
     success('👋 See you in a bit!')
Ejemplo n.º 10
0
    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
Ejemplo n.º 11
0
    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!')
Ejemplo n.º 12
0
 def _settings():
     check_output('am start -a android.settings.SETTINGS')
     success('⚙️ Opened settings!')