Пример #1
0
def fetch_jdk(args):
    """fetches required JDK version

    If mx is not passed the --quiet flag, menu will be printed for available JDK selection.
    """
    args = _parse_fetchsettings(args)

    distribution = args["java-distribution"]
    base_path = args["base-path"]
    artifact = distribution.get_folder_name()
    final_path = distribution.get_final_path(base_path)
    url = mx_urlrewrites.rewriteurl(distribution.get_url())
    sha_url = url + ".sha1"
    archive_name = distribution.get_archive_name()
    archive_target_location = join(base_path, archive_name)

    if not is_quiet():
        if not mx.ask_yes_no("Install {} to {}".format(artifact, final_path),
                             default='y'):
            mx.abort("JDK installation canceled")

    if exists(final_path):
        if args["keep-archive"]:
            mx.warn(
                "The --keep-archive option is ignored when the JDK is already installed."
            )
        mx.log("Requested JDK is already installed at {}".format(final_path))
    else:
        # Try to extract on the same file system as the target to be able to atomically move the result.
        with mx.TempDir(parent_dir=base_path) as temp_dir:
            mx.log("Fetching {} archive from {}...".format(artifact, url))
            archive_location = join(temp_dir, archive_name)
            mx._opts.no_download_progress = is_quiet()
            sha1_hash = mx._hashFromUrl(sha_url).decode('utf-8')

            mx.download_file_with_sha1(artifact,
                                       archive_location, [url],
                                       sha1_hash,
                                       archive_location + '.sha1',
                                       resolve=True,
                                       mustExist=True,
                                       sources=False)
            untar = mx.TarExtractor(archive_location)

            mx.log("Installing {} to {}...".format(artifact, final_path))

            extracted_path = join(temp_dir, 'extracted')
            try:
                untar.extract(extracted_path)
            except:
                mx.rmtree(temp_dir, ignore_errors=True)
                mx.abort("Error parsing archive. Please try again")

            jdk_root_folder = get_extracted_jdk_archive_root_folder(
                extracted_path)
            if args["keep-archive"]:
                atomic_file_move_with_fallback(archive_location,
                                               archive_target_location)
                atomic_file_move_with_fallback(
                    archive_location + '.sha1',
                    archive_target_location + ".sha1")
                mx.log(
                    "Archive is located at {}".format(archive_target_location))

            atomic_file_move_with_fallback(
                join(extracted_path, jdk_root_folder), final_path)

    curr_path = final_path
    if mx.is_darwin() and exists(join(final_path, 'Contents', 'Home')):
        if args["strip-contents-home"]:
            with mx.TempDir(parent_dir=final_path) as tmp_path:
                shutil.move(final_path, tmp_path)
                shutil.move(join(tmp_path, 'Contents', 'Home'), final_path)
        else:
            final_path = join(final_path, 'Contents', 'Home')

    if "alias" in args:
        alias_full_path = join(base_path, args["alias"])
        if exists(alias_full_path):
            mx.rmtree(alias_full_path)
        if not (mx.is_windows() or mx.is_cygwin()):
            os.symlink(abspath(curr_path), alias_full_path)
        else:
            mx.copytree(curr_path, alias_full_path,
                        symlinks=True)  # fallback for windows
        final_path = alias_full_path

    mx.log("Run the following to set JAVA_HOME in your shell:")
    shell = os.environ.get("SHELL")
    if shell is None:
        shell = ''
    print(get_setvar_format(shell) % ("JAVA_HOME", abspath(final_path)))
Пример #2
0
def fetch_jdk(args):
    """
    Installs a JDK based on the coordinates in `args`. See ``mx fetch-jdk --help`` for more info.
    Note that if a JDK already exists at the installation location denoted by `args`, no action is taken.

    :return str: the JAVA_HOME for the JDK at the installation location denoted by `args`
    """
    settings = _parse_args(args)

    jdk_binary = settings["jdk-binary"]
    jdks_dir = settings["jdks-dir"]
    artifact = jdk_binary._folder_name
    final_path = jdk_binary.get_final_path(jdks_dir)
    url = mx_urlrewrites.rewriteurl(jdk_binary._url)
    sha_url = url + ".sha1"
    archive_name = jdk_binary._archive
    archive_target_location = join(jdks_dir, archive_name)

    if not is_quiet():
        if not mx.ask_yes_no("Install {} to {}".format(artifact, final_path),
                             default='y'):
            mx.abort("JDK installation canceled")

    if exists(final_path):
        if settings["keep-archive"]:
            mx.warn(
                "The --keep-archive option is ignored when the JDK is already installed."
            )
        mx.log("Requested JDK is already installed at {}".format(final_path))
    else:
        # Try to extract on the same file system as the target to be able to atomically move the result.
        with mx.TempDir(parent_dir=jdks_dir) as temp_dir:
            mx.log("Fetching {} archive from {}...".format(artifact, url))
            archive_location = join(temp_dir, archive_name)
            mx._opts.no_download_progress = is_quiet()
            try:
                sha1_hash = mx._hashFromUrl(sha_url).decode('utf-8')
            except Exception as e:  #pylint: disable=broad-except
                mx.abort('Error retrieving {}: {}'.format(sha_url, e))

            mx.download_file_with_sha1(artifact,
                                       archive_location, [url],
                                       sha1_hash,
                                       archive_location + '.sha1',
                                       resolve=True,
                                       mustExist=True,
                                       sources=False)
            untar = mx.TarExtractor(archive_location)

            mx.log("Installing {} to {}...".format(artifact, final_path))

            extracted_path = join(temp_dir, 'extracted')
            try:
                untar.extract(extracted_path)
            except:
                mx.rmtree(temp_dir, ignore_errors=True)
                mx.abort("Error parsing archive. Please try again")

            jdk_root_folder = _get_extracted_jdk_archive_root_folder(
                extracted_path)
            if settings["keep-archive"]:
                atomic_file_move_with_fallback(archive_location,
                                               archive_target_location)
                atomic_file_move_with_fallback(
                    archive_location + '.sha1',
                    archive_target_location + ".sha1")
                mx.log(
                    "Archive is located at {}".format(archive_target_location))

            atomic_file_move_with_fallback(
                join(extracted_path, jdk_root_folder), final_path)

    curr_path = final_path
    if exists(join(final_path, 'Contents', 'Home')):
        if settings["strip-contents-home"]:
            with mx.TempDir() as tmp_path:
                tmp_jdk = join(tmp_path, 'jdk')
                shutil.move(final_path, tmp_jdk)
                shutil.move(join(tmp_jdk, 'Contents', 'Home'), final_path)
        else:
            final_path = join(final_path, 'Contents', 'Home')

    alias = settings.get('alias')
    if alias:
        alias_full_path = join(jdks_dir, alias)
        if not exists(alias_full_path) or os.path.realpath(
                alias_full_path) != os.path.realpath(abspath(curr_path)):
            if os.path.islink(alias_full_path):
                os.unlink(alias_full_path)
            elif exists(alias_full_path):
                mx.abort(
                    alias_full_path +
                    ' exists and it is not an existing symlink so it can not be used for a new symlink. Please remove it manually.'
                )

            if mx.can_symlink():
                if isabs(alias):
                    os.symlink(curr_path, alias_full_path)
                else:
                    reldir = os.path.relpath(dirname(curr_path),
                                             dirname(alias_full_path))
                    if reldir == '.':
                        alias_target = basename(curr_path)
                    else:
                        alias_target = join(reldir, basename(curr_path))
                    os.symlink(alias_target, alias_full_path)
            else:
                mx.copytree(curr_path, alias_full_path)
            final_path = alias_full_path

    mx.log("Run the following to set JAVA_HOME in your shell:")
    shell = os.environ.get("SHELL")
    if shell is None:
        shell = ''
    if not settings["strip-contents-home"] and exists(
            join(final_path, 'Contents', 'Home')):
        java_home = join(final_path, 'Contents', 'Home')
    else:
        java_home = final_path
    mx.log(get_setvar_format(shell) % ("JAVA_HOME", abspath(java_home)))
    return final_path
Пример #3
0
def _parse_fetchsettings(args):
    settings = {}
    settings["keep-archive"] = False
    settings["base-path"] = default_base_path()

    common_location = join(_mx_home, 'common.json')

    parser = ArgumentParser(prog='mx fetch-jdk')
    parser.add_argument(
        '--java-distribution',
        action='store',
        help=
        'JDK distribution that should be downloaded (e.g., "labsjdk-ce-11" or "openjdk8")'
    )
    parser.add_argument(
        '--configuration',
        action='store',
        help='location of configuration json file (default: \'{}\')'.format(
            common_location))
    parser.add_argument(
        '--to',
        action='store',
        help='location where JDK would be downloaded (default: \'{}\')'.format(
            settings["base-path"]))
    parser.add_argument('--alias',
                        action='store',
                        help='name of symlink to JDK')
    parser.add_argument('--keep-archive',
                        action='store_true',
                        help='keep downloaded JDK archive')
    if mx.is_darwin():
        parser.add_argument('--strip-contents-home',
                            action='store_true',
                            help='strip Contents/Home')
    parser.add_argument('remainder', nargs=REMAINDER, metavar='...')
    args = parser.parse_args(args)

    if args.to is not None:
        settings["base-path"] = args.to

    if not check_write_access(settings["base-path"]):
        mx.abort(
            "JDK installation directory {} is not writeable.".format(
                settings["base-path"]) + os.linesep +
            "Either re-run with elevated privileges (e.g. sudo) or specify a writeable directory with the --to option."
        )

    if args.configuration is not None:
        common_location = args.configuration
    else:
        if mx.primary_suite() is not None:
            common_location = join(mx.primary_suite().vc_dir,
                                   'common.json')  # Try fetching suite config
        else:
            common_location = join(os.getcwd(),
                                   'common.json')  # Fallback to same folder
            if not exists(common_location):
                common_location = join(_mx_home,
                                       'common.json')  # Fallback to mx
            mx.warn(
                "Selected `{}` as configuration location, since no location is provided"
                .format(common_location))
    if not exists(common_location):
        mx.abort("Configuration file doesn't exist")

    parse_common_json(common_location)

    if args.java_distribution is not None:
        settings["java-distribution"] = JdkDistribution.by_name(
            args.java_distribution)
    else:
        settings["java-distribution"] = JdkDistribution.choose_dist(is_quiet())

    if args.alias is not None:
        settings["alias"] = args.alias

    if args.keep_archive is not None:
        settings["keep-archive"] = args.keep_archive

    if mx.is_darwin() and (args.strip_contents_home is not None):
        settings["strip-contents-home"] = args.strip_contents_home

    return settings
Пример #4
0
def _parse_args(args):
    """
    Defines and parses the command line arguments in `args` for the ``fetch-jdk`` command.

    :return dict: a dictionary configuring the action to be taken by ``fetch-jdk``. The entries are:
                "keep-archive": True if the downloaded archive is to be retained after extraction, False if it is to be deleted
                "jdks-dir": directory in which archive is to be extracted
                "jdk-binary": a _JdkBinary object
                "alias": path of a symlink to create to the extracted JDK
                "strip-contents-home": True if the ``Contents/Home`` should be stripped if it exists from the extracted JDK
    """
    settings = {}
    settings["keep-archive"] = False
    settings["jdks-dir"] = join(mx.dot_mx_dir(), 'jdks')

    # Order in which to look for common.json:
    # 1. Primary suite path (i.e. -p mx option)
    # 2. Current working directory
    # 4. $MX_HOME/common.json
    path_list = PathList()
    if mx._primary_suite_path:
        path_list.add(_find_file(mx._primary_suite_path, 'common.json'))
    path_list.add(_find_file(os.getcwd(), 'common.json'))
    path_list.add(join(_mx_home, 'common.json'))
    default_jdk_versions_location = path_list.paths[0]

    # Order in which to look for jdk-binaries.json:
    # 1. Primary suite path (i.e. -p mx option)
    # 2. Current working directory
    # 4. $MX_HOME/jdk-binaries.json
    path_list = PathList()
    if mx._primary_suite_path:
        path_list.add(_find_file(mx._primary_suite_path, 'jdk-binaries.json'))
    path_list.add(_find_file(os.getcwd(), 'jdk-binaries.json'))
    path_list.add(join(_mx_home, 'jdk-binaries.json'))
    default_jdk_binaries_location = str(path_list)

    parser = ArgumentParser(prog='mx fetch-jdk',
                            usage='%(prog)s [options]' + """
        Download and install JDKs.

        The set of JDKS available for download are specified by the "jdks" field of the JSON
        object loaded by --configuration. The "jdks" field is itself is an object whose field names
        are JDK identifiers and whose field values include a version. For example:

        {
          "jdks": {
            "openjdk8":           {"version": "8u302+02-jvmci-21.2-b02" },
            "labsjdk-ce-11":      {"version": "ce-11.0.11+8-jvmci-21.2-b02" },
          }
        }

        The location of binaries matching these JDK definitions is specified by the "jdk-binaries" field
        of the JSON object loaded by --jdk-binaries (can be the same value as --configuration). For
        example:

        {
          "jdk-binaries": {
            "openjdk8": {
              "filename": "openjdk-{version}-{platform}",
              "url": "https://github.com/graalvm/graal-jvmci-8/releases/download/{version|jvmci}/{filename}.tar.gz"
            },
            "labsjdk-ce-11": {
              "filename": "labsjdk-{version}-{platform}",
              "url": "https://github.com/graalvm/labs-openjdk-11/releases/download/{version|jvmci}/{filename}.tar.gz"
            }
          }
        }

        The "jdk-binaries.<id>" object specifies the URL at which a JDK binary for the "jdks.<id>" object is found.
        The "filename" and "url" attributes of a JDK binary object are template strings with curly braces denoting
        keywords that will be replaced with their values. The supported keywords and their value for a
        "jdk-binaries.<id>" object are:

        version    The value of "jdks.<id>.version".
        platform   The value denoting the operating system and architecture (e.g. "linux-amd64").
        filename   The value of "jdk-binaries.<id>.filename".

        Each keyword value can be processed by a filter by appending "|<filter>" to the keyword selector.
        The supported filters are:

        jvmci      Extracts the first string that looks like a jvmci version (e.g. "8u302+05-jvmci-21.2-b01" -> "21.2-b01").
        jvmci-tag  Extracts the first string that looks like a jvmci tag (e.g. "8u302+05-jvmci-21.2-b01" -> "jvmci-21.2-b01").
    """)

    parser.add_argument(
        '--jdk-id',
        '--java-distribution',
        action='store',
        metavar='<id>',
        help=
        'Identifier of the JDK that should be downloaded (e.g., "labsjdk-ce-11" or "openjdk8")'
    )
    parser.add_argument(
        '--configuration',
        action='store',
        metavar='<path>',
        help='location of JSON file containing JDK definitions (default: {})'.
        format(default_jdk_versions_location))
    parser.add_argument(
        '--jdk-binaries',
        action='store',
        metavar='<path>',
        help=
        '{} separated JSON files specifying location of JDK binaries (default: {})'
        .format(os.pathsep, default_jdk_binaries_location))
    parser.add_argument(
        '--to',
        action='store',
        metavar='<dir>',
        help=
        'location where JDK will be installed. Specify <system> to use the system default location. (default: {})'
        .format(settings["jdks-dir"]))
    parser.add_argument(
        '--alias',
        action='store',
        metavar='<path>',
        help=
        'name under which the extracted JDK should be made available (e.g. via a symlink). A relative path will be resolved against the value of the --to option.'
    )
    parser.add_argument('--keep-archive',
                        action='store_true',
                        help='keep downloaded JDK archive')
    parser.add_argument(
        '--strip-contents-home',
        action='store_true',
        help='strip Contents/Home if it exists from installed JDK')
    args = parser.parse_args(args)

    if args.to is not None:
        if args.to == '<system>':
            args.to = _default_system_jdks_dir()
        settings["jdks-dir"] = args.to

    if not _check_write_access(settings["jdks-dir"]):
        mx.abort(
            "JDK installation directory {} is not writeable.".format(
                settings["jdks-dir"]) + os.linesep +
            "Either re-run with elevated privileges (e.g. sudo) or specify a writeable directory with the --to option."
        )

    jdk_versions_location = _check_exists_or_None(
        args.configuration) or default_jdk_versions_location
    jdk_binaries_locations = (args.jdk_binaries
                              or default_jdk_binaries_location).split(
                                  os.pathsep)

    jdk_versions = _parse_jdk_versions(jdk_versions_location)
    jdk_binaries = _parse_jdk_binaries(jdk_binaries_locations, jdk_versions)

    if args.jdk_id is not None:
        settings["jdk-binary"] = _get_jdk_binary_or_abort(
            jdk_binaries, args.jdk_id)
    else:
        settings["jdk-binary"] = _choose_jdk_binary(jdk_binaries, is_quiet())

    if args.alias is not None:
        settings["alias"] = args.alias

    if args.keep_archive is not None:
        settings["keep-archive"] = args.keep_archive

    settings["strip-contents-home"] = args.strip_contents_home

    return settings