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)
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)
def chdir(newdir): old_path = get_cwd() os.chdir(newdir) try: yield finally: os.chdir(old_path)
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)
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)))
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)
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)
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)
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
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)
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
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("")
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)
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)
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)
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)
def read_profile(self, profile=None): p, _ = read_profile(profile, get_cwd(), self._client_cache.profiles_path) return p
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)))