def main(args=None):
    """Installs and provides a constant version of Chrome."""
    unused_parsed_args = _PARSER.parse_args(args=args)
    home_directory = os.environ.get('HOME')
    oppia_dir = os.getcwd()

    # CHROME_SOURCE_URL is an environment variable set in Oppia's Travis repo
    # settings. It can be found under 'Environment Variables' header here:
    # https://travis-ci.org/oppia/oppia/settings.
    chrome_source_url = os.environ.get('CHROME_SOURCE_URL')
    travis_chrome_path = os.path.join(home_directory, '.cache/TravisChrome/',
                                      os.path.basename(chrome_source_url))

    # Caching Chrome's Debian package after download to prevent connection
    # problem.
    if not os.path.isdir(os.path.join(home_directory, '.cache/TravisChrome/')):
        os.makedirs(os.path.join(home_directory, '.cache/TravisChrome/'))

    if not os.path.isfile(travis_chrome_path):
        os.chdir(os.path.join(home_directory, '.cache/TravisChrome/'))
        python_utils.url_retrieve(chrome_source_url,
                                  filename=os.path.basename(chrome_source_url))
        os.chdir(oppia_dir)

    python_utils.PRINT('Installing %s' % travis_chrome_path)
    subprocess.check_call(['sudo', 'dpkg', '-i', travis_chrome_path])
Example #2
0
def download_and_untar_files(source_url, target_parent_dir, tar_root_name,
                             target_root_name):
    """Downloads a tar file, untars it, and saves the result in a given dir.

    The download occurs only if the target directory that the tar file untars
    to does not exist.

    NB: This function assumes that the root level of the tar file has exactly
    one folder.

    Args:
        source_url: str. The URL from which to download the tar file.
        target_parent_dir: str. The directory to save the contents of the tar
            file to.
        tar_root_name: str. The name of the top-level folder in the tar
            directory.
        target_root_name: str. The name that the top-level folder should be
            renamed to in the local directory.
    """
    if not os.path.exists(os.path.join(target_parent_dir, target_root_name)):
        python_utils.PRINT('Downloading and untarring file %s to %s ...' %
                           (tar_root_name, target_parent_dir))
        common.ensure_directory_exists(target_parent_dir)

        python_utils.url_retrieve(source_url, filename=TMP_UNZIP_PATH)
        with contextlib.closing(tarfile.open(name=TMP_UNZIP_PATH,
                                             mode='r:gz')) as tfile:
            tfile.extractall(target_parent_dir)
        os.remove(TMP_UNZIP_PATH)

        # Rename the target directory.
        os.rename(os.path.join(target_parent_dir, tar_root_name),
                  os.path.join(target_parent_dir, target_root_name))

        python_utils.PRINT('Download of %s succeeded.' % tar_root_name)
Example #3
0
def download_files(source_url_root, target_dir, source_filenames):
    """Downloads a group of files and saves them to a given directory.

    Each file is downloaded only if it does not already exist.

    Args:
        source_url_root: str. The URL to prepend to all the filenames.
        target_dir: str. The directory to save the files to.
        source_filenames: list(str). Each filename is appended to the
            end of the source_url_root in order to give the URL from which to
            download the file. The downloaded file is then placed in target_dir,
            and retains the same filename.
    """
    assert isinstance(source_filenames, list), (
        'Expected list of filenames, got \'%s\'' % source_filenames)
    common.ensure_directory_exists(target_dir)
    for filename in source_filenames:
        if not os.path.exists(os.path.join(target_dir, filename)):
            python_utils.PRINT(
                'Downloading file %s to %s ...' % (filename, target_dir))
            python_utils.url_retrieve(
                '%s/%s' % (source_url_root, filename),
                filename=os.path.join(target_dir, filename))

            python_utils.PRINT('Download of %s succeeded.' % filename)
Example #4
0
def install_buf_and_protoc():
    """Installs buf and protoc for Linux or Darwin, depending upon the
    platform.
    """
    buf_files = BUF_DARWIN_FILES if common.is_mac_os() else BUF_LINUX_FILES
    protoc_file = (PROTOC_DARWIN_FILE
                   if common.is_mac_os() else PROTOC_LINUX_FILE)
    buf_path = os.path.join(BUF_DIR, buf_files[0])
    protoc_path = os.path.join(PROTOC_DIR, 'bin', 'protoc')

    if os.path.isfile(buf_path) and os.path.isfile(protoc_path):
        return

    common.ensure_directory_exists(BUF_DIR)
    for bin_file in buf_files:
        python_utils.url_retrieve('%s/%s' % (BUF_BASE_URL, bin_file),
                                  filename=os.path.join(BUF_DIR, bin_file))
    python_utils.url_retrieve('%s/%s' % (PROTOC_URL, protoc_file),
                              filename=os.path.join(BUF_DIR, protoc_file))
    try:
        with zipfile.ZipFile(os.path.join(BUF_DIR, protoc_file), 'r') as zfile:
            zfile.extractall(path=PROTOC_DIR)
        os.remove(os.path.join(BUF_DIR, protoc_file))
    except Exception:
        raise Exception('Error installing protoc binary')
    common.recursive_chmod(buf_path, 0o744)
    common.recursive_chmod(protoc_path, 0o744)
Example #5
0
def main(args=None):
    """Runs the script to setup GAE."""
    unused_parsed_args = _PARSER.parse_args(args=args)
    coverage_home = os.path.join(common.OPPIA_TOOLS_DIR,
                                 'coverage-%s' % common.COVERAGE_VERSION)

    # Note that if the following line is changed so that it uses webob_1_1_1,
    # PUT requests from the frontend fail.
    sys.path.append('.')
    sys.path.append(coverage_home)
    sys.path.append(common.GOOGLE_APP_ENGINE_SDK_HOME)
    sys.path.append(
        os.path.join(common.GOOGLE_APP_ENGINE_SDK_HOME, 'lib', 'webob_0_9'))
    sys.path.append(os.path.join(common.OPPIA_TOOLS_DIR, 'webtest-2.0.33'))

    # Delete old *.pyc files.
    for directory, _, files in os.walk('.'):
        for file_name in files:
            if file_name.endswith('.pyc'):
                filepath = os.path.join(directory, file_name)
                os.remove(filepath)

    python_utils.PRINT('Checking whether google-cloud-sdk is installed in %s' %
                       common.GOOGLE_CLOUD_SDK_HOME)
    if not os.path.exists(common.GOOGLE_CLOUD_SDK_HOME):
        python_utils.PRINT(
            'Downloading Google Cloud SDK (this may take a little while)...')
        os.makedirs(common.GOOGLE_CLOUD_SDK_HOME)
        try:
            python_utils.url_retrieve(
                'https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/'
                'google-cloud-sdk-304.0.0-linux-x86_64.tar.gz',
                filename='gcloud-sdk.tar.gz')
        except Exception:
            python_utils.PRINT('Error downloading Google Cloud SDK. Exiting.')
            raise Exception('Error downloading Google Cloud SDK.')
        python_utils.PRINT('Download complete. Installing Google Cloud SDK...')
        tar = tarfile.open(name='gcloud-sdk.tar.gz')
        tar.extractall(path=os.path.join(common.OPPIA_TOOLS_DIR,
                                         'google-cloud-sdk-304.0.0/'))
        tar.close()

        # This command installs specific google cloud components for the google
        # cloud sdk to prevent the need for developers to install it themselves
        # when the app engine development server starts up. The --quiet
        # parameter specifically tells the gcloud program to autofill all
        # prompts with default values. In this case, that means accepting all
        # installations of gcloud packages.
        subprocess.call([
            common.GCLOUD_PATH, 'components', 'install',
            'cloud-datastore-emulator', 'app-engine-python',
            'app-engine-python-extras', '--quiet'
        ])

        os.remove('gcloud-sdk.tar.gz')
Example #6
0
    def test_url_retrieve(self):
        tmp_file = tempfile.NamedTemporaryFile()
        tmp_file.name = 'temp_file.txt'
        python_utils.url_retrieve('http://www.google.com',
                                  filename='temp_file.txt')

        with python_utils.open_file('temp_file.txt', 'rb', encoding=None) as f:
            content = f.read()

        self.assertIn(b'<title>Google</title>', content)
        tmp_file.close()
Example #7
0
def install_prototool():
    """Installs prototool for Linux or Darwin, depending upon the platform."""
    if os.path.exists(PROTOTOOL_BIN_PATH):
        return

    prototool_url = PROTOTOOL_LINUX_BIN_URL
    if common.is_mac_os():
        prototool_url = PROTOTOOL_DARWIN_BIN_URL

    common.ensure_directory_exists(PROTOTOOL_DIR)
    python_utils.url_retrieve(prototool_url, filename=PROTOTOOL_BIN_PATH)
    common.recursive_chmod(PROTOTOOL_BIN_PATH, 0o744)
Example #8
0
def download_and_install_package(url_to_retrieve, filename):
    """Downloads and installs package in Oppia tools directory.

    Args:
        url_to_retrieve: string. The url from which package is to be
            downloaded.
        filename: string. The name of the tar file.
    """
    python_utils.url_retrieve(url_to_retrieve, filename=filename)
    tar = tarfile.open(name=filename)
    tar.extractall(path=common.OPPIA_TOOLS_DIR)
    tar.close()
    os.remove(filename)
Example #9
0
def main(args=None):
    """Runs the script to setup GAE."""
    unused_parsed_args = _PARSER.parse_args(args=args)

    sys.path.append('.')
    sys.path.append(common.GOOGLE_APP_ENGINE_SDK_HOME)
    sys.path.append(os.path.join(common.OPPIA_TOOLS_DIR, 'webtest-2.0.35'))

    # Delete old *.pyc files.
    for directory, _, files in os.walk('.'):
        for file_name in files:
            if file_name.endswith('.pyc'):
                filepath = os.path.join(directory, file_name)
                os.remove(filepath)

    python_utils.PRINT('Checking whether google-cloud-sdk is installed in %s' %
                       common.GOOGLE_CLOUD_SDK_HOME)
    if not os.path.exists(common.GOOGLE_CLOUD_SDK_HOME):
        python_utils.PRINT(
            'Downloading Google Cloud SDK (this may take a little while)...')
        os.makedirs(common.GOOGLE_CLOUD_SDK_HOME)
        try:
            # If the google cloud version is updated here, the corresponding
            # lines (GAE_DIR and GCLOUD_PATH) in release_constants.json should
            # also be updated.
            python_utils.url_retrieve(
                'https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/'
                'google-cloud-sdk-335.0.0-linux-x86_64.tar.gz',
                filename='gcloud-sdk.tar.gz')
        except Exception:
            python_utils.PRINT('Error downloading Google Cloud SDK. Exiting.')
            raise Exception('Error downloading Google Cloud SDK.')
        python_utils.PRINT('Download complete. Installing Google Cloud SDK...')
        tar = tarfile.open(name='gcloud-sdk.tar.gz')
        tar.extractall(path=os.path.join(common.OPPIA_TOOLS_DIR,
                                         'google-cloud-sdk-335.0.0/'))
        tar.close()

        os.remove('gcloud-sdk.tar.gz')

    # This command installs specific google cloud components for the google
    # cloud sdk to prevent the need for developers to install it themselves when
    # the app engine development server starts up. The --quiet parameter
    # specifically tells the gcloud program to autofill all prompts with default
    # values. In this case, that means accepting all installations of gcloud
    # packages.
    subprocess.call([
        common.GCLOUD_PATH, 'components', 'install', 'beta',
        'cloud-datastore-emulator', 'app-engine-python',
        'app-engine-python-extras', '--quiet'
    ])
Example #10
0
def download_and_unzip_files(
        source_url, target_parent_dir, zip_root_name, target_root_name):
    """Downloads a zip file, unzips it, and saves the result in a given dir.

    The download occurs only if the target directory that the zip file unzips
    to does not exist.

    NB: This function assumes that the root level of the zip file has exactly
    one folder.

    Args:
        source_url: str. The URL from which to download the zip file.
        target_parent_dir: str. The directory to save the contents of the zip
            file to.
        zip_root_name: str. The name of the top-level folder in the zip
            directory.
        target_root_name: str. The name that the top-level folder should be
            renamed to in the local directory.
    """
    if not os.path.exists(os.path.join(target_parent_dir, target_root_name)):
        python_utils.PRINT('Downloading and unzipping file %s to %s ...' % (
            zip_root_name, target_parent_dir))
        common.ensure_directory_exists(target_parent_dir)

        python_utils.url_retrieve(source_url, filename=TMP_UNZIP_PATH)

        try:
            with zipfile.ZipFile(TMP_UNZIP_PATH, 'r') as zfile:
                zfile.extractall(path=target_parent_dir)
            os.remove(TMP_UNZIP_PATH)
        except Exception:
            if os.path.exists(TMP_UNZIP_PATH):
                os.remove(TMP_UNZIP_PATH)

            # Some downloads (like jqueryui-themes) may require a user-agent.
            req = python_utils.url_request(source_url, None, {})
            req.add_header('User-agent', 'python')
            # This is needed to get a seekable filestream that can be used
            # by zipfile.ZipFile.
            file_stream = python_utils.string_io(
                buffer_value=python_utils.url_open(req).read())
            with zipfile.ZipFile(file_stream, 'r') as zfile:
                zfile.extractall(path=target_parent_dir)

        # Rename the target directory.
        os.rename(
            os.path.join(target_parent_dir, zip_root_name),
            os.path.join(target_parent_dir, target_root_name))

        python_utils.PRINT('Download of %s succeeded.' % zip_root_name)
Example #11
0
def download_and_install_package(url_to_retrieve, filename):
    """Downloads and installs package in Oppia tools directory.

    Args:
        url_to_retrieve: string. The url from which package is to be
            downloaded.
        filename: string. The name of the tar file.
    """
    python_utils.url_retrieve(url_to_retrieve, filename=filename)
    _, extension = os.path.splitext(filename)
    if extension == '.gz' or extension == '.tgz':
        tar = tarfile.open(name=filename)
        tar.extractall(path=common.OPPIA_TOOLS_DIR)
        tar.close()
    elif common.OS_NAME == 'Windows' and extension == '.zip':
        p = subprocess.Popen(
            ['powershell', 'Expand-Archive', filename, common.OPPIA_TOOLS_DIR],
            stdout=sys.stdout)
        p.communicate()

    os.remove(filename)
Example #12
0
def download_and_install_node():
    """Download and install node to Oppia tools directory."""
    outfile_name = 'node-download'

    if common.is_windows_os():
        if common.is_x64_architecture():
            architecture = 'x64'
        else:
            architecture = 'x86'

        extension = '.zip'
        node_file_name = 'node-v%s-win-%s' % (
            common.NODE_VERSION, architecture)
        url_to_retrieve = 'https://nodejs.org/dist/v%s/%s%s' % (
            common.NODE_VERSION, node_file_name, extension)
        python_utils.url_retrieve(url_to_retrieve, outfile_name)
        subprocess.check_call(
            ['powershell.exe', '-c', 'expand-archive',
             outfile_name, '-DestinationPath',
             common.OPPIA_TOOLS_DIR])
    else:
        extension = '.tar.gz'
        if common.is_x64_architecture():
            if common.is_mac_os():
                node_file_name = 'node-v%s-darwin-x64' % (common.NODE_VERSION)
            elif common.is_linux_os():
                node_file_name = 'node-v%s-linux-x64' % (common.NODE_VERSION)
        else:
            node_file_name = 'node-v%s' % common.NODE_VERSION
        download_and_install_package(
            'https://nodejs.org/dist/v%s/%s%s' % (
                common.NODE_VERSION, node_file_name, extension),
            outfile_name)
    os.rename(
        os.path.join(common.OPPIA_TOOLS_DIR, node_file_name),
        common.NODE_PATH)
    if node_file_name == 'node-v%s' % common.NODE_VERSION:
        with common.CD(common.NODE_PATH):
            subprocess.check_call(['./configure'])
            subprocess.check_call(['make'])
Example #13
0
def main(args=None):
    """Runs the script to setup GAE."""
    unused_parsed_args = _PARSER.parse_args(args=args)
    coverage_home = os.path.join(common.OPPIA_TOOLS_DIR, 'coverage-4.5.4')

    # Note that if the following line is changed so that it uses webob_1_1_1,
    # PUT requests from the frontend fail.
    sys.path.append('.')
    sys.path.append(coverage_home)
    sys.path.append(common.GOOGLE_APP_ENGINE_HOME)
    sys.path.append(
        os.path.join(common.GOOGLE_APP_ENGINE_HOME, 'lib', 'webob_0_9'))
    sys.path.append(os.path.join(common.OPPIA_TOOLS_DIR, 'webtest-2.0.33'))

    # Delete old *.pyc files.
    for directory, _, files in os.walk('.'):
        for file_name in files:
            if file_name.endswith('.pyc'):
                filepath = os.path.join(directory, file_name)
                os.remove(filepath)

    python_utils.PRINT(
        'Checking whether Google App Engine is installed in %s'
        % common.GOOGLE_APP_ENGINE_HOME)
    if not os.path.exists(common.GOOGLE_APP_ENGINE_HOME):
        python_utils.PRINT(
            'Downloading Google App Engine (this may take a little while)...')
        os.makedirs(common.GOOGLE_APP_ENGINE_HOME)
        try:
            python_utils.url_retrieve(
                'https://storage.googleapis.com/appengine-sdks/featured/'
                'google_appengine_1.9.67.zip', filename='gae-download.zip')
        except Exception:
            python_utils.PRINT('Error downloading Google App Engine. Exiting.')
            raise Exception
        python_utils.PRINT('Download complete. Installing Google App Engine...')
        with zipfile.ZipFile(GAE_DOWNLOAD_ZIP_PATH, 'r') as zip_ref:
            zip_ref.extractall(
                path=os.path.join(
                    common.OPPIA_TOOLS_DIR, 'google_appengine_1.9.67/'))
        os.remove(GAE_DOWNLOAD_ZIP_PATH)


    python_utils.PRINT(
        'Checking whether google-cloud-sdk is installed in %s'
        % common.GOOGLE_CLOUD_SDK_HOME)
    if not os.path.exists(common.GOOGLE_CLOUD_SDK_HOME):
        python_utils.PRINT(
            'Downloading Google Cloud SDK (this may take a little while)...')
        os.makedirs(common.GOOGLE_CLOUD_SDK_HOME)
        try:
            python_utils.url_retrieve(
                'https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/'
                'google-cloud-sdk-251.0.0-linux-x86_64.tar.gz',
                filename='gcloud-sdk.tar.gz')
        except Exception:
            python_utils.PRINT('Error downloading Google Cloud SDK. Exiting.')
            raise Exception
        python_utils.PRINT('Download complete. Installing Google Cloud SDK...')
        tar = tarfile.open(name='gcloud-sdk.tar.gz')
        tar.extractall(
            path=os.path.join(
                common.OPPIA_TOOLS_DIR, 'google-cloud-sdk-251.0.0/'))
        tar.close()
        os.remove('gcloud-sdk.tar.gz')
Example #14
0
def main(args=None):
    """Runs the script to setup Oppia."""
    unused_parsed_args = _PARSER.parse_args(args=args)
    test_python_version()

    # The second option allows this script to also be run from deployment
    # folders.
    if not os.getcwd().endswith('oppia') and not os.getcwd().endswith(
            'deploy-'):
        python_utils.PRINT('')
        python_utils.PRINT(
            'WARNING   This script should be run from the oppia/ root folder.')
        python_utils.PRINT('')
        raise Exception

    # Set COMMON_DIR to the absolute path of the directory above OPPIA_DIR. This
    # is necessary becaue COMMON_DIR (or subsequent variables which refer to it)
    # may use it in a situation where relative paths won't work as expected(such
    # as $PYTHONPATH).
    create_directory(common.OPPIA_TOOLS_DIR)
    create_directory(common.THIRD_PARTY_DIR)
    create_directory(common.NODE_MODULES_PATH)

    os_info = os.uname()
    if os_info[0] != 'Darwin' and os_info[0] != 'Linux':
        # Node is a requirement for all installation scripts. Here, we check if
        # the OS supports node.js installation; if not, we exit with an error.
        common.print_each_string_after_two_new_lines([
            'WARNING: Unsupported OS for installation of node.js.',
            'If you are running this script on Windows, see the instructions',
            'here regarding installation of node.js:',
            'https://github.com/oppia/oppia/wiki/Installing-Oppia-%28Windows'
            '%29',
            'STATUS: Installation completed except for node.js. Exiting.'
        ])
        raise Exception

    # Download and install node.js.
    python_utils.PRINT('Checking if node.js is installed in %s' %
                       common.OPPIA_TOOLS_DIR)
    if not os.path.exists(common.NODE_PATH):
        python_utils.PRINT('Installing Node.js')
        if os_info[0] == 'Darwin':
            if os_info[4] == 'x86_64':
                node_file_name = 'node-v10.15.3-darwin-x64'
            else:
                node_file_name = 'node-v10.15.3-darwin-x86'
        elif os_info[0] == 'Linux':
            if os_info[4] == 'x86_64':
                node_file_name = 'node-v10.15.3-linux-x64'
            else:
                node_file_name = 'node-v10.15.3-linux-x86'

        python_utils.url_retrieve(
            'https://nodejs.org/dist/v10.15.3/%s.tar.gz' % node_file_name,
            filename='node-download.tgz')
        tar = tarfile.open(name='node-download.tgz')
        tar.extractall(path=common.OPPIA_TOOLS_DIR)
        tar.close()
        os.remove('node-download.tgz')
        os.rename(os.path.join(common.OPPIA_TOOLS_DIR, node_file_name),
                  common.NODE_PATH)

    # Change ownership of node_modules.
    # Note: on some machines, these commands seem to take quite a long time.
    common.recursive_chown(common.NODE_MODULES_PATH, os.getuid(), -1)
    common.recursive_chmod(common.NODE_MODULES_PATH, 0o744)

    # Download and install yarn.
    python_utils.PRINT('Checking if yarn is installed in %s' %
                       common.OPPIA_TOOLS_DIR)
    if not os.path.exists(common.YARN_PATH):
        python_utils.PRINT('Removing package-lock.json')
        clean.delete_file('package-lock.json')
        common.print_each_string_after_two_new_lines([
            'Installing yarn',
            'WARNING: Please note that Oppia uses Yarn to manage node packages',
            'do *NOT* use npm. For more information on how to use yarn,',
            'visit https://yarnpkg.com/en/docs/usage.'
        ])

        # NB: Update .yarnrc if the yarn version below is changed.
        yarn_version = 'v1.17.3'
        yarn_file_name = 'yarn-%s.tar.gz' % yarn_version
        python_utils.url_retrieve(
            'https://github.com/yarnpkg/yarn/releases/download/%s/%s' %
            (yarn_version, yarn_file_name),
            filename=yarn_file_name)
        tar = tarfile.open(name=yarn_file_name)
        tar.extractall(path=common.OPPIA_TOOLS_DIR)
        tar.close()
        os.remove(yarn_file_name)

    # Adjust path to support the default Chrome locations for Unix, Windows and
    # Mac OS.
    if os.environ.get('TRAVIS'):
        chrome_bin = '/usr/bin/chromium-browser'
    elif os.path.isfile('/usr/bin/google-chrome'):
        # Unix.
        chrome_bin = '/usr/bin/google-chrome'
    elif os.path.isfile('/usr/bin/chromium-browser'):
        # Unix.
        chrome_bin = '/usr/bin/chromium-browser'
    elif os.path.isfile(
            '/c/Program Files (x86)/Google/Chrome/Application/chrome.exe'):
        # Windows.
        chrome_bin = (
            '/c/Program Files (x86)/Google/Chrome/Application/chrome.exe')
    elif os.path.isfile(
            '/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe'):
        # WSL.
        chrome_bin = (
            '/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe')
    elif os.path.isfile(
            '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'):
        # Mac OS.
        chrome_bin = (
            '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome')
    else:
        python_utils.PRINT('Chrome is not found, stopping ...')
        raise Exception

    os.environ['CHROME_BIN'] = chrome_bin
    python_utils.PRINT('Environment setup completed.')