Example #1
0
def tools():
    if yesno('install_with', 'Install `with` utility?', want_full):
        withutil = InstallFromSource('https://github.com/mchav/with',
                                     '~/src/with.git')
        withutil.symlink('with', '~/bin/with')
        withutil.select_branch('master')
        run(withutil)

    if yesno('install_universal_ctags', 'Install Universal Ctags?', want_full):
        need_installpkg(apt=('autoconf', 'g++'))
        mkdir('~/bin')
        if haveexecutable('brew'):
            # install with homebrew
            execute(['brew', 'tap', 'universal-ctags/universal-ctags'])
            execute(['brew', 'install', '--HEAD', 'universal-ctags'])
        else:
            uc = InstallFromSource('https://github.com/universal-ctags/ctags',
                                   '~/src/universal-ctags.git')
            uc.select_branch('master')
            uc.compile_cmd([
                ['./autogen.sh'],
                ['./configure'],
                ['make'],
            ])
            uc.symlink('ctags', '~/bin/ctags')
            run(uc)
    elif allow_installing_stuff and yesno('install_ctags', 'Install `ctags`?',
                                          want_full):
        installpkg('ctags')
    if allow_installing_stuff and yesno('install_patch', 'Install patch?',
                                        want_full):
        installpkg('patch')

    if allow_installing_stuff and yesno('install_tidy',
                                        'Install tidy cli tool?', want_full):
        installpkg('tidy')

    # on OSX we want to install gnu utils (brew install coreutils findutils)
    # and put /usr/local/opt/coreutils/libexec/gnubin in PATH
    if IS_OSX and haveexecutable('brew') and allow_installing_stuff:
        if yesno('brew_install_coreutils',
                 'Install gnu utils?',
                 default=want_full):
            brew_list = set(
                execute(['brew', 'list'],
                        stdout=True)[1].decode('utf-8').splitlines())
            install = [
                pkg for pkg in ('coreutils', 'findutils')
                if pkg not in brew_list
            ]
            if len(install):
                execute(['brew', 'install'] + install)
Example #2
0
def need_installpkg(*, apt=None, brew=None, yum=None):
    if not allow_installing_stuff:
        what = apt or brew or yum
        raise Exception(
            "Can't install {} when only doing minimal config".format(what))

    if haveexecutable('apt-get'):
        for name in apt or []:
            installpkg(name, brew=False, yum=False, port=False)
    if haveexecutable('brew'):
        for name in brew or []:
            installpkg(name, apt=False, yum=False, port=False)
    if haveexecutable('yum'):
        for name in yum or []:
            installpkg(name, apt=False, brew=False, port=False)
Example #3
0
def getpippaths():
    if IS_OSX:
        return {}

    # do we need to out a pip config such that py2/py3 binaries don't clobber each other?
    question = 'Force pip to install into separate py2/py3 bin dirs?'
    if not yesno('force_pip_bin_paths', question, None):
        return {}

    scripts = {}

    for version in (2, 3):
        # TODO: we probably should drop into vim somewhere and make sure g:my_pyX_paths is
        # defined in prefs.vim or else our stuff is gonna be broken
        # TODO: we also want these in our $PATH ... or not?
        pip = "pip%d" % version
        var = "g:my_py%d_paths" % version

        if not haveexecutable(pip):
            continue

        stdout = execute([pip, '--version'],
                         stdout=True)[1].decode('utf-8').rstrip()
        assert re.search(r' \(python \d+\.\d+\)$', stdout)
        version = stdout.rsplit(' ', 1)[1][:-1]
        path = '%s/.local/python-%s-bin' % (HOME, version)

        scripts[pip] = path
        lineinfile('~/.vimrc',
                   "let %s = ['%s']" % (var, path),
                   where=WHERE_END)

    return scripts
Example #4
0
def brew_install():
    if haveexecutable('brew'):
        return

    if yesno('install_homebrew', 'Install Homebrew?', default=True):
        install_cmd = '/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"'
        execute(['bash', '-c', install_cmd], stdout="TTY")
Example #5
0
def jerjerrod_install():
    # NOTE: only install jerjerrod where we've installed powerline
    install_commands = [
        ['pip3', 'install', '--user', '-e', '.'],
    ]

    if IS_OSX and haveexecutable('/usr/bin/pip3'):
        # XXX: this version of pip3 is too old to understand how to install in
        # ---editable mode with just a pyproject.toml, so we need to just
        # install it as-is
        install_commands.append(
            ['/usr/bin/pip3', 'install', '--user', '.'],
        )

    # install from source!
    inst = InstallFromSource('https://github.com/phodge/jerjerrod.git',
                             '~/src/jerjerrod.git')
    inst.select_branch('master')
    # TODO: if you uninstall jerjerrod, this won't actually reinstalll it :-(
    inst.compile_cmd(install_commands)
    run(inst)

    jerjerrod_addline('PROJECT', '~/src/*.git')
    jerjerrod_addline('PROJECT', '~/src/*.hg')
    jerjerrod_addline('PROJECT', HERE)
Example #6
0
def search_tools():
    if yesno('install_ack', 'Install ack?', False):
        installpkg('ack', apt='ack-grep')

    if want_silver_searcher():
        installpkg('ag', yum='the_silver_searcher', apt='silversearcher-ag')

    if yesno('install_ripgrep', 'Install ripgrep?', True):
        yum = False
        if haveexecutable('yum') and install_fedora_copr():
            yum = 'ripgrep'
        installpkg('ripgrep', yum=yum)
Example #7
0
def install_fedora_copr():
    if not allow_installing_stuff:
        return False

    if not haveexecutable('yum'):
        return False

    copr_url = 'https://copr.fedorainfracloud.org/coprs/carlwgeorge/ripgrep/repo/epel-7/carlwgeorge-ripgrep-epel-7.repo'
    if not yesno('allow_fedora_copr', 'Add fedora COPR repo on this host?',
                 None):
        return False

    # enable the repo
    installpkg('yum-utils')
    execute(['sudo', 'yum-config-manager', '--add-repo=' + copr_url],
            stdout="TTY")
    return True
Example #8
0
def fzf_install():
    if not yesno('install_fzf', 'Install fzf?', want_full):
        return

    if haveexecutable('brew') and allow_installing_stuff:
        installpkg('fzf')
        brewpath = execute(['brew', '--prefix'],
                           stdout=True)[1].decode('utf-8').strip()
        if brewpath == '/opt/homebrew':
            # brew puts the fzf files into versioned folders, so all we can do
            # is glob and sort (which isn't perfect because it would need to be
            # a semver-compatible sort) and pick the first one
            fzf_path = execute(
                [
                    'bash', '-c',
                    f'echo {brewpath}/Cellar/fzf/* | sort -r | head -n 1'
                ],
                stdout=True,
            )[1].decode('utf-8').strip()
        else:
            # this is how it was on my old mac
            fzf_path = brewpath + '/opt/fzf'
    else:
        # do it the long way
        import os.path
        fzf_repo = os.path.expanduser('~/src/fzf.git')
        fzf_install = InstallFromSource('https://github.com/junegunn/fzf.git',
                                        fzf_repo)
        fzf_install.select_tag('0.17.3')
        fzf_install.compile_cmd([
            ['./install', '--bin'],
        ])
        fzf_install.symlink('bin/fzf', '~/bin/fzf')
        run(fzf_install)
        execute(['./install', '--bin'], cwd=fzf_repo, stdout='TTY')
        fzf_path = fzf_repo

    lineinfile('~/.bashrc', 'source {}/shell/completion.bash'.format(fzf_path))
    lineinfile('~/.bashrc',
               'source {}/shell/key-bindings.bash'.format(fzf_path))
    if wantzsh():
        lineinfile('~/.zshrc',
                   'source {}/shell/completion.zsh'.format(fzf_path))
        lineinfile('~/.zshrc',
                   'source {}/shell/key-bindings.zsh'.format(fzf_path))
Example #9
0
def mypips(venv_pip=None, write_dev_reqs=False):
    # if we're on macos then we need to tell homely.pipinstall to use 'pip3' instead of 'pip'
    if IS_OSX:
        pips = ['pip3']
    else:
        pips = None

    # of course we probably want virtualenv!
    if venv_pip is None:
        pipinstall('virtualenv', pips=pips)

    theworks = want_full or venv_pip

    # these packages will be installed using the virtualenv's pip, or pip2+pip3 depending on what's
    # present. They're needed for development.
    packages = [
        'jedi',
        'yapf',
        'isort',
        # needed for `git rebase -i` commit comparisons
        'GitPython',
    ]

    if wantnvim() and not install_nvim_via_apt():
        # if we want nvim then we probably need the pynvim package
        packages.append('pynvim')

    # a nice python repl
    if theworks or yesno('install_ptpython', 'PIP Install ptpython?', True):
        packages.append('ptpython')

    # another nice python repl
    if theworks or yesno('install_ipython', 'PIP Install iPython?', True):
        packages.append('ipython')

    # a few of my macros use `q` for logging
    if theworks or yesno('install_python_q', 'PIP Install `q`?', True):
        packages.append('q')

    if write_dev_reqs:
        assert venv_pip is None
        mkdir('~/.config')

        with writefile('~/.config/dev_requirements.txt') as f:
            f.write('flake8\n')
            for p in packages:
                f.write(p + '\n')

    if want_python2_anything:
        trypips = ['pip2', 'pip3']
    else:
        trypips = ['pip3']

    for package in packages:
        if venv_pip:
            venv_exec(venv_pip, ['pip', 'install', package])
        else:
            mypipinstall(package, trypips=trypips)

    # if it's a virtualenv, always just install flake8. Otherwise, we need to ask the user if
    # they want to install both
    if venv_pip:
        venv_exec(venv_pip, ['pip', 'install', 'flake8'])
    else:
        # always install simplejson globally as we need it for other parts of our homely install
        mypipinstall('simplejson', trypips=trypips)

        have_pip3 = haveexecutable('pip3')
        if have_pip3 and yesno('install_flake8_python3',
                               'Install flake8 for python3?'):
            mypipinstall('flake8', ['pip3'])
        if want_python2_anything and yesno('install_flake8_python2',
                                           'Install flake8 for python2?'):
            mypipinstall('flake8', ['pip2'])
Example #10
0
def install_python2_pip():
    import subprocess
    if not haveexecutable('pip2'):
        if yesno('global_pip2', 'Install pip2 systemwide?', None):
            cmd = 'curl https://bootstrap.pypa.io/get-pip.py | sudo python2'
            subprocess.check_call(cmd, shell=True)
Example #11
0
def install_winwin_shortcuts():
    if not IS_OSX:
        # FIXME: get this working under Ubuntu as well
        return

    q = 'Install macOS system terminal shortcuts (requires Alacritty)?'
    if not yesno('want_winwin_shortcuts', q):
        return

    # we need to install winwin package or the launcher won't be able to find
    # the libs
    execute(['pip3', 'install', '--user', '-e', '.'], cwd=HERE + '/winwin.git')

    # XXX: for some reason on later versions of macOS I had to also install
    # winwin into this python/pip as well as this was the only one available to
    # the automation tool
    if IS_OSX and haveexecutable('/usr/bin/pip3'):
        execute(['/usr/bin/pip3', 'install', '--user', '-e', '.'],
                cwd=HERE + '/winwin.git')

    import shutil
    from tempfile import TemporaryDirectory

    def _replace_wildcards_recursive(target, name, command):
        # skip symlinks
        if os.path.islink(target):
            return

        # perform wildcard replacement in ordinary files
        if os.path.isfile(target):
            if target.endswith('.template'):
                dest = target[:-9]
                with open(target, 'rb') as fp_read, open(dest,
                                                         'xb') as fp_dest:
                    contents = fp_read.read()
                    contents = contents.replace(b'[[[WORKFLOW_NAME]]]',
                                                name.encode('utf-8'))
                    contents = contents.replace(b'[[[WORKFLOW_COMMAND]]]',
                                                command.encode('utf-8'))
                    fp_dest.write(contents)
                os.unlink(target)
                print("Wrote wildcards to {}".format(dest))
            return

        for child in os.listdir(target):
            if child.startswith('.'):
                continue

            _replace_wildcards_recursive(target + '/' + child, name, command)

    def _install_macos_workflow_service(name, command):
        with TemporaryDirectory() as tmpdir:
            tmp_workflow = '{}/{}.workflow'.format(tmpdir, name)
            shutil.copytree(
                '{}/macos_automation/Template.workflow'.format(HERE),
                tmp_workflow)
            _replace_wildcards_recursive(tmp_workflow, name, command)

            # remove existing service
            dest_workflow = '{}/Library/Services/{}.workflow'.format(
                HOME, name)
            if os.path.exists(dest_workflow):
                shutil.rmtree(dest_workflow)
            shutil.copytree(tmp_workflow, dest_workflow)

    todo_launcher_data = {
        'key_equivalent': '@^$t',
        'presentation_modes': {
            'ContextMenu': '1',
            'ServicesMenu': '1',
            'TouchBar': '1'
        },
    }
    todo_launcher_key = '(null) - TODO Launcher QA - runWorkflowAsService'
    _install_macos_workflow_service(
        'TODO Launcher QA',
        # we use '/bin/bash -i ...' here because otherwise the Quick Action
        # will launch in non-interactive mode, causing it to skip ~/.bashrc and
        # so on, and then tmux won't load correctly because $PATH isn't set up,
        # and other Bad Things
        "/bin/bash -i -c '{}/bin/macos-launch-todos'".format(HERE),
    )

    vanilla_launcher_key = '(null) - Terminal Launcher QA - runWorkflowAsService'
    vanilla_launcher_data = {
        'key_equivalent': '@^t',
        'presentation_modes': {
            'ContextMenu': '1',
            'ServicesMenu': '1',
            'TouchBar': '1'
        },
    }
    _install_macos_workflow_service(
        'Terminal Launcher QA',
        '/Applications/Alacritty.app/Contents/MacOS/alacritty',
    )

    _install_macos_workflow_service(
        'Terminal Selector QA',
        '{}/bin/macos-launch-terminal-selector'.format(HERE),
    )

    all_pbs = execute(['defaults', 'read', 'pbs'], stdout=True)[1]
    if b'NSServicesStatus' not in all_pbs:
        print("NSServicesStatus not found")
        return

    import plistlib
    from subprocess import PIPE, Popen

    raw = execute(['defaults', 'read', 'pbs', 'NSServicesStatus'],
                  stdout=True)[1]

    p = Popen(['plutil', '-convert', 'xml1', '-', '-o', '-'],
              stdin=PIPE,
              stdout=PIPE)
    xml, stderr = p.communicate(raw, timeout=5.0)
    assert stderr is None
    assert p.returncode == 0

    # now we can read the xml using plistlib
    data = plistlib.loads(xml)

    needs_writing = False

    for key, value in (
        (todo_launcher_key, todo_launcher_data),
        (vanilla_launcher_key, vanilla_launcher_data),
    ):
        if data[key] != value:
            needs_writing = True
            data[key] = value

    if needs_writing:
        new_xml = plistlib.dumps(data)
        if not allowinteractive():
            return

        print("You need to set keyboard shortcuts.")
        print("Go to:")
        print("  -> System Preferences")
        print("  -> Keyboard")
        print("  -> Shortcuts")
        print("  -> Services")
        print(
            "  -> under 'General' set keyboard shortcuts for 'XXX QA' services"
        )
        yesno(None, "Done?")
        if yesno(None,
                 "Attempt automated install of keyboard shortcuts?",
                 default=False):
            # FIXME: this never worked - the keyboard shortcuts don't seem to
            # activate even if the System Preferences UI does show them there
            execute([
                'defaults', 'write', 'pbs', 'NSServicesStatus',
                new_xml.decode('utf-8')
            ])
Example #12
0
@section_ubuntu(enabled=allow_installing_stuff)
def git_install():
    if not yesno('upgrade_git',
                 'Install latest git from ppa:git-core/ppa?',
                 default=want_full):
        return

    for cmd in [
        ['sudo', 'apt-add-repository', '-y', 'ppa:git-core/ppa'],
        ['sudo', 'apt-get', 'update'],
        ['sudo', 'apt-get', 'install', 'git'],
    ]:
        execute(cmd, stdout="TTY")


@section_macos(enabled=haveexecutable('brew'))
def font_install():
    fonts = [
        'homebrew/cask-fonts/font-inconsolata',
        # this download doesn't seem to work any more
        # 'homebrew/cask-fonts/font-anonymous-pro',
    ]
    if wantpowerline():
        fonts.extend([
            'homebrew/cask-fonts/font-inconsolata-for-powerline',
            # this one seems to require `brew install svn` which I'm maybe not prepared to do
            # 'homebrew/cask-fonts/font-anonymice-powerline',
        ])
    # install some nicer fonts
    execute(['brew', 'install'] + fonts)