Ejemplo n.º 1
0
def cmd_profile_delete_key(profile_name, key, cache_profiles_path):
    first_key, rest_key = _get_profile_keys(key)
    profile, _ = read_profile(profile_name, get_cwd(), cache_profiles_path)

    try:
        package, name = rest_key.split(":")
    except ValueError:
        package = None
        name = rest_key

    try:
        if first_key == "settings":
            del profile.settings[rest_key]
        elif first_key == "options":
            profile.options.remove(name, package)
        elif first_key == "env":
            profile.env_values.remove(name, package)
        elif first_key == "build_requires":
            raise ConanException("Edit the profile manually to delete a build_require")
    except KeyError:
        raise ConanException("Profile key '%s' doesn't exist" % key)

    contents = profile.dumps()
    profile_path = get_profile_path(profile_name, cache_profiles_path, get_cwd())
    save(profile_path, contents)
Ejemplo n.º 2
0
def run_in_windows_bash(conanfile, bashcmd, cwd=None, subsystem=None, msys_mingw=True, env=None):
    """ Will run a unix command inside a bash terminal
        It requires to have MSYS2, CYGWIN, or WSL
    """
    env = env or {}
    if platform.system() != "Windows":
        raise ConanException("Command only for Windows operating system")
    subsystem = subsystem or os_info.detect_windows_subsystem()

    if not subsystem:
        raise ConanException("Cannot recognize the Windows subsystem, install MSYS2/cygwin or specify a build_require "
                             "to apply it.")

    if subsystem == MSYS2 and msys_mingw:
        # This needs to be set so that msys2 bash profile will set up the environment correctly.
        env_vars = {"MSYSTEM": "MINGW32" if conanfile.settings.get_safe("arch") == "x86" else "MINGW64",
                    "MSYS2_PATH_TYPE": "inherit"}
    else:
        env_vars = {}

    with environment_append(env_vars):
        hack_env = ""
        if subsystem != WSL:  # In the bash.exe from WSL this trick do not work, always the /usr/bin etc at first place
            inherited_path = conanfile.env.get("PATH", None)
            if isinstance(inherited_path, list):
                paths = [unix_path(path, path_flavor=subsystem) for path in inherited_path]
                inherited_path = ":".join(paths)
            else:
                inherited_path = unix_path(inherited_path, path_flavor=subsystem)

            if "PATH" in env:
                tmp = unix_path(env["PATH"].replace(";", ":"), path_flavor=subsystem)
                inherited_path = "%s:%s" % (tmp, inherited_path) if inherited_path else tmp

            # Put the build_requires and requires path at the first place inside the shell
            hack_env = ' && PATH="%s:$PATH"' % inherited_path if inherited_path else ""

        for var_name, value in env.items():
            if var_name == "PATH":
                continue
            hack_env += ' && %s=%s' % (var_name, value)

        # Needed to change to that dir inside the bash shell
        if cwd and not os.path.isabs(cwd):
            cwd = os.path.join(get_cwd(), cwd)

        curdir = unix_path(cwd or get_cwd(), path_flavor=subsystem)
        to_run = 'cd "%s"%s && %s ' % (curdir, hack_env, bashcmd)
        bash_path = os_info.bash_path()
        bash_path = '"%s"' % bash_path if " " in bash_path else bash_path
        wincmd = '%s --login -c %s' % (bash_path, escape_windows_cmd(to_run))
        conanfile.output.info('run_in_windows_bash: %s' % wincmd)
        # https://github.com/conan-io/conan/issues/2839 (subprocess=True)
        return conanfile._runner(wincmd, output=conanfile.output, subprocess=True)
Ejemplo n.º 3
0
def chdir(newdir):
    old_path = get_cwd()
    os.chdir(newdir)
    try:
        yield
    finally:
        os.chdir(old_path)
Ejemplo n.º 4
0
def cmd_profile_update(profile_name, key, value, cache_profiles_path):
    first_key, rest_key = _get_profile_keys(key)

    profile, _ = read_profile(profile_name, get_cwd(), cache_profiles_path)
    if first_key == "settings":
        profile.settings[rest_key] = value
    elif first_key == "options":
        tmp = OptionsValues([(rest_key, value)])
        profile.options.update(tmp)
    elif first_key == "env":
        profile.env_values.update_replace(rest_key, value)
    elif first_key == "build_requires":
        raise ConanException("Edit the profile manually to change the build_requires")

    contents = profile.dumps()
    profile_path = get_profile_path(profile_name, cache_profiles_path, get_cwd())
    save(profile_path, contents)
Ejemplo n.º 5
0
def unzip(filename, destination=".", keep_permissions=False):
    """
    Unzip a zipped file
    :param filename: Path to the zip file
    :param destination: Destination folder
    :param keep_permissions: Keep the zip permissions. WARNING: Can be dangerous if the zip was not created in a NIX
    system, the bits could produce undefined permission schema. Use only this option if you are sure that the
    zip was created correctly.
    :return:
    """
    if (filename.endswith(".tar.gz") or filename.endswith(".tgz") or
            filename.endswith(".tbz2") or filename.endswith(".tar.bz2") or
            filename.endswith(".tar")):
        return untargz(filename, destination)
    import zipfile
    full_path = os.path.normpath(os.path.join(get_cwd(), destination))

    if hasattr(sys.stdout, "isatty") and sys.stdout.isatty():
        def print_progress(the_size, uncomp_size):
            the_size = (the_size * 100.0 / uncomp_size) if uncomp_size != 0 else 0
            if the_size > print_progress.last_size + 1:
                txt_msg = "Unzipping %d %%" % the_size
                _global_output.rewrite_line(txt_msg)
                print_progress.last_size = the_size
    else:
        def print_progress(_, __):
            pass

    with zipfile.ZipFile(filename, "r") as z:
        uncompress_size = sum((file_.file_size for file_ in z.infolist()))
        if uncompress_size > 100000:
            _global_output.info("Unzipping %s, this can take a while" % human_size(uncompress_size))
        else:
            _global_output.info("Unzipping %s" % human_size(uncompress_size))
        extracted_size = 0

        print_progress.last_size = -1
        if platform.system() == "Windows":
            for file_ in z.infolist():
                extracted_size += file_.file_size
                print_progress(extracted_size, uncompress_size)
                try:
                    z.extract(file_, full_path)
                except Exception as e:
                    _global_output.error("Error extract %s\n%s" % (file_.filename, str(e)))
        else:  # duplicated for, to avoid a platform check for each zipped file
            for file_ in z.infolist():
                extracted_size += file_.file_size
                print_progress(extracted_size, uncompress_size)
                try:
                    z.extract(file_, full_path)
                    if keep_permissions:
                        # Could be dangerous if the ZIP has been created in a non nix system
                        # https://bugs.python.org/issue15795
                        perm = file_.external_attr >> 16 & 0xFFF
                        os.chmod(os.path.join(full_path, file_.filename), perm)
                except Exception as e:
                    _global_output.error("Error extract %s\n%s" % (file_.filename, str(e)))
Ejemplo n.º 6
0
 def json_build_order(self, info, json_output, cwd):
     data = {"groups": [[str(ref) for ref in group] for group in info]}
     json_str = json.dumps(data)
     if json_output is True:  # To the output
         self.user_io.out.write(json_str)
     else:  # Path to a file
         cwd = os.path.abspath(cwd or get_cwd())
         if not os.path.isabs(json_output):
             json_output = os.path.join(cwd, json_output)
         save(json_output, json_str)
Ejemplo n.º 7
0
    def json_output(self, info, json_output, cwd):
        cwd = os.path.abspath(cwd or get_cwd())
        if not os.path.isabs(json_output):
            json_output = os.path.join(cwd, json_output)

        def date_handler(obj):
            return obj.isoformat() if hasattr(obj, 'isoformat') else obj

        save(json_output, json.dumps(info, default=date_handler))
        self.user_io.out.info("json file created at '%s'" % json_output)
Ejemplo n.º 8
0
    def info_graph(self, graph_filename, deps_graph, project_reference, cwd):
        if graph_filename.endswith(".html"):
            from conans.client.graph.grapher import ConanHTMLGrapher
            grapher = ConanHTMLGrapher(project_reference, deps_graph)
        else:
            from conans.client.graph.grapher import ConanGrapher
            grapher = ConanGrapher(project_reference, deps_graph)

        cwd = os.path.abspath(cwd or get_cwd())
        if not os.path.isabs(graph_filename):
            graph_filename = os.path.join(cwd, graph_filename)
        grapher.graph_file(graph_filename)
Ejemplo n.º 9
0
 def _simple_os_call(self, command, cwd):
     if not cwd:
         return os.system(command)
     else:
         try:
             old_dir = get_cwd()
             os.chdir(cwd)
             result = os.system(command)
         except Exception as e:
             raise ConanException("Error while executing"
                                  " '%s'\n\t%s" % (command, str(e)))
         finally:
             os.chdir(old_dir)
         return result
Ejemplo n.º 10
0
def cmd_profile_get(profile_name, key, cache_profiles_path):
    first_key, rest_key = _get_profile_keys(key)
    profile, _ = read_profile(profile_name, get_cwd(), cache_profiles_path)
    try:
        if first_key == "settings":
            return profile.settings[rest_key]
        elif first_key == "options":
            return dict(profile.options.as_list())[rest_key]
        elif first_key == "env":
            package = None
            var = rest_key
            if ":" in rest_key:
                package, var = rest_key.split(":")
            return profile.env_values.data[package][var]
        elif first_key == "build_requires":
            raise ConanException("List the profile manually to see the build_requires")
    except KeyError:
        raise ConanException("Key not found: '%s'" % key)
Ejemplo n.º 11
0
def cmd_profile_create(profile_name, cache_profiles_path, output, detect=False):
    profile_path = get_profile_path(profile_name, cache_profiles_path, get_cwd(),
                                    exists=False)
    if os.path.exists(profile_path):
        raise ConanException("Profile already exists")

    profile = Profile()
    if detect:
        settings = detect_defaults_settings(output)
        for name, value in settings:
            profile.settings[name] = value

    contents = profile.dumps()
    save(profile_path, contents)

    if detect:
        output.info("Profile created with detected settings: %s" % profile_path)
    else:
        output.info("Empty profile created: %s" % profile_path)
    return profile_path
Ejemplo n.º 12
0
def unzip(filename, destination=".", keep_permissions=False, pattern=None, output=None,
          strip_root=False):
    """
    Unzip a zipped file
    :param filename: Path to the zip file
    :param destination: Destination folder (or file for .gz files)
    :param keep_permissions: Keep the zip permissions. WARNING: Can be
    dangerous if the zip was not created in a NIX system, the bits could
    produce undefined permission schema. Use this option only if you are sure
    that the zip was created correctly.
    :param pattern: Extract only paths matching the pattern. This should be a
    Unix shell-style wildcard, see fnmatch documentation for more details.
    :param output: output
    :param flat: If all the contents are in a single dir, flat that directory.
    :return:
    """
    output = default_output(output, 'conans.client.tools.files.unzip')

    if (filename.endswith(".tar.gz") or filename.endswith(".tgz") or
            filename.endswith(".tbz2") or filename.endswith(".tar.bz2") or
            filename.endswith(".tar")):
        return untargz(filename, destination, pattern, strip_root)
    if filename.endswith(".gz"):
        with gzip.open(filename, 'rb') as f:
            file_content = f.read()
        target_name = filename[:-3] if destination == "." else destination
        save(target_name, file_content)
        return
    if filename.endswith(".tar.xz") or filename.endswith(".txz"):
        if six.PY2:
            raise ConanException("XZ format not supported in Python 2. Use Python 3 instead")
        return untargz(filename, destination, pattern, strip_root)

    import zipfile
    full_path = os.path.normpath(os.path.join(get_cwd(), destination))

    if hasattr(sys.stdout, "isatty") and sys.stdout.isatty():
        def print_progress(the_size, uncomp_size):
            the_size = (the_size * 100.0 / uncomp_size) if uncomp_size != 0 else 0
            txt_msg = "Unzipping %d %%"
            if the_size > print_progress.last_size + 1:
                output.rewrite_line(txt_msg % the_size)
                print_progress.last_size = the_size
                if int(the_size) == 99:
                    output.rewrite_line(txt_msg % 100)
    else:
        def print_progress(_, __):
            pass

    with zipfile.ZipFile(filename, "r") as z:
        zip_info = z.infolist()
        if pattern:
            zip_info = [zi for zi in zip_info if fnmatch(zi.filename, pattern)]
        if strip_root:
            names = [n.replace("\\", "/") for n in z.namelist()]
            common_folder = os.path.commonprefix(names).split("/", 1)[0]
            if not common_folder and len(names) > 1:
                raise ConanException("The zip file contains more than 1 folder in the root")
            if len(names) == 1 and len(names[0].split("/", 1)) == 1:
                raise ConanException("The zip file contains a file in the root")
            # Remove the directory entry if present
            # Note: The "zip" format contains the "/" at the end if it is a directory
            zip_info = [m for m in zip_info if m.filename != (common_folder + "/")]
            for member in zip_info:
                name = member.filename.replace("\\", "/")
                member.filename = name.split("/", 1)[1]

        uncompress_size = sum((file_.file_size for file_ in zip_info))
        if uncompress_size > 100000:
            output.info("Unzipping %s, this can take a while" % human_size(uncompress_size))
        else:
            output.info("Unzipping %s" % human_size(uncompress_size))
        extracted_size = 0

        print_progress.last_size = -1
        if platform.system() == "Windows":
            for file_ in zip_info:
                extracted_size += file_.file_size
                print_progress(extracted_size, uncompress_size)
                try:
                    z.extract(file_, full_path)
                except Exception as e:
                    output.error("Error extract %s\n%s" % (file_.filename, str(e)))
        else:  # duplicated for, to avoid a platform check for each zipped file
            for file_ in zip_info:
                extracted_size += file_.file_size
                print_progress(extracted_size, uncompress_size)
                try:
                    z.extract(file_, full_path)
                    if keep_permissions:
                        # Could be dangerous if the ZIP has been created in a non nix system
                        # https://bugs.python.org/issue15795
                        perm = file_.external_attr >> 16 & 0xFFF
                        os.chmod(os.path.join(full_path, file_.filename), perm)
                except Exception as e:
                    output.error("Error extract %s\n%s" % (file_.filename, str(e)))
        output.writeln("")
Ejemplo n.º 13
0
Archivo: win.py Proyecto: wdobbe/conan
def run_in_windows_bash(conanfile,
                        bashcmd,
                        cwd=None,
                        subsystem=None,
                        msys_mingw=True,
                        env=None):
    """ Will run a unix command inside a bash terminal
        It requires to have MSYS2, CYGWIN, or WSL
    """
    env = env or {}
    if platform.system() != "Windows":
        raise ConanException("Command only for Windows operating system")
    subsystem = subsystem or os_info.detect_windows_subsystem()

    if not subsystem:
        raise ConanException(
            "Cannot recognize the Windows subsystem, install MSYS2/cygwin or specify a build_require "
            "to apply it.")

    if subsystem == MSYS2 and msys_mingw:
        # This needs to be set so that msys2 bash profile will set up the environment correctly.
        env_vars = {
            "MSYSTEM":
            "MINGW32"
            if conanfile.settings.get_safe("arch") == "x86" else "MINGW64",
            "MSYS2_PATH_TYPE":
            "inherit"
        }
    else:
        env_vars = {}

    with environment_append(env_vars):
        hack_env = ""
        if subsystem != WSL:  # In the bash.exe from WSL this trick do not work, always the /usr/bin etc at first place
            inherited_path = conanfile.env.get("PATH", None)
            if isinstance(inherited_path, list):
                paths = [
                    unix_path(path, path_flavor=subsystem)
                    for path in inherited_path
                ]
                inherited_path = ":".join(paths)
            else:
                inherited_path = unix_path(inherited_path,
                                           path_flavor=subsystem)

            if "PATH" in env:
                tmp = unix_path(env["PATH"].replace(";", ":"),
                                path_flavor=subsystem)
                inherited_path = "%s:%s" % (
                    tmp, inherited_path) if inherited_path else tmp

            # Put the build_requires and requires path at the first place inside the shell
            hack_env = ' && PATH="%s:$PATH"' % inherited_path if inherited_path else ""

        for var_name, value in env.items():
            if var_name == "PATH":
                continue
            hack_env += ' && %s=%s' % (var_name, value)

        # Needed to change to that dir inside the bash shell
        if cwd and not os.path.isabs(cwd):
            cwd = os.path.join(get_cwd(), cwd)

        curdir = unix_path(cwd or get_cwd(), path_flavor=subsystem)
        to_run = 'cd "%s"%s && %s ' % (curdir, hack_env, bashcmd)
        bash_path = os_info.bash_path()
        bash_path = '"%s"' % bash_path if " " in bash_path else bash_path
        wincmd = '%s --login -c %s' % (bash_path, escape_windows_cmd(to_run))
        conanfile.output.info('run_in_windows_bash: %s' % wincmd)
        # https://github.com/conan-io/conan/issues/2839 (subprocess=True)
        return conanfile._runner(wincmd,
                                 output=conanfile.output,
                                 subprocess=True)
Ejemplo n.º 14
0
 def imports_undo(self, manifest_path):
     cwd = get_cwd()
     manifest_path = _make_abs_path(manifest_path, cwd)
     undo_imports(manifest_path, self._user_io.out)
Ejemplo n.º 15
0
Archivo: win.py Proyecto: yiakwy/conan
def run_in_windows_bash(conanfile,
                        bashcmd,
                        cwd=None,
                        subsystem=None,
                        msys_mingw=True,
                        env=None,
                        with_login=True):
    """ Will run a unix command inside a bash terminal
        It requires to have MSYS2, CYGWIN, or WSL
    """
    env = env or {}
    if platform.system() != "Windows":
        raise ConanException("Command only for Windows operating system")
    subsystem = subsystem or OSInfo.detect_windows_subsystem()

    if not subsystem:
        raise ConanException(
            "Cannot recognize the Windows subsystem, install MSYS2/cygwin "
            "or specify a build_require to apply it.")

    if subsystem == MSYS2 and msys_mingw:
        # This needs to be set so that msys2 bash profile will set up the environment correctly.
        env_vars = {
            "MSYSTEM": ("MINGW32" if conanfile.settings.get_safe("arch")
                        == "x86" else "MINGW64"),
            "MSYS2_PATH_TYPE":
            "inherit"
        }
    else:
        env_vars = {}

    with environment_append(env_vars):

        hack_env = ""
        # In the bash.exe from WSL this trick do not work, always the /usr/bin etc at first place
        if subsystem != WSL:

            def get_path_value(container, subsystem_name):
                """Gets the path from the container dict and returns a
                string with the path for the subsystem_name"""
                _path_key = next(
                    (name
                     for name in container.keys() if "path" == name.lower()),
                    None)
                if _path_key:
                    _path_value = container.get(_path_key)
                    if isinstance(_path_value, list):
                        return ":".join([
                            unix_path(path, path_flavor=subsystem_name)
                            for path in _path_value
                        ])
                    else:
                        return unix_path(_path_value,
                                         path_flavor=subsystem_name)

            # First get the PATH from the conanfile.env
            inherited_path = get_path_value(conanfile.env, subsystem)
            # Then get the PATH from the real env
            env_path = get_path_value(env, subsystem)

            # Both together
            full_env = ":".join(v for v in [env_path, inherited_path] if v)
            # Put the build_requires and requires path at the first place inside the shell
            hack_env = ' && PATH="%s:$PATH"' % full_env if full_env else ""

        for var_name, value in env.items():
            if var_name == "PATH":
                continue
            hack_env += ' && %s=%s' % (var_name, value)

        # Needed to change to that dir inside the bash shell
        if cwd and not os.path.isabs(cwd):
            cwd = os.path.join(get_cwd(), cwd)

        curdir = unix_path(cwd or get_cwd(), path_flavor=subsystem)
        to_run = 'cd "%s"%s && %s ' % (curdir, hack_env, bashcmd)
        bash_path = OSInfo.bash_path()
        bash_path = '"%s"' % bash_path if " " in bash_path else bash_path
        login = "******" if with_login else ""
        wincmd = '%s %s -c %s' % (bash_path, login, escape_windows_cmd(to_run))
        conanfile.output.info('run_in_windows_bash: %s' % wincmd)

        # If is there any other env var that we know it contains paths, convert it to unix_path
        used_special_vars = [
            var for var in ["AR", "AS", "RANLIB", "LD", "STRIP", "CC", "CXX"]
            if var in conanfile.env.keys()
        ]
        normalized_env = {
            p: unix_path(conanfile.env[p], path_flavor=subsystem)
            for p in used_special_vars
        }

        # https://github.com/conan-io/conan/issues/2839 (subprocess=True)
        with environment_append(normalized_env):
            return conanfile._conan_runner(wincmd,
                                           output=conanfile.output,
                                           subprocess=True)
Ejemplo n.º 16
0
    def export_pkg(self,
                   conanfile_path,
                   name,
                   channel,
                   source_folder=None,
                   build_folder=None,
                   package_folder=None,
                   install_folder=None,
                   profile_name=None,
                   settings=None,
                   options=None,
                   env=None,
                   force=False,
                   user=None,
                   version=None,
                   cwd=None):

        settings = settings or []
        options = options or []
        env = env or []
        cwd = cwd or get_cwd()

        # Checks that info files exists if the install folder is specified
        if install_folder and not existing_info_files(
                _make_abs_path(install_folder, cwd)):
            raise ConanException(
                "The specified install folder doesn't contain '%s' and '%s' "
                "files" % (CONANINFO, BUILD_INFO))

        conanfile_path = _get_conanfile_path(conanfile_path, cwd, py=True)

        if package_folder:
            if build_folder or source_folder:
                raise ConanException(
                    "package folder definition incompatible with build and source folders"
                )
            package_folder = _make_abs_path(package_folder, cwd)

        build_folder = _make_abs_path(build_folder, cwd)
        install_folder = _make_abs_path(install_folder,
                                        cwd,
                                        default=build_folder)
        source_folder = _make_abs_path(source_folder,
                                       cwd,
                                       default=os.path.dirname(conanfile_path))

        # Checks that no both settings and info files are specified
        if install_folder and existing_info_files(install_folder) and \
                (profile_name or settings or options or env):
            raise ConanException(
                "%s and %s are found, at '%s' folder, so specifying profile, "
                "settings, options or env is not allowed" %
                (CONANINFO, BUILD_INFO, install_folder))

        infos_present = existing_info_files(install_folder)
        if not infos_present:
            profile = profile_from_args(profile_name,
                                        settings,
                                        options,
                                        env=env,
                                        cwd=cwd,
                                        client_cache=self._client_cache)
        else:
            profile = read_conaninfo_profile(install_folder)

        conanfile = load_conanfile_class(conanfile_path)
        if (name and conanfile.name and conanfile.name != name) or \
           (version and conanfile.version and conanfile.version != version):
            raise ConanException(
                "Specified name/version doesn't match with the "
                "name/version in the conanfile")
        cmd_export(conanfile_path, name, version, user, channel, False,
                   self._user_io.out, self._client_cache)

        if not (name and version):
            name = conanfile.name
            version = conanfile.version

        reference = ConanFileReference(name, version, user, channel)
        recorder = ActionRecorder()
        manager = self._init_manager(recorder)
        manager.export_pkg(reference,
                           source_folder=source_folder,
                           build_folder=build_folder,
                           package_folder=package_folder,
                           install_folder=install_folder,
                           profile=profile,
                           force=force)
Ejemplo n.º 17
0
 def read_profile(self, profile=None):
     p, _ = read_profile(profile, get_cwd(),
                         self._client_cache.profiles_path)
     return p
Ejemplo n.º 18
0
def unzip(filename, destination=".", keep_permissions=False, pattern=None):
    """
    Unzip a zipped file
    :param filename: Path to the zip file
    :param destination: Destination folder
    :param keep_permissions: Keep the zip permissions. WARNING: Can be
    dangerous if the zip was not created in a NIX system, the bits could
    produce undefined permission schema. Use this option only if you are sure
    that the zip was created correctly.
    :param pattern: Extract only paths matching the pattern. This should be a
    Unix shell-style wildcard, see fnmatch documentation for more details.
    :return:
    """
    if (filename.endswith(".tar.gz") or filename.endswith(".tgz")
            or filename.endswith(".tbz2") or filename.endswith(".tar.bz2")
            or filename.endswith(".tar")):
        return untargz(filename, destination, pattern)
    if filename.endswith(".tar.xz") or filename.endswith(".txz"):
        if six.PY2:
            raise ConanException(
                "XZ format not supported in Python 2. Use Python 3 instead")
        return untargz(filename, destination, pattern)

    import zipfile
    full_path = os.path.normpath(os.path.join(get_cwd(), destination))

    if hasattr(sys.stdout, "isatty") and sys.stdout.isatty():

        def print_progress(the_size, uncomp_size):
            the_size = (the_size * 100.0 /
                        uncomp_size) if uncomp_size != 0 else 0
            txt_msg = "Unzipping %d %%"
            if the_size > print_progress.last_size + 1:
                _global_output.rewrite_line(txt_msg % the_size)
                print_progress.last_size = the_size
                if int(the_size) == 99:
                    _global_output.rewrite_line(txt_msg % 100)
                    _global_output.writeln("")
    else:

        def print_progress(_, __):
            pass

    with zipfile.ZipFile(filename, "r") as z:
        if not pattern:
            zip_info = z.infolist()
        else:
            zip_info = [
                zi for zi in z.infolist() if fnmatch(zi.filename, pattern)
            ]
        uncompress_size = sum((file_.file_size for file_ in zip_info))
        if uncompress_size > 100000:
            _global_output.info("Unzipping %s, this can take a while" %
                                human_size(uncompress_size))
        else:
            _global_output.info("Unzipping %s" % human_size(uncompress_size))
        extracted_size = 0

        print_progress.last_size = -1
        if platform.system() == "Windows":
            for file_ in zip_info:
                extracted_size += file_.file_size
                print_progress(extracted_size, uncompress_size)
                try:
                    z.extract(file_, full_path)
                except Exception as e:
                    _global_output.error("Error extract %s\n%s" %
                                         (file_.filename, str(e)))
        else:  # duplicated for, to avoid a platform check for each zipped file
            for file_ in zip_info:
                extracted_size += file_.file_size
                print_progress(extracted_size, uncompress_size)
                try:
                    z.extract(file_, full_path)
                    if keep_permissions:
                        # Could be dangerous if the ZIP has been created in a non nix system
                        # https://bugs.python.org/issue15795
                        perm = file_.external_attr >> 16 & 0xFFF
                        os.chmod(os.path.join(full_path, file_.filename), perm)
                except Exception as e:
                    _global_output.error("Error extract %s\n%s" %
                                         (file_.filename, str(e)))
Ejemplo n.º 19
0
def unzip(filename, destination=".", keep_permissions=False):
    """
    Unzip a zipped file
    :param filename: Path to the zip file
    :param destination: Destination folder
    :param keep_permissions: Keep the zip permissions. WARNING: Can be dangerous if the zip was not created in a NIX
    system, the bits could produce undefined permission schema. Use only this option if you are sure that the
    zip was created correctly.
    :return:
    """
    if (filename.endswith(".tar.gz") or filename.endswith(".tgz")
            or filename.endswith(".tbz2") or filename.endswith(".tar.bz2")
            or filename.endswith(".tar")):
        return untargz(filename, destination)
    import zipfile
    full_path = os.path.normpath(os.path.join(get_cwd(), destination))

    if hasattr(sys.stdout, "isatty") and sys.stdout.isatty():

        def print_progress(the_size, uncomp_size):
            the_size = (the_size * 100.0 /
                        uncomp_size) if uncomp_size != 0 else 0
            if the_size > print_progress.last_size + 1:
                txt_msg = "Unzipping %d %%" % the_size
                _global_output.rewrite_line(txt_msg)
                print_progress.last_size = the_size
    else:

        def print_progress(_, __):
            pass

    with zipfile.ZipFile(filename, "r") as z:
        uncompress_size = sum((file_.file_size for file_ in z.infolist()))
        if uncompress_size > 100000:
            _global_output.info("Unzipping %s, this can take a while" %
                                human_size(uncompress_size))
        else:
            _global_output.info("Unzipping %s" % human_size(uncompress_size))
        extracted_size = 0

        print_progress.last_size = -1
        if platform.system() == "Windows":
            for file_ in z.infolist():
                extracted_size += file_.file_size
                print_progress(extracted_size, uncompress_size)
                try:
                    z.extract(file_, full_path)
                except Exception as e:
                    _global_output.error("Error extract %s\n%s" %
                                         (file_.filename, str(e)))
        else:  # duplicated for, to avoid a platform check for each zipped file
            for file_ in z.infolist():
                extracted_size += file_.file_size
                print_progress(extracted_size, uncompress_size)
                try:
                    z.extract(file_, full_path)
                    if keep_permissions:
                        # Could be dangerous if the ZIP has been created in a non nix system
                        # https://bugs.python.org/issue15795
                        perm = file_.external_attr >> 16 & 0xFFF
                        os.chmod(os.path.join(full_path, file_.filename), perm)
                except Exception as e:
                    _global_output.error("Error extract %s\n%s" %
                                         (file_.filename, str(e)))