Beispiel #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)))
Beispiel #2
0
def gc_dists(args):
    """ Garbage collect mx distributions."""

    parser = argparse.ArgumentParser(prog='mx gc-dists', description='''Garbage collect layout distributions.
        By default, it collects all found layout distributions that are *not* part of the current configuration (see `--keep-current`).
        This command respects mx level suite filtering (e.g., `mx --suite my-suite gc-dists`).
        ''', epilog='''If the environment variable `MX_GC_AFTER_BUILD` is set, %(prog)s will be executed after `mx build`
        using the content of the environment variable as parameters.''')
    # mutually exclusive groups do not support title and description - wrapping in another group as a workaround
    action_group_desc = parser.add_argument_group('actions', 'What to do with the result. One of the following arguments is required.')
    action_group = action_group_desc.add_mutually_exclusive_group(required=True)
    action_group.add_argument('-f', '--force', action='store_true', help='remove layout distributions without further questions')
    action_group.add_argument('-n', '--dry-run', action='store_true', help='show what would be removed without actually doing anything')
    action_group.add_argument('-i', '--interactive', action='store_true', help='ask for every layout distributions whether it should be removed')
    keep_current_group_desc = parser.add_argument_group('current configuration handling', description='How to deal with the current configuration, i.e., what `mx build` would rebuild.')
    keep_current_group = keep_current_group_desc.add_mutually_exclusive_group()
    keep_current_group.add_argument('--keep-current', action='store_true', default=True, help='keep layout distributions of the current configuration (default)')
    keep_current_group.add_argument('--no-keep-current', action='store_false', dest='keep_current', help='remove layout distributions of the current configuration')
    filter_group = parser.add_argument_group('result filters', description='Filter can be combined.')
    filter_group.add_argument('--reverse', action='store_true', help='reverse the result')
    filter_group.add_argument('--older-than', action=TimeAction, help='only show results older than the specified point in time (format: {})'.format(TimeAction.fmt.replace('%', '%%')))
    try:
        parsed_args = parser.parse_args(args)
    except ValueError as ve:
        parser.error(str(ve))
    suites = mx.suites(opt_limit_to_suite=True, includeBinary=False, include_mx=False)
    c = []

    for s in suites:
        c += _gc_layout_dists(s, parsed_args)

    if not c:
        mx.log("Nothing to do!")
        return

    if parsed_args.older_than:
        c = [x for x in c if x[1] < parsed_args.older_than]
    # sort by mod date
    c = sorted(c, key=lambda x: x[1], reverse=parsed_args.reverse)

    # calculate max sizes
    max_path = 0
    max_mod_time = 0
    max_size = 0
    for path, mod_time, size in c:
        max_path = max(len(path), max_path)
        max_mod_time = max(len(_format_datetime(mod_time)), max_mod_time)
        max_size = max(len(_format_bytes(size)), max_size)

    msg_fmt = '{0:<' + str(max_path) + '} modified {1:<' + str(max_mod_time + len(' ago')) +'}  {2:<' + str(max_size) + '}'

    size_sum = 0
    for path, mod_time, size in c:
        if parsed_args.dry_run:
            mx.log(msg_fmt.format(path, _format_datetime(mod_time) + ' ago', _format_bytes(size)))
            size_sum += size
        else:
            msg = '{0}   (modified {1} ago, size {2})'.format(path, _format_datetime(mod_time), _format_bytes(size))
            if parsed_args.force or parsed_args.interactive and mx.ask_yes_no('Delete ' + msg):
                mx.log('rm ' + path)
                mx.rmtree(path)
                size_sum += size

    if parsed_args.dry_run:
        mx.log('Would free ' + _format_bytes(size_sum))
    else:
        mx.log('Freed ' + _format_bytes(size_sum))
Beispiel #3
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
Beispiel #4
0
def fsckprojects(args):
    """find directories corresponding to deleted Java projects and delete them"""
    for suite in mx.suites(True, includeBinary=False):
        projectDirs = [p.dir for p in suite.projects]
        distIdeDirs = [
            d.get_ide_project_dir() for d in suite.dists
            if d.isJARDistribution() and d.get_ide_project_dir() is not None
        ]
        for dirpath, dirnames, files in os.walk(suite.dir):
            if dirpath == suite.dir:
                # no point in traversing vc metadata dir, lib, .workspace
                # if there are nested source suites must not scan those now, as they are not in projectDirs (but contain .project files)
                omitted = [suite.mxDir, 'lib', '.workspace', 'mx.imports']
                if suite.vc:
                    omitted.append(suite.vc.metadir())
                dirnames[:] = [d for d in dirnames if d not in omitted]
            elif dirpath == suite.get_output_root():
                # don't want to traverse output dir
                dirnames[:] = []
            elif dirpath == suite.mxDir:
                # don't want to traverse mx.name as it contains a .project
                dirnames[:] = []
            elif dirpath in projectDirs:
                # don't traverse subdirs of an existing project in this suite
                dirnames[:] = []
            elif dirpath in distIdeDirs:
                # don't traverse subdirs of an existing distribution in this suite
                dirnames[:] = []
            else:
                maybe_project = basename(dirpath)
                if not mx._removedDeps.get(maybe_project):
                    projectConfigFiles = frozenset([
                        '.classpath', '.project', 'nbproject',
                        maybe_project + '.iml'
                    ])
                    indicators = projectConfigFiles.intersection(files)
                    if len(indicators) != 0:
                        indicators = [
                            os.path.relpath(join(dirpath, i), suite.vc_dir)
                            for i in indicators
                        ]
                        indicatorsInVC = suite.vc.locate(
                            suite.vc_dir, indicators)
                        # Only proceed if there are indicator files that are not under VC
                        if len(indicators) > len(indicatorsInVC):
                            if mx.ask_yes_no(
                                    dirpath +
                                    ' looks like a removed project -- delete it',
                                    'n'):
                                shutil.rmtree(dirpath)
                                mx.log('Deleted ' + dirpath)

        ideaProjectDirectory = join(suite.dir, '.idea')
        librariesDirectory = join(ideaProjectDirectory, 'libraries')
        if librariesDirectory and exists(librariesDirectory):
            neededLibraries = set()
            unique_library_file_names = set()
            for p in suite.projects_recursive(
            ) + mx._mx_suite.projects_recursive():
                if not p.isJavaProject():
                    continue

                def processDep(dep, edge):
                    if dep is p:
                        return
                    if dep.isLibrary() or dep.isJARDistribution(
                    ) or dep.isJdkLibrary() or dep.isMavenProject(
                    ) or dep.isClasspathDependency():
                        neededLibraries.add(dep)

                p.walk_deps(visit=processDep, ignoredEdges=[mx.DEP_EXCLUDED])
            neededLibraryFiles = frozenset([
                mx_ide_intellij._intellij_library_file_name(
                    l.name, unique_library_file_names) for l in neededLibraries
            ])
            existingLibraryFiles = frozenset(os.listdir(librariesDirectory))
            for library_file in existingLibraryFiles - neededLibraryFiles:
                file_path = join(librariesDirectory, library_file)
                relative_file_path = os.path.relpath(file_path, os.curdir)
                if mx.ask_yes_no(
                        relative_file_path +
                        ' looks like a removed library -- delete it', 'n'):
                    os.remove(file_path)
                    mx.log('Deleted ' + relative_file_path)