Beispiel #1
0
    def __init__(
        self,
        base_folder=None,
        current_folder=None,
        servers=None,
        users=None,
        client_version=CLIENT_VERSION,
        min_server_compatible_version=MIN_SERVER_COMPATIBLE_VERSION,
    ):
        """
        storage_folder: Local storage path
        current_folder: Current execution folder
        servers: dict of {remote_name: TestServer}
        logins is a list of (user, password) for auto input in order
        if required==> [("lasote", "mypass"), ("other", "otherpass")]
        """
        if users is None:
            users = [(TESTING_REMOTE_PRIVATE_USER, TESTING_REMOTE_PRIVATE_PASS)]
        self.users = users
        self.servers = servers or {}

        self.client_version = Version(client_version)
        self.min_server_compatible_version = Version(min_server_compatible_version)

        self.base_folder = base_folder or temp_folder()
        # Define storage_folder, if not, it will be readed from conf file and pointed to real user home
        self.storage_folder = os.path.join(self.base_folder, ".conan", "data")
        # First initialization for set paths (some test copies data before first real initialization)
        self.init_dynamic_vars()
        self.default_settings(get_env("CONAN_COMPILER", "gcc"), get_env("CONAN_COMPILER_VERSION", "4.8"))

        logger.debug("Client storage = %s" % self.storage_folder)
        self.current_folder = current_folder or temp_folder()
Beispiel #2
0
    def __init__(self, base_folder=None, current_folder=None,
                 servers=None, users=None, client_version=CLIENT_VERSION,
                 min_server_compatible_version=MIN_SERVER_COMPATIBLE_VERSION):
        """
        storage_folder: Local storage path
        current_folder: Current execution folder
        servers: dict of {remote_name: TestServer}
        logins is a list of (user, password) for auto input in order
        if required==> [("lasote", "mypass"), ("other", "otherpass")]
        """
        self.users = users or {"default":
                               [(TESTING_REMOTE_PRIVATE_USER, TESTING_REMOTE_PRIVATE_PASS)]}
        self.servers = servers or {}

        self.client_version = Version(str(client_version))
        self.min_server_compatible_version = Version(str(min_server_compatible_version))

        self.base_folder = base_folder or temp_folder()
        # Define storage_folder, if not, it will be read from conf file & pointed to real user home
        self.storage_folder = os.path.join(self.base_folder, ".conan", "data")
        self.paths = ConanPaths(self.base_folder, self.storage_folder, TestBufferConanOutput())
        self.default_settings(get_env("CONAN_COMPILER", "gcc"),
                              get_env("CONAN_COMPILER_VERSION", "4.8"))

        self.init_dynamic_vars()

        save(self.paths.registry, "")
        registry = RemoteRegistry(self.paths.registry, TestBufferConanOutput())
        for name, server in self.servers.items():
            registry.add(name, server.fake_url)

        logger.debug("Client storage = %s" % self.storage_folder)
        self.current_folder = current_folder or temp_folder()
Beispiel #3
0
 def _is_sudo_enabled():
     if "CONAN_SYSREQUIRES_SUDO" not in os.environ:
         if os.name == 'posix' and os.geteuid() == 0:
             return False
         if os.name == 'nt':
             return False
     return get_env("CONAN_SYSREQUIRES_SUDO", True)
Beispiel #4
0
 def _get_sysrequire_mode():
     allowed_modes= ("enabled", "verify", "disabled")
     mode = get_env("CONAN_SYSREQUIRES_MODE", "enabled")
     mode_lower = mode.lower()
     if mode_lower not in allowed_modes:
         raise ConanException("CONAN_SYSREQUIRES_MODE=%s is not allowed, allowed modes=%r" % (mode, allowed_modes))
     return mode_lower
Beispiel #5
0
    def package(self):
        """Generate the info txt files and calls the conanfile package method.
        """

        # FIXME: Is weak to assign here the recipe_hash
        manifest = self._client_cache.load_manifest(self._conan_ref)
        self._conan_file.info.recipe_hash = manifest.summary_hash

        # Creating ***info.txt files
        save(os.path.join(self.build_folder, CONANINFO), self._conan_file.info.dumps())
        self._out.info("Generated %s" % CONANINFO)
        save(os.path.join(self.build_folder, BUILD_INFO), TXTGenerator(self._conan_file).content)
        self._out.info("Generated %s" % BUILD_INFO)

        os.chdir(self.build_folder)

        if getattr(self._conan_file, 'no_copy_source', False):
            source_folder = self.source_folder
        else:
            source_folder = self.build_folder
        with get_env_context_manager(self._conan_file):
            install_folder = self.build_folder  # While installing, the infos goes to build folder
            create_package(self._conan_file, source_folder, self.build_folder, self.package_folder,
                           install_folder, self._out)

        if get_env("CONAN_READ_ONLY_CACHE", False):
            make_read_only(self.package_folder)
Beispiel #6
0
def _format_conanfile_exception(scope, method, exception):
    """
    It will iterate the traceback lines, when it finds that the source code is inside the users
    conanfile it "start recording" the messages, when the trace exits the conanfile we return
    the traces.
    """
    import sys
    import traceback
    if get_env("CONAN_VERBOSE_TRACEBACK", False):
        return traceback.format_exc()
    try:
        conanfile_reached = False
        tb = sys.exc_info()[2]
        index = 0
        content_lines = []

        while True:  # If out of index will raise and will be captured later
            filepath, line, name, contents = traceback.extract_tb(tb, 40)[index]  # 40 levels of nested functions max, get the latest
            if "conanfile.py" not in filepath:  # Avoid show trace from internal conan source code
                if conanfile_reached:  # The error goes to internal code, exit print
                    break
            else:
                if not conanfile_reached:  # First line
                    msg = "%s: Error in %s() method" % (scope, method)
                    msg += ", line %d\n\t%s" % (line, contents)
                else:
                    msg = "while calling '%s', line %d\n\t%s" % (name, line, contents) if line else "\n\t%s" % contents
                content_lines.append(msg)
                conanfile_reached = True
            index += 1
    except:
        pass
    ret = "\n".join(content_lines)
    ret += "\n\t%s: %s" % (exception.__class__.__name__, str(exception))
    return ret
Beispiel #7
0
 def storage_path(self):
     try:
         result = os.path.expanduser(self.storage["path"])
     except KeyError:
         result = None
     result = get_env("CONAN_STORAGE_PATH", result)
     return result
Beispiel #8
0
    def storage_path(self):
        # Try with CONAN_STORAGE_PATH
        result = get_env('CONAN_STORAGE_PATH', None)

        # Try with conan.conf "path"
        if not result:
            try:
                env_conan_user_home = os.getenv("CONAN_USER_HOME")
                # if env var is declared, any specified path will be relative to CONAN_USER_HOME
                # even with the ~/
                if env_conan_user_home:
                    storage = self.storage["path"]
                    if storage[:2] == "~/":
                        storage = storage[2:]
                    result = os.path.join(env_conan_user_home, storage)
                else:
                    result = self.storage["path"]
            except KeyError:
                pass

        # expand the result and check if absolute
        if result:
            result = conan_expand_user(result)
            if not os.path.isabs(result):
                raise ConanException("Conan storage path has to be an absolute path")
        return result
Beispiel #9
0
def get_package(conanfile, package_ref, package_folder, output, recorder, proxy, update):
    # TODO: This access to proxy attributes has to be improved
    remote_manager = proxy._remote_manager
    registry = proxy.registry
    try:
        if update:
            _remove_if_outdated(package_folder, package_ref, proxy, output)
        local_package = os.path.exists(package_folder)
        if local_package:
            output.success('Already installed!')
            log_package_got_from_local_cache(package_ref)
            recorder.package_fetched_from_cache(package_ref)
            return False
        else:
            remote = registry.get_ref(package_ref.conan)
            # remote will be defined, as package availability has been checked from installer
            remote_manager.get_package(conanfile, package_ref, package_folder, remote, output, recorder)
            if get_env("CONAN_READ_ONLY_CACHE", False):
                make_read_only(package_folder)
            recorder.package_downloaded(package_ref, remote.url)
            return True
    except BaseException as e:
        output.error("Exception while getting package: %s" % str(package_ref.package_id))
        output.error("Exception: %s %s" % (type(e), str(e)))
        _clean_package(package_folder, output)
        raise
Beispiel #10
0
def vs_installation_path(version, preference=None):

    vs_installation_path = None

    if not preference:
        env_prefs = get_env("CONAN_VS_INSTALLATION_PREFERENCE", list())

        if env_prefs:
            preference = env_prefs
        else:  # default values
            preference = ["Enterprise", "Professional", "Community", "BuildTools"]

    # Try with vswhere()
    try:
        legacy_products = vswhere(legacy=True)
        all_products = vswhere(products=["*"])
        products = legacy_products + all_products
    except ConanException:
        products = None

    vs_paths = []

    if products:
        # remove repeated products
        seen_products = []
        for product in products:
            if product not in seen_products:
                seen_products.append(product)

        # Append products with "productId" by order of preference
        for product_type in preference:
            for product in seen_products:
                product = dict(product)
                if product["installationVersion"].startswith(("%d." % int(version))) and "productId" in product:
                    if product_type in product["productId"]:
                        vs_paths.append(product["installationPath"])

        # Append products without "productId" (Legacy installations)
        for product in seen_products:
            product = dict(product)
            if product["installationVersion"].startswith(("%d." % int(version))) and "productId" not in product:
                vs_paths.append(product["installationPath"])

    # If vswhere does not find anything or not available, try with vs_comntools()
    if not vs_paths:
        vs_path = vs_comntools(version)

        if vs_path:
            sub_path_to_remove = os.path.join("", "Common7", "Tools", "")
            # Remove '\\Common7\\Tools\\' to get same output as vswhere
            if vs_path.endswith(sub_path_to_remove):
                vs_path = vs_path[:-(len(sub_path_to_remove)+1)]

        vs_installation_path = vs_path
    else:
        vs_installation_path = vs_paths[0]

    return vs_installation_path
Beispiel #11
0
def get_command():

    def instance_remote_manager(client_cache):
        requester = requests.Session()
        requester.proxies = client_cache.conan_config.proxies
        # Verify client version against remotes
        version_checker_requester = VersionCheckerRequester(requester, Version(CLIENT_VERSION),
                                                            Version(MIN_SERVER_COMPATIBLE_VERSION),
                                                            out)
        # To handle remote connections
        rest_api_client = RestApiClient(out, requester=version_checker_requester)
        # To store user and token
        localdb = LocalDB(client_cache.localdb)
        # Wraps RestApiClient to add authentication support (same interface)
        auth_manager = ConanApiAuthManager(rest_api_client, user_io, localdb)
        # Handle remote connections
        remote_manager = RemoteManager(client_cache, auth_manager, out)
        return remote_manager

    use_color = get_env("CONAN_COLOR_DISPLAY", 1)
    if use_color and hasattr(sys.stdout, "isatty") and sys.stdout.isatty():
        import colorama
        colorama.init()
        color = True
    else:
        color = False
    out = ConanOutput(sys.stdout, color)
    user_io = UserIO(out=out)

    user_folder = os.getenv("CONAN_USER_HOME", conan_expand_user("~"))

    try:
        # To capture exceptions in conan.conf parsing
        client_cache = ClientCache(user_folder, None, out)
        # obtain a temp ConanManager instance to execute the migrations
        remote_manager = instance_remote_manager(client_cache)

        # Get a DiskSearchManager
        search_adapter = DiskSearchAdapter()
        search_manager = DiskSearchManager(client_cache, search_adapter)
        manager = ConanManager(client_cache, user_io, ConanRunner(), remote_manager, search_manager)

        client_cache = migrate_and_get_client_cache(user_folder, out, manager)
    except Exception as e:
        out.error(str(e))
        sys.exit(True)

    # Get the new command instance after migrations have been done
    remote_manager = instance_remote_manager(client_cache)

    # Get a search manager
    search_adapter = DiskSearchAdapter()
    search_manager = DiskSearchManager(client_cache, search_adapter)
    command = Command(client_cache, user_io, ConanRunner(), remote_manager, search_manager)
    return command
Beispiel #12
0
def configure_logger():
    from conans.util.env_reader import get_env

    # #### LOGGER, MOVED FROM CONF BECAUSE OF MULTIPLE PROBLEM WITH CIRCULAR INCLUDES #####
    logging_level = get_env('CONAN_LOGGING_LEVEL', logging.CRITICAL)
    logging_file = get_env('CONAN_LOGGING_FILE', None)  # None is stdout

    logger = logging.getLogger('conans')
    if logging_file is not None:
        hdlr = logging.FileHandler(logging_file)
    else:
        hdlr = StreamHandler(sys.stderr)

    formatter = MultiLineFormatter('%(levelname)-6s:%(filename)-15s[%(lineno)d]: '
                                   '%(message)s [%(asctime)s]')
    hdlr.setFormatter(formatter)
    for hand in logger.handlers:
        logger.removeHandler(hand)
    logger.addHandler(hdlr)
    logger.setLevel(logging_level)
    return logger
Beispiel #13
0
    def _build_folder(test_build_folder, profile, base_folder):
        # Use the specified build folder when available.
        if test_build_folder:
            return (os.path.abspath(test_build_folder), False)

        # Otherwise, generate a new test folder depending on the configuration.
        if get_env('CONAN_TEMP_TEST_FOLDER', False):
            return (tempfile.mkdtemp(prefix='conans'), True)

        sha = hashlib.sha1("".join(profile.dumps()).encode()).hexdigest()
        build_folder = os.path.join(base_folder, "build", sha)
        return (build_folder, False)
Beispiel #14
0
    def factory():
        """Factory"""

        def instance_remote_manager(client_cache):
            requester = get_basic_requester(client_cache)
            # Verify client version against remotes
            version_checker_requester = VersionCheckerRequester(requester, Version(CLIENT_VERSION),
                                                                Version(MIN_SERVER_COMPATIBLE_VERSION),
                                                                out)
            # To handle remote connections
            put_headers = client_cache.read_put_headers()
            rest_api_client = RestApiClient(out, requester=version_checker_requester, put_headers=put_headers)
            # To store user and token
            localdb = LocalDB(client_cache.localdb)
            # Wraps RestApiClient to add authentication support (same interface)
            auth_manager = ConanApiAuthManager(rest_api_client, user_io, localdb)
            # Handle remote connections
            remote_manager = RemoteManager(client_cache, auth_manager, out)
            return remote_manager

        use_color = get_env("CONAN_COLOR_DISPLAY", 1)
        if use_color and hasattr(sys.stdout, "isatty") and sys.stdout.isatty():
            import colorama
            colorama.init()
            color = True
        else:
            color = False
        out = ConanOutput(sys.stdout, color)
        user_io = UserIO(out=out)

        user_folder = os.getenv("CONAN_USER_HOME", conan_expand_user("~"))

        try:
            client_cache = migrate_and_get_client_cache(user_folder, out)
        except Exception as e:
            out.error(str(e))
            raise

        with tools.environment_append(client_cache.conan_config.env_vars):
            # Adjust CONAN_LOGGING_LEVEL with the env readed
            conans.util.log.logger = configure_logger()

            # Get the new command instance after migrations have been done
            remote_manager = instance_remote_manager(client_cache)

            # Get a search manager
            search_adapter = DiskSearchAdapter()
            search_manager = DiskSearchManager(client_cache, search_adapter)
            conan = Conan(client_cache, user_io, get_conan_runner(), remote_manager, search_manager)

        return conan
Beispiel #15
0
 def storage_path(self):
     try:
         conan_user_home = os.getenv("CONAN_USER_HOME")
         if conan_user_home:
             storage = self.storage["path"]
             if storage[:2] == "~/":
                 storage = storage[2:]
             result = os.path.join(conan_user_home, storage)
         else:
             result = conan_expand_user(self.storage["path"])
     except KeyError:
         result = None
     result = get_env('CONAN_STORAGE_PATH', result)
     return result
Beispiel #16
0
    def update(self, down_reqs, output, own_ref, down_ref):
        """ Compute actual requirement values when downstream values are defined
        param down_reqs: the current requirements as coming from downstream to override
                         current requirements
        param own_ref: ConanFileReference of the current conanfile
        param down_ref: ConanFileReference of the downstream that is overriding values or None
        return: new Requirements() value to be passed upstream
        """

        assert isinstance(down_reqs, Requirements)
        assert isinstance(own_ref, ConanFileReference) if own_ref else True
        assert isinstance(down_ref, ConanFileReference) if down_ref else True

        error_on_override = get_env("CONAN_ERROR_ON_OVERRIDE", False)

        new_reqs = down_reqs.copy()
        if own_ref:
            new_reqs.pop(own_ref.name, None)
        for name, req in self.items():
            if req.private:
                continue
            if name in down_reqs:
                other_req = down_reqs[name]
                # update dependency
                other_ref = other_req.ref
                if other_ref and other_ref != req.ref:
                    msg = "requirement %s overridden by %s to %s " \
                          % (req.ref, down_ref or "your conanfile", other_ref)

                    if error_on_override and not other_req.override:
                        raise ConanException(msg)

                    msg = "%s %s" % (own_ref, msg)
                    output.warn(msg)
                    req.ref = other_ref

            new_reqs[name] = req
        return new_reqs
Beispiel #17
0
def _format_conanfile_exception(scope, method, exception):
    """
    It will iterate the traceback lines, when it finds that the source code is inside the users
    conanfile it "start recording" the messages, when the trace exits the conanfile we return
    the traces.
    """
    import sys
    import traceback
    if get_env("CONAN_VERBOSE_TRACEBACK", False):
        return traceback.format_exc()
    try:
        conanfile_reached = False
        tb = sys.exc_info()[2]
        index = 0
        content_lines = []

        while True:  # If out of index will raise and will be captured later
            filepath, line, name, contents = traceback.extract_tb(
                tb,
                40)[index]  # 40 levels of nested functions max, get the latest
            if "conanfile.py" not in filepath:  # Avoid show trace from internal conan source code
                if conanfile_reached:  # The error goes to internal code, exit print
                    break
            else:
                if not conanfile_reached:  # First line
                    msg = "%s: Error in %s() method" % (scope, method)
                    msg += ", line %d\n\t%s" % (line, contents)
                else:
                    msg = "while calling '%s', line %d\n\t%s" % (
                        name, line, contents) if line else "\n\t%s" % contents
                content_lines.append(msg)
                conanfile_reached = True
            index += 1
    except:
        pass
    ret = "\n".join(content_lines)
    ret += "\n\t%s: %s" % (exception.__class__.__name__, str(exception))
    return ret
Beispiel #18
0
    def source(self):
        filename = "tcl{}-src.tar.gz".format(self.version)
        url = "https://downloads.sourceforge.net/project/tcl/Tcl/{}/{}".format(
            self.version, filename)
        sha256 = "ad0cd2de2c87b9ba8086b43957a0de3eb2eb565c7159d5f53ccbba3feb915f4e"

        dlfilepath = os.path.join(tempfile.gettempdir(), filename)
        if os.path.exists(dlfilepath) and not get_env("TCL_FORCE_DOWNLOAD",
                                                      False):
            self.output.info(
                "Skipping download. Using cached {}".format(dlfilepath))
        else:
            self.output.info("Downloading {} from {}".format(self.name, url))
            tools.download(url, dlfilepath)
        tools.check_sha256(dlfilepath, sha256)
        tools.untargz(dlfilepath)

        extracted_dir = "{}{}".format(self.name, self.version)
        os.rename(extracted_dir, self._source_subfolder)

        unix_config_dir = self._get_configure_dir("unix")
        # When disabling 64-bit support (in 32-bit), this test must be 0 in order to use "long long" for 64-bit ints
        # (${tcl_type_64bit} can be either "__int64" or "long long")
        tools.replace_in_file(os.path.join(unix_config_dir, "configure"),
                              "(sizeof(${tcl_type_64bit})==sizeof(long))",
                              "(sizeof(${tcl_type_64bit})!=sizeof(long))")

        unix_makefile_in = os.path.join(unix_config_dir, "Makefile.in")
        # Avoid building internal libraries as shared libraries
        tools.replace_in_file(unix_makefile_in,
                              "--enable-shared --enable-threads",
                              "--enable-threads")
        # Avoid clearing CFLAGS and LDFLAGS in the makefile
        tools.replace_in_file(unix_makefile_in, "\nCFLAGS\t", "\n#CFLAGS\t")
        tools.replace_in_file(unix_makefile_in, "\nLDFLAGS\t", "\n#LDFLAGS\t")
        # Use CFLAGS and CPPFLAGS as argument to CC
        tools.replace_in_file(unix_makefile_in, "${CFLAGS}",
                              "${CFLAGS} ${CPPFLAGS}")
Beispiel #19
0
def _validate_fpic(conanfile):
    v2_mode = get_env(CONAN_V2_MODE_ENVVAR, False)
    # FIXME: The toolchain() has dissapeared, but now it is integrated with generators.
    # FIXME: Not sure this check should be here, this could raise before the graph is fully evaluated
    toolchain = hasattr(conanfile, "toolchain")

    if not (toolchain or v2_mode):
        return
    fpic = conanfile.options.get_safe("fPIC")
    if fpic is None:
        return
    os_ = conanfile.settings.get_safe("os")
    if os_ and "Windows" in os_:
        if v2_mode:
            raise ConanInvalidConfiguration("fPIC option defined for Windows")
        conanfile.output.error("fPIC option defined for Windows")
        return
    shared = conanfile.options.get_safe("shared")
    if shared:
        if v2_mode:
            raise ConanInvalidConfiguration(
                "fPIC option defined for a shared library")
        conanfile.output.error("fPIC option defined for a shared library")
Beispiel #20
0
def write_generators(conanfile, path, output):
    """ produces auxiliary files, required to build a project or a package.
    """
    for generator_name in conanfile.generators:
        try:
            generator_class = registered_generators[generator_name]
        except KeyError:
            raise ConanException("Invalid generator '%s'. Available types: %s" %
                                 (generator_name, ", ".join(registered_generators.available)))
        try:
            generator = generator_class(conanfile)
        except TypeError:
            # To allow old-style generator packages to work (e.g. premake)
            output.warn("Generator %s failed with new __init__(), trying old one")
            generator = generator_class(conanfile.deps_cpp_info, conanfile.cpp_info)

        try:
            generator.output_path = path
            content = generator.content
            if isinstance(content, dict):
                if generator.filename:
                    output.warn("Generator %s is multifile. Property 'filename' not used"
                                % (generator_name,))
                for k, v in content.items():
                    v = normalize(v)
                    output.info("Generator %s created %s" % (generator_name, k))
                    save(join(path, k), v)
            else:
                content = normalize(content)
                output.info("Generator %s created %s" % (generator_name, generator.filename))
                save(join(path, generator.filename), content)
        except Exception as e:
            if get_env("CONAN_VERBOSE_TRACEBACK", False):
                output.error(traceback.format_exc())
            output.error("Generator %s(file:%s) failed\n%s"
                         % (generator_name, generator.filename, str(e)))
            raise ConanException(e)
Beispiel #21
0
def write_generators(conanfile, path, output):
    """ produces auxiliary files, required to build a project or a package.
    """
    for generator_name in conanfile.generators:
        try:
            generator_class = registered_generators[generator_name]
        except KeyError:
            raise ConanException("Invalid generator '%s'. Available types: %s" %
                                 (generator_name, ", ".join(registered_generators.available)))
        try:
            generator = generator_class(conanfile)
        except TypeError:
            # To allow old-style generator packages to work (e.g. premake)
            output.warn("Generator %s failed with new __init__(), trying old one")
            generator = generator_class(conanfile.deps_cpp_info, conanfile.cpp_info)

        try:
            generator.output_path = path
            content = generator.content
            if isinstance(content, dict):
                if generator.filename:
                    output.warn("Generator %s is multifile. Property 'filename' not used"
                                % (generator_name,))
                for k, v in content.items():
                    v = normalize(v)
                    output.info("Generator %s created %s" % (generator_name, k))
                    save(join(path, k), v, only_if_modified=True)
            else:
                content = normalize(content)
                output.info("Generator %s created %s" % (generator_name, generator.filename))
                save(join(path, generator.filename), content, only_if_modified=True)
        except Exception as e:
            if get_env("CONAN_VERBOSE_TRACEBACK", False):
                output.error(traceback.format_exc())
            output.error("Generator %s(file:%s) failed\n%s"
                         % (generator_name, generator.filename, str(e)))
            raise ConanException(e)
Beispiel #22
0
    def run(self, command_line, user_io=None, ignore_error=False):
        """ run a single command as in the command line.
            If user or password is filled, user_io will be mocked to return this
            tuple if required
        """
        self.init_dynamic_vars(user_io)
        with tools.environment_append(self.client_cache.conan_config.env_vars):
            # Settings preprocessor
            interactive = not get_env("CONAN_NON_INTERACTIVE", False)
            conan = Conan(self.client_cache, self.user_io, self.runner, self.remote_manager,
                          self.search_manager, settings_preprocessor, interactive=interactive)
        outputer = CommandOutputer(self.user_io, self.client_cache)
        command = Command(conan, self.client_cache, self.user_io, outputer)
        args = shlex.split(command_line)
        current_dir = os.getcwd()
        os.chdir(self.current_folder)
        old_path = sys.path[:]
        sys.path.append(os.path.join(self.client_cache.conan_folder, "python"))
        old_modules = list(sys.modules.keys())
        try:
            error = command.run(args)
        finally:
            sys.path = old_path
            os.chdir(current_dir)
            # Reset sys.modules to its prev state. A .copy() DOES NOT WORK
            added_modules = set(sys.modules).difference(old_modules)
            for added in added_modules:
                sys.modules.pop(added, None)

        if not ignore_error and error:
            logger.error(self.user_io.out)
            print(self.user_io.out)
            raise Exception("Command failed:\n%s" % command_line)

        self.all_output += str(self.user_io.out)
        return error
Beispiel #23
0
    def _get_remote_package(self, conan_file, package_reference, output):
        """Get remote package. It won't check if it's outdated"""
        # Compute conan_file package from local (already compiled) or from remote

        package_folder = self._client_cache.package(package_reference,
                                                    conan_file.short_paths)

        # If already exists do not dirt the output, the common situation
        # is that package is already installed and OK. If don't, the proxy
        # will print some other message about it
        if not os.path.exists(package_folder):
            self._out.info("Retrieving package %s" %
                           package_reference.package_id)

        if self._remote_proxy.get_package(package_reference,
                                          short_paths=conan_file.short_paths):
            _handle_system_requirements(conan_file, package_reference,
                                        self._client_cache, output)
            if get_env("CONAN_READ_ONLY_CACHE", False):
                make_read_only(package_folder)
            return True

        _raise_package_not_found_error(conan_file, package_reference.conan,
                                       output)
Beispiel #24
0
    def run(self, command_line, user_io=None, ignore_error=False):
        """ run a single command as in the command line.
            If user or password is filled, user_io will be mocked to return this
            tuple if required
        """
        self.init_dynamic_vars(user_io)
        with tools.environment_append(self.client_cache.conan_config.env_vars):
            # Settings preprocessor
            interactive = not get_env("CONAN_NON_INTERACTIVE", False)
            conan = Conan(self.client_cache, self.user_io, self.runner, self.remote_manager,
                          settings_preprocessor, interactive=interactive)
        outputer = CommandOutputer(self.user_io, self.client_cache)
        command = Command(conan, self.client_cache, self.user_io, outputer)
        args = shlex.split(command_line)
        current_dir = os.getcwd()
        os.chdir(self.current_folder)
        old_path = sys.path[:]
        sys.path.append(os.path.join(self.client_cache.conan_folder, "python"))
        old_modules = list(sys.modules.keys())
        try:
            error = command.run(args)
        finally:
            sys.path = old_path
            os.chdir(current_dir)
            # Reset sys.modules to its prev state. A .copy() DOES NOT WORK
            added_modules = set(sys.modules).difference(old_modules)
            for added in added_modules:
                sys.modules.pop(added, None)

        if not ignore_error and error:
            logger.error(self.user_io.out)
            print(self.user_io.out)
            raise Exception("Command failed:\n%s" % command_line)

        self.all_output += str(self.user_io.out)
        return error
Beispiel #25
0
 def setUp(self):
     revisions_enabled = get_env("TESTING_REVISIONS_ENABLED", False)
     self.server = TestServer([("*/*@*/*", "*")], [("*/*@*/*", "*")])
     self.client = TestClient(servers={"default": self.server})
     self.client.save({"conanfile.py": GenConanfile()})
     self.client.run("create . Pkg/0.1@user/testing")
     self.client.run("upload * --all --confirm -r default")
     # Check files are uploded in this order: conan_package.tgz, conaninfo.txt, conanmanifest.txt
     order1 = str(self.client.out).find("Uploading conan_package.tgz")
     order2 = str(self.client.out).find("Uploading conaninfo.txt", order1)
     order3 = str(self.client.out).find("Uploading conanmanifest.txt",
                                        order2)
     self.assertTrue(order1 < order2 < order3)
     rrev = "f3367e0e7d170aa12abccb175fee5f97" if revisions_enabled else "0"
     pref_str = "Pkg/0.1@user/testing#%s" % rrev
     prev = "83c38d3b4e5f1b8450434436eec31b00" if revisions_enabled else "0"
     self.pref = pref = PackageReference(ConanFileReference.loads(pref_str),
                                         NO_SETTINGS_PACKAGE_ID, prev)
     self.manifest_path = self.server.server_store.get_package_file_path(
         pref, "conanmanifest.txt")
     self.info_path = self.server.server_store.get_package_file_path(
         pref, "conaninfo.txt")
     self.tgz_path = self.server.server_store.get_package_file_path(
         pref, "conan_package.tgz")
Beispiel #26
0
    def _init_collaborators(self, user_io=None):

        output = TestBufferConanOutput()
        self.user_io = user_io or MockedUserIO(self.users, out=output)
        self.client_cache = ClientCache(self.base_folder, self.storage_folder,
                                        output)
        self.runner = TestRunner(output, runner=self.conan_runner)

        # Check if servers are real
        real_servers = False
        for server in self.servers.values():
            if isinstance(server, str):  # Just URI
                real_servers = True

        with tools.environment_append(self.client_cache.conan_config.env_vars):
            if real_servers:
                requester = requests.Session()
            else:
                if self.requester_class:
                    requester = self.requester_class(self.servers)
                else:
                    requester = TestRequester(self.servers)

            self.requester = ConanRequester(requester, self.client_cache,
                                            get_request_timeout())

            self.hook_manager = HookManager(self.client_cache.hooks_path,
                                            get_env("CONAN_HOOKS", list()),
                                            self.user_io.out)

            self.localdb, self.rest_api_client, self.remote_manager = Conan.instance_remote_manager(
                self.requester, self.client_cache, self.user_io,
                self.client_version, self.min_server_compatible_version,
                self.hook_manager)
            self.rest_api_client.block_v2 = self.block_v2
            return output, self.requester
Beispiel #27
0
class MultiRemoteTest(unittest.TestCase):
    def setUp(self):
        self.servers = OrderedDict()
        self.users = {}
        for i in range(3):
            test_server = TestServer()
            self.servers["remote%d" % i] = test_server
            self.users["remote%d" % i] = [("lasote", "mypass")]

        self.client = TestClient(servers=self.servers, users=self.users)

    def test_predefine_remote(self):
        self.client.save({"conanfile.py": GenConanfile("Hello0", "0.1")})
        self.client.run("export . lasote/stable")
        self.client.run("upload Hello0/0.1@lasote/stable -r=remote0")
        self.client.run("upload Hello0/0.1@lasote/stable -r=remote1")
        self.client.run("upload Hello0/0.1@lasote/stable -r=remote2")
        self.client.run('remove "*" -f')
        self.client.run("remote add_ref Hello0/0.1@lasote/stable remote1")
        self.client.run("install Hello0/0.1@lasote/stable --build=missing")
        self.assertIn(
            "Hello0/0.1@lasote/stable: Retrieving from predefined remote 'remote1'",
            self.client.out)
        self.client.run("remote list_ref")
        self.assertIn(": remote1", self.client.out)

    def test_upload(self):
        ref = ConanFileReference.loads("Hello0/0.1@lasote/stable")
        self.client.save({"conanfile.py": GenConanfile("Hello0", "0.1")})
        self.client.run("export . lasote/stable")
        self.client.run("upload %s" % str(ref))

        self.client.run("info %s" % str(ref))
        self.assertIn("remote0=http://", self.client.out)

        # The remote, once fixed does not change
        self.client.run("upload %s -r=remote1" % str(ref))
        self.client.run("info %s" % str(ref))
        self.assertIn("remote0=http://", self.client.out)

        # Now install it in other machine from remote 0
        client2 = TestClient(servers=self.servers, users=self.users)
        client2.run("install %s --build=missing" % str(ref))
        client2.run("info %s" % str(ref))
        self.assertIn("remote0=http://", client2.out)

        # Now install it in other machine from remote 1
        servers = self.servers.copy()
        servers.pop("remote0")
        client3 = TestClient(servers=servers, users=self.users)
        client3.run("install %s --build=missing" % str(ref))
        client3.run("info %s" % str(ref))
        self.assertIn("remote1=http://", client3.out)

    def test_fail_when_not_notfound(self):
        """
        If a remote fails with a 404 it has to keep looking in the next remote, but if it fails by
        any other reason it has to stop
        """
        servers = OrderedDict()
        servers["s0"] = TestServer()
        servers["s1"] = TestServer()
        servers["s2"] = TestServer()

        client = TestClient(servers=servers, users=self.users)
        client.save({"conanfile.py": GenConanfile("MyLib", "0.1")})
        client.run("create . lasote/testing")
        client.run("user lasote -p mypass -r s1")
        client.run("upload MyLib* -r s1 -c")

        servers[
            "s1"].fake_url = "http://asdlhaljksdhlajkshdljakhsd.com"  # Do not exist
        client2 = TestClient(servers=servers, users=self.users)
        err = client2.run("install MyLib/0.1@conan/testing --build=missing",
                          assert_error=True)
        self.assertTrue(err)
        self.assertIn("MyLib/0.1@conan/testing: Trying with 's0'...",
                      client2.out)
        self.assertIn("MyLib/0.1@conan/testing: Trying with 's1'...",
                      client2.out)
        self.assertIn(
            "Unable to connect to s1=http://asdlhaljksdhlajkshdljakhsd.com",
            client2.out)
        # s2 is not even tried
        self.assertNotIn("MyLib/0.1@conan/testing: Trying with 's2'...",
                         client2.out)

    def test_install_from_remotes(self):
        for i in range(3):
            ref = ConanFileReference.loads("Hello%d/0.1@lasote/stable" % i)
            self.client.save(
                {"conanfile.py": GenConanfile("Hello%d" % i, "0.1")})
            self.client.run("export . lasote/stable")
            self.client.run("upload %s -r=remote%d" % (str(ref), i))

            self.client.run("info %s" % str(ref))
            self.assertIn("remote%d=http://" % i, self.client.out)

        # Now install it in other machine from remote 0
        client2 = TestClient(servers=self.servers, users=self.users)

        refs = [
            "Hello0/0.1@lasote/stable", "Hello1/0.1@lasote/stable",
            "Hello2/0.1@lasote/stable"
        ]
        client2.save({
            "conanfile.py":
            GenConanfile("HelloX", "0.1").with_requires(*refs)
        })
        client2.run("install . --build=missing")
        self.assertIn("Hello0/0.1@lasote/stable from 'remote0'", client2.out)
        self.assertIn("Hello1/0.1@lasote/stable from 'remote1'", client2.out)
        self.assertIn("Hello2/0.1@lasote/stable from 'remote2'", client2.out)
        client2.run("info .")
        self.assertIn("Remote: remote0=http://", client2.out)
        self.assertIn("Remote: remote1=http://", client2.out)
        self.assertIn("Remote: remote2=http://", client2.out)

    @pytest.mark.skipif(
        get_env("TESTING_REVISIONS_ENABLED", False),
        reason=
        "This test is not valid for revisions, where we keep iterating the "
        "remotes for searching a package for the same recipe revision")
    def test_package_binary_remote(self):
        # https://github.com/conan-io/conan/issues/3882
        # Upload recipe + package to remote1 and remote2
        reference = "Hello/0.1@lasote/stable"
        self.client.save({"conanfile.py": GenConanfile()})
        self.client.run("create . %s" % reference)
        self.client.run("upload %s -r=remote0 --all" % reference)
        self.client.run("upload %s -r=remote2 --all" % reference)
        ref = ConanFileReference.loads(reference)

        # Remove only binary from remote1 and everything in local
        self.client.run("remove -f %s -p -r remote0" % reference)
        self.client.run('remove "*" -f')

        self.servers.pop("remote1")
        # Now install it from a client, it won't find the binary in remote2
        self.client.run("install %s" % reference, assert_error=True)
        self.assertIn("Can't find a 'Hello/0.1@lasote/stable' package",
                      self.client.out)
        self.assertNotIn("remote2", self.client.out)

        self.client.run("install %s -r remote2" % reference)
        self.assertIn(
            "Package installed 5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9",
            self.client.out)
        self.assertIn("Hello/0.1@lasote/stable from 'remote0' - Cache",
                      self.client.out)

        metadata = self.client.cache.package_layout(ref).load_metadata()
        self.assertEqual(metadata.recipe.remote, "remote0")
        self.assertEqual(
            metadata.packages["5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9"].
            remote, "remote2")

        client2 = TestClient(servers=self.servers, users=self.users)
        time.sleep(1)  # Make sure timestamps increase
        client2.save({"conanfile.py": str(GenConanfile()) + " # Comment"})
        client2.run("create . %s" % reference)
        client2.run("upload %s -r=remote2 --all" % reference)

        # Install from client, it should update the package from remote2
        self.client.run("install %s --update" % reference)

        self.assertNotIn(
            "Hello/0.1@lasote/stable: WARN: Can't update, no package in remote",
            self.client.out)
        self.assertIn(
            "Hello/0.1@lasote/stable:"
            "5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9 - Update",
            self.client.out)
        self.assertIn("Downloading conan_package.tgz", self.client.out)
Beispiel #28
0
class BuildOrderTest(unittest.TestCase):
    def single_consumer_test(self):
        # https://github.com/conan-io/conan/issues/5727
        client = TestClient()
        client.save({"conanfile.py": GenConanfile("test4", "0.1")})
        client.run(
            "lock create conanfile.py --build --lockfile-out=conan.lock")
        client.run("lock build-order conan.lock --json=bo.json")
        jsonbo = json.loads(client.load("bo.json"))
        self.assertEqual([], jsonbo)

    def test_base_graph(self):
        client = TestClient()
        client.save({"conanfile.py": GenConanfile("test4", "0.1")})
        client.run("lock create conanfile.py --base --lockfile-out=conan.lock")
        client.run("lock build-order conan.lock --json=bo.json",
                   assert_error=True)
        self.assertIn(
            "Lockfiles with --base do not contain profile information, "
            "cannot be used. Create a full lockfile", client.out)

    @parameterized.expand([(True, ), (False, )])
    def build_not_locked_test(self, export):
        # https://github.com/conan-io/conan/issues/5727
        client = TestClient()
        client.save({"conanfile.py": GenConanfile("test4", "0.1")})
        if export:
            client.run("export .")
            client.run(
                "lock create --reference=test4/0.1@ --lockfile-out=conan.lock")
        else:
            client.run("create .")
            client.run(
                "lock create --reference=test4/0.1@ --build=test4 --lockfile-out=conan.lock"
            )
        if client.cache.config.revisions_enabled:
            ref = "test4/0.1#f876ec9ea0f44cb7adb1588e431b391a"
            prev = "92cf292e73488c3527dab5f5ba81b947"
            build_order = [[[
                "test4/0.1@#f876ec9ea0f44cb7adb1588e431b391a",
                "5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9", "host", "1"
            ]]]
        else:
            ref = "test4/0.1"
            prev = "0"
            build_order = [[[
                "test4/0.1@", "5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9",
                "host", "1"
            ]]]
        locked = json.loads(client.load("conan.lock"))["graph_lock"]["nodes"]
        test4 = locked["1"]
        self.assertEqual(test4["ref"], ref)
        self.assertEqual(test4["package_id"],
                         "5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9")
        self.assertEqual(test4.get("prev"),
                         None)  # PREV is not defined yet, only exported
        client.run("lock build-order conan.lock --json=bo.json")
        jsonbo = json.loads(client.load("bo.json"))
        self.assertEqual(build_order, jsonbo)
        client.run(
            "install test4/0.1@ --lockfile=conan.lock --lockfile-out=conan.lock --build"
        )
        self.assertIn(
            "test4/0.1:5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9 - Build",
            client.out)
        locked = json.loads(client.load("conan.lock"))["graph_lock"]["nodes"]
        test4 = locked["1"]
        self.assertEqual(test4["ref"], ref)
        self.assertEqual(test4["package_id"],
                         "5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9")
        self.assertEqual(test4["prev"], prev)

        # New build order, nothing else to do
        client.run("lock build-order conan.lock --json=bo.json")
        jsonbo = json.loads(client.load("bo.json"))
        self.assertEqual([], jsonbo)

    def build_locked_error_test(self):
        client = TestClient()
        client.save({"conanfile.py": GenConanfile("test4", "0.1")})
        client.run("create .")
        client.run(
            "lock create --reference=test4/0.1@ --lockfile-out=conan.lock")
        locked = json.loads(client.load("conan.lock"))["graph_lock"]["nodes"]
        test4 = locked["1"]
        if client.cache.config.revisions_enabled:
            ref = "test4/0.1#f876ec9ea0f44cb7adb1588e431b391a"
            prev = "92cf292e73488c3527dab5f5ba81b947"
        else:
            ref = "test4/0.1"
            prev = "0"
        self.assertEqual(test4["ref"], ref)
        self.assertEqual(test4["package_id"],
                         "5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9")
        self.assertEqual(test4["prev"], prev)
        client.run("lock build-order conan.lock --json=bo.json")
        jsonbo = json.loads(client.load("bo.json"))
        self.assertEqual([], jsonbo)
        # if we try to build anyway, error
        client.run("install test4/0.1@ --lockfile=conan.lock --build",
                   assert_error=True)
        self.assertIn(
            "Cannot build 'test4/0.1#f876ec9ea0f44cb7adb1588e431b391a' because it is "
            "already locked in the input lockfile", client.out)

    @parameterized.expand([(True, ), (False, )])
    def transitive_build_not_locked_test(self, export):
        # https://github.com/conan-io/conan/issues/5727
        client = TestClient()
        client.save({
            "dep/conanfile.py": GenConanfile(),
            "pkg/conanfile.py": GenConanfile().with_require("dep/0.1"),
            "app/conanfile.py": GenConanfile().with_require("pkg/0.1")
        })
        if export:
            client.run("export dep dep/0.1@")
            client.run("export pkg pkg/0.1@")
            client.run("export app app/0.1@")
            client.run(
                "lock create --reference=app/0.1@ --lockfile-out=conan.lock")
        else:
            client.run("create dep dep/0.1@")
            client.run("create pkg pkg/0.1@")
            client.run("create app app/0.1@")
            client.run(
                "lock create --reference=app/0.1@ --build --lockfile-out=conan.lock"
            )

        locked = json.loads(client.load("conan.lock"))["graph_lock"]["nodes"]

        if client.cache.config.revisions_enabled:
            build_order = [[[
                "dep/0.1@#f3367e0e7d170aa12abccb175fee5f97",
                "5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9", "host", "3"
            ]],
                           [[
                               "pkg/0.1@#447b56f0334b7e2a28aa86e218c8b3bd",
                               "0b3845ce7fd8c0b4e46566097797bd872cb5bcf6",
                               "host", "2"
                           ]],
                           [[
                               "app/0.1@#5e0af887c3e9391c872773734ccd2ca0",
                               "745ccd40fd696b66b0cb160fd5251a533563bbb4",
                               "host", "1"
                           ]]]
            prev_dep = "83c38d3b4e5f1b8450434436eec31b00"
            prev_pkg = "bcde0c25612a6d296cf2cab2c264054d"
            prev_app = "9f30558ce471f676e3e06b633aabcf99"
        else:
            build_order = [[[
                "dep/0.1@", "5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9", "host",
                "3"
            ]],
                           [[
                               "pkg/0.1@",
                               "0b3845ce7fd8c0b4e46566097797bd872cb5bcf6",
                               "host", "2"
                           ]],
                           [[
                               "app/0.1@",
                               "745ccd40fd696b66b0cb160fd5251a533563bbb4",
                               "host", "1"
                           ]]]
            prev_dep = "0"
            prev_pkg = "0"
            prev_app = "0"

        for level in build_order:
            for item in level:
                ref, package_id, _, lockid = item
                ref = ref.replace("@", "")
                node = locked[lockid]
                self.assertEqual(node["ref"], ref)
                self.assertEqual(node["package_id"], package_id)
                self.assertEqual(
                    node.get("prev"),
                    None)  # PREV is not defined yet, only exported

        client.run("lock build-order conan.lock --json=bo.json")
        jsonbo = json.loads(client.load("bo.json"))
        self.assertEqual(build_order, jsonbo)

        if export:
            client.run("install app/0.1@ --lockfile=conan.lock",
                       assert_error=True)
            self.assertIn(
                "Missing prebuilt package for 'app/0.1', 'dep/0.1', 'pkg/0.1'",
                client.out)

        # Build one by one
        client.run(
            "install {0} --lockfile=conan.lock --lockfile-out=conan.lock"
            " --build={0}".format(build_order[0][0][0]))
        self.assertIn(
            "dep/0.1:5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9 - Build",
            client.out)
        locked = json.loads(client.load("conan.lock"))["graph_lock"]["nodes"]
        node = locked["3"]
        self.assertEqual(node.get("prev"), prev_dep)
        node = locked["2"]
        self.assertEqual(node.get("prev"),
                         None)  # PREV is not defined yet, only exported
        node = locked["1"]
        self.assertEqual(node.get("prev"),
                         None)  # PREV is not defined yet, only exported

        client.run("lock build-order conan.lock --json=bo.json")
        jsonbo = json.loads(client.load("bo.json"))
        self.assertEqual(build_order[1:], jsonbo)

        client.run("install pkg/0.1@ --lockfile=conan.lock --build",
                   assert_error=True)
        self.assertIn(
            "Cannot build 'dep/0.1#f3367e0e7d170aa12abccb175fee5f97' because it is "
            "already locked in the input lockfile", client.out)
        client.run(
            "install {0} --lockfile=conan.lock --lockfile-out=conan.lock "
            "--build={0}".format(build_order[1][0][0]))
        self.assertIn(
            "dep/0.1:5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9 - Cache",
            client.out)
        self.assertIn(
            "pkg/0.1:0b3845ce7fd8c0b4e46566097797bd872cb5bcf6 - Build",
            client.out)
        locked = json.loads(client.load("conan.lock"))["graph_lock"]["nodes"]
        node = locked["3"]
        self.assertEqual(node.get("prev"), prev_dep)
        node = locked["2"]
        self.assertEqual(node.get("prev"), prev_pkg)
        node = locked["1"]
        self.assertEqual(node.get("prev"),
                         None)  # PREV is not defined yet, only exported

        client.run("lock build-order conan.lock --json=bo.json")
        jsonbo = json.loads(client.load("bo.json"))
        self.assertEqual(build_order[2:], jsonbo)

        client.run("install app/0.1@ --lockfile=conan.lock --build",
                   assert_error=True)
        self.assertIn(
            "Cannot build 'dep/0.1#f3367e0e7d170aa12abccb175fee5f97' because it is "
            "already locked in the input lockfile", client.out)
        client.run(
            "install {0} --lockfile=conan.lock --lockfile-out=conan.lock "
            "--build={0}".format(build_order[2][0][0]))
        self.assertIn(
            "dep/0.1:5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9 - Cache",
            client.out)
        self.assertIn(
            "pkg/0.1:0b3845ce7fd8c0b4e46566097797bd872cb5bcf6 - Cache",
            client.out)
        self.assertIn(
            "app/0.1:745ccd40fd696b66b0cb160fd5251a533563bbb4 - Build",
            client.out)

        locked = json.loads(client.load("conan.lock"))["graph_lock"]["nodes"]
        node = locked["3"]
        self.assertEqual(node.get("prev"), prev_dep)
        node = locked["2"]
        self.assertEqual(node.get("prev"), prev_pkg)
        node = locked["1"]
        self.assertEqual(node.get("prev"), prev_app)

        # New build order, nothing else to do
        client.run("lock build-order conan.lock --json=bo.json")
        jsonbo = json.loads(client.load("bo.json"))
        self.assertEqual([], jsonbo)

    @unittest.skipUnless(get_env("TESTING_REVISIONS_ENABLED", False),
                         "Only revisions")
    def package_revision_mode_build_order_test(self):
        # https://github.com/conan-io/conan/issues/6232
        client = TestClient()
        client.run(
            "config set general.default_package_id_mode=package_revision_mode")
        client.save({"conanfile.py": GenConanfile()})
        client.run("export . libb/0.1@")
        client.run("export . libc/0.1@")
        client.save({"conanfile.py": GenConanfile().with_require("libc/0.1")})
        client.run("export . liba/0.1@")
        client.save({
            "conanfile.py":
            GenConanfile().with_require("liba/0.1").with_require("libb/0.1")
        })
        client.run("export . app/0.1@")

        client.run(
            "lock create --reference=app/0.1@ --build=missing --lockfile-out=conan.lock"
        )
        self.assertIn("app/0.1:Package_ID_unknown - Unknown", client.out)
        self.assertIn("liba/0.1:Package_ID_unknown - Unknown", client.out)
        self.assertIn(
            "libb/0.1:5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9 - Build",
            client.out)
        self.assertIn(
            "libc/0.1:5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9 - Build",
            client.out)
        lock = json.loads(client.load("conan.lock"))
        app = lock["graph_lock"]["nodes"]["1"]
        self.assertEqual(app["package_id"], "Package_ID_unknown")
        liba = lock["graph_lock"]["nodes"]["2"]
        self.assertEqual(liba["package_id"], "Package_ID_unknown")
        libc = lock["graph_lock"]["nodes"]["3"]
        self.assertEqual(libc["package_id"],
                         "5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9")
        libd = lock["graph_lock"]["nodes"]["4"]
        self.assertEqual(libd["package_id"],
                         "5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9")

        client.run("lock build-order conan.lock --json=bo.json")
        bo = client.load("bo.json")
        build_order = json.loads(bo)
        expected = [[[
            'libc/0.1@#f3367e0e7d170aa12abccb175fee5f97',
            '5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9', 'host', '3'
        ],
                     [
                         'libb/0.1@#f3367e0e7d170aa12abccb175fee5f97',
                         '5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9', 'host',
                         '4'
                     ]],
                    [[
                        'liba/0.1@#7086607aa6efbad8e2527748e3ee8237',
                        'Package_ID_unknown', 'host', '2'
                    ]],
                    [[
                        'app/0.1@#7742ee9e2f19af4f9ed7619f231ca871',
                        'Package_ID_unknown', 'host', '1'
                    ]]]
        self.assertEqual(build_order, expected)
Beispiel #29
0
def _make_files_writable(file_names):
    if not get_env("CONAN_READ_ONLY_CACHE", False):
        return

    for file_name in file_names:
        os.chmod(file_name, os.stat(file_name).st_mode | stat.S_IWRITE)
Beispiel #30
0
    pkg_b_revision = "b6f49e5ba6dd3d64af09a2f288e71330"
    pkg_b_id = "5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9"
    pkg_b_package_revision = "#33a5634bbd9ec26b369d3900d91ea9a0"
    modified_pkg_b_revision = "62a38c702f14cb9de952bb22b40d6ecc"
    modified_pkg_b_package_revision = "#b7850e289326d594fbc10088d55f5259"


class GraphLockVersionRangeInfoTest(GraphLockVersionRangeTest):
    graph_lock_command = "info . --install-folder=."


class GraphLockVersionRangeGraphLockTest(GraphLockVersionRangeTest):
    graph_lock_command = "graph lock ."


@unittest.skipUnless(get_env("TESTING_REVISIONS_ENABLED", False),
                     "Only revisions")
class GraphLockRevisionTest(unittest.TestCase):
    pkg_b_revision = "9b64caa2465f7660e6f613b7e87f0cd7"
    pkg_b_id = "5bf1ba84b5ec8663764a406f08a7f9ae5d3d5fb5"
    pkg_b_package_revision = "#2ec4fb334e1b4f3fd0a6f66605066ac7"

    def setUp(self):
        test_server = TestServer(users={"user": "******"})
        servers = {"default": test_server}
        client = TestClient(servers=servers,
                            users={"default": [("user", "user")]})
        # Important to activate revisions
        self.client = client
        client.save({
            "conanfile.py":
Beispiel #31
0
    def _cmake_cross_build_defines(self):

        os_ = self._ss("os")
        arch = self._ss("arch")
        os_ver_str = "os.api_level" if os_ == "Android" else "os.version"
        op_system_version = self._ss(os_ver_str)

        env_sn = get_env("CONAN_CMAKE_SYSTEM_NAME", "")
        env_sn = {"False": False, "True": True, "": None}.get(env_sn, env_sn)
        cmake_system_name = env_sn or self._forced_cmake_system_name

        os_build, _, _, _ = get_cross_building_settings(self._conanfile.settings)

        ret = OrderedDict()
        os_ver = get_env("CONAN_CMAKE_SYSTEM_VERSION", op_system_version)
        toolchain_file = get_env("CONAN_CMAKE_TOOLCHAIN_FILE", "")

        if toolchain_file != "":
            logger.info("Setting Cross build toolchain file: %s" % toolchain_file)
            ret["CMAKE_TOOLCHAIN_FILE"] = toolchain_file
            return ret

        if cmake_system_name is False:
            return ret

        # System name and system version
        if cmake_system_name is not True:  # String not empty
            ret["CMAKE_SYSTEM_NAME"] = cmake_system_name
        else:  # detect if we are cross building and the system name and version
            if cross_building(self._conanfile.settings):  # We are cross building
                if os_ != os_build:
                    if os_:  # the_os is the host (regular setting)
                        ret["CMAKE_SYSTEM_NAME"] = ("Darwin" if os_ in ["iOS", "tvOS", "watchOS"]
                                                    else os_)
                    else:
                        ret["CMAKE_SYSTEM_NAME"] = "Generic"
        if os_ver:
            ret["CMAKE_SYSTEM_VERSION"] = os_ver
            if str(os_) == "Macos":
                ret["CMAKE_OSX_DEPLOYMENT_TARGET"] = os_ver

        # system processor
        cmake_system_processor = os.getenv("CONAN_CMAKE_SYSTEM_PROCESSOR")
        if cmake_system_processor:
            ret["CMAKE_SYSTEM_PROCESSOR"] = cmake_system_processor

        if ret:  # If enabled cross compile
            for env_var in ["CONAN_CMAKE_FIND_ROOT_PATH",
                            "CONAN_CMAKE_FIND_ROOT_PATH_MODE_PROGRAM",
                            "CONAN_CMAKE_FIND_ROOT_PATH_MODE_LIBRARY",
                            "CONAN_CMAKE_FIND_ROOT_PATH_MODE_INCLUDE"]:

                value = os.getenv(env_var)
                if value:
                    ret[env_var] = value

            if self._conanfile and self._conanfile.deps_cpp_info.sysroot:
                sysroot_path = self._conanfile.deps_cpp_info.sysroot
            else:
                sysroot_path = os.getenv("CONAN_CMAKE_FIND_ROOT_PATH", None)

            if sysroot_path:
                # Needs to be set here, can't be managed in the cmake generator, CMake needs
                # to know about the sysroot before any other thing
                ret["CMAKE_SYSROOT"] = sysroot_path.replace("\\", "/")

            # Adjust Android stuff
            if os_ == "Android":
                arch_abi_settings = {"armv8": "arm64-v8a",
                                     "armv7": "armeabi-v7a",
                                     "armv7hf": "armeabi-v7a",
                                     "armv6": "armeabi-v6",
                                     "armv5": "armeabi"
                                     }.get(arch, arch)
                if arch_abi_settings:
                    ret["CMAKE_ANDROID_ARCH_ABI"] = arch_abi_settings

        logger.info("Setting Cross build flags: %s"
                    % ", ".join(["%s=%s" % (k, v) for k, v in ret.items()]))
        return ret
Beispiel #32
0
    def write_generators(self, conanfile, path, output):
        """ produces auxiliary files, required to build a project or a package.
        """
        for generator_name in set(conanfile.generators):
            generator_class = self._new_generator(generator_name, output)
            if generator_class:
                if generator_name == "msbuild":
                    msg = (
                        "\n*****************************************************************\n"
                        "******************************************************************\n"
                        "'msbuild' has been deprecated and moved.\n"
                        "It will be removed in next Conan release.\n"
                        "Use 'MSBuildDeps' method instead.\n"
                        "********************************************************************\n"
                        "********************************************************************\n")
                    from conans.client.output import Color
                    output.writeln(msg, front=Color.BRIGHT_RED)
                try:
                    generator = generator_class(conanfile)
                    output.highlight("Generator '{}' calling 'generate()'".format(generator_name))
                    generator.output_path = path
                    mkdir(path)
                    with chdir(path):
                        generator.generate()
                    continue
                except Exception as e:
                    raise ConanException("Error in generator '{}': {}".format(generator_name,
                                                                              str(e)))

            try:
                generator_class = self._generators[generator_name]
            except KeyError:
                available = list(self._generators.keys()) + self._new_generators
                raise ConanException("Invalid generator '%s'. Available types: %s" %
                                     (generator_name, ", ".join(available)))
            try:
                generator = generator_class(conanfile)
            except TypeError:
                # To allow old-style generator packages to work (e.g. premake)
                output.warn("Generator %s failed with new __init__(), trying old one")
                generator = generator_class(conanfile.deps_cpp_info, conanfile.cpp_info)

            try:
                generator.output_path = path
                content = generator.content
                if isinstance(content, dict):
                    if generator.filename:
                        output.warn("Generator %s is multifile. Property 'filename' not used"
                                    % (generator_name,))
                    for k, v in content.items():
                        if generator.normalize:  # To not break existing behavior, to be removed 2.0
                            v = normalize(v)
                        output.info("Generator %s created %s" % (generator_name, k))
                        save(join(path, k), v, only_if_modified=True)
                else:
                    content = normalize(content)
                    output.info("Generator %s created %s" % (generator_name, generator.filename))
                    save(join(path, generator.filename), content, only_if_modified=True)
            except Exception as e:
                if get_env("CONAN_VERBOSE_TRACEBACK", False):
                    output.error(traceback.format_exc())
                output.error("Generator %s(file:%s) failed\n%s"
                             % (generator_name, generator.filename, str(e)))
                raise ConanException(e)
Beispiel #33
0
 def logging_file(self):
     return get_env('CONAN_LOGGING_FILE', None)
Beispiel #34
0
def get_conan_runner():
    print_commands_to_output = get_env("CONAN_PRINT_RUN_COMMANDS", False)
    generate_run_log_file = get_env("CONAN_LOG_RUN_TO_FILE", False)
    log_run_to_output = get_env("CONAN_LOG_RUN_TO_OUTPUT", True)
    runner = ConanRunner(print_commands_to_output, generate_run_log_file, log_run_to_output)
    return runner
Beispiel #35
0
import logging
from logging import StreamHandler
import sys
from conans.util.env_reader import get_env

# #### LOGGER, MOVED FROM CONF BECAUSE OF MULTIPLE PROBLEM WITH CIRCULAR INCLUDES #####
CONAN_LOGGING_LEVEL = get_env('CONAN_LOGGING_LEVEL', logging.CRITICAL)
CONAN_LOGGING_FILE = get_env('CONAN_LOGGING_FILE', None)  # None is stdout


class MultiLineFormatter(logging.Formatter):
    def format(self, record):
        str_ = logging.Formatter.format(self, record)
        separator = record.message if record.message else None
        if separator is None:
            return separator
        tmp = str_.split(separator)
        if len(tmp) == 2:
            header, _ = tmp
        else:
            header = tmp
        str_ = str_.replace('\n', '\n' + ' ' * len(header))
        return str_

logger = logging.getLogger('conans')
if CONAN_LOGGING_FILE is not None:
    hdlr = logging.FileHandler(CONAN_LOGGING_FILE)
else:
    hdlr = StreamHandler(sys.stderr)

formatter = MultiLineFormatter('%(levelname)-6s:%(filename)-15s[%(lineno)d]: '
Beispiel #36
0
    GREEN = Fore.GREEN  # @UndefinedVariable
    MAGENTA = Fore.MAGENTA  # @UndefinedVariable
    BLUE = Fore.BLUE  # @UndefinedVariable
    YELLOW = Fore.YELLOW  # @UndefinedVariable
    BLACK = Fore.BLACK  # @UndefinedVariable

    BRIGHT_RED = Style.BRIGHT + Fore.RED  # @UndefinedVariable
    BRIGHT_BLUE = Style.BRIGHT + Fore.BLUE  # @UndefinedVariable
    BRIGHT_YELLOW = Style.BRIGHT + Fore.YELLOW  # @UndefinedVariable
    BRIGHT_GREEN = Style.BRIGHT + Fore.GREEN  # @UndefinedVariable
    BRIGHT_CYAN = Style.BRIGHT + Fore.CYAN   # @UndefinedVariable
    BRIGHT_WHITE = Style.BRIGHT + Fore.WHITE   # @UndefinedVariable
    BRIGHT_MAGENTA = Style.BRIGHT + Fore.MAGENTA   # @UndefinedVariable


if get_env("CONAN_COLOR_DARK", 0):
    Color.WHITE = Fore.BLACK
    Color.CYAN = Fore.BLUE
    Color.YELLOW = Fore.MAGENTA
    Color.BRIGHT_WHITE = Fore.BLACK
    Color.BRIGHT_CYAN = Fore.BLUE
    Color.BRIGHT_YELLOW = Fore.MAGENTA
    Color.BRIGHT_GREEN = Fore.GREEN


class ConanOutput(object):
    """ wraps an output stream, so it can be pretty colored,
    and auxiliary info, success, warn methods for convenience.
    """

    def __init__(self, stream, color=False):
Beispiel #37
0
import logging
from logging import StreamHandler
import sys
from conans.util.env_reader import get_env

# #### LOGGER, MOVED FROM CONF BECAUSE OF MULTIPLE PROBLEM WITH CIRCULAR INCLUDES #####
CONAN_LOGGING_LEVEL = get_env("CONAN_LOGGING_LEVEL", logging.CRITICAL)
CONAN_LOGGING_FILE = get_env("CONAN_LOGGING_FILE", None)  # None is stdout


class MultiLineFormatter(logging.Formatter):
    def format(self, record):
        str_ = logging.Formatter.format(self, record)
        separator = record.message if record.message else None
        if separator is None:
            return separator
        tmp = str_.split(separator)
        if len(tmp) == 2:
            header, _ = tmp
        else:
            header = tmp
        str_ = str_.replace("\n", "\n" + " " * len(header))
        return str_


logger = logging.getLogger("conans")
if CONAN_LOGGING_FILE is not None:
    hdlr = logging.FileHandler(CONAN_LOGGING_FILE)
else:
    hdlr = StreamHandler(sys.stderr)
Beispiel #38
0
    def get_command(self, project_file, props_file_path=None, targets=None, upgrade_project=True,
                    build_type=None, arch=None, parallel=True, toolset=None, platforms=None,
                    use_env=False):

        targets = targets or []
        command = []

        if upgrade_project and not get_env("CONAN_SKIP_VS_PROJECTS_UPGRADE", False):
            command.append("devenv %s /upgrade &&" % project_file)
        else:
            self._output.info("Skipped sln project upgrade")

        build_type = build_type or self._settings.get_safe("build_type")
        arch = arch or self._settings.get_safe("arch")
        if not build_type:
            raise ConanException("Cannot build_sln_command, build_type not defined")
        if not arch:
            raise ConanException("Cannot build_sln_command, arch not defined")

        command.append("msbuild %s /p:Configuration=%s" % (project_file, build_type))
        msvc_arch = {'x86': 'x86',
                     'x86_64': 'x64',
                     'armv7': 'ARM',
                     'armv8': 'ARM64'}
        if platforms:
            msvc_arch.update(platforms)
        msvc_arch = msvc_arch.get(str(arch))
        try:
            sln = tools.load(project_file)
            pattern = re.compile(r"GlobalSection\(SolutionConfigurationPlatforms\)"
                                 r"(.*?)EndGlobalSection", re.DOTALL)
            solution_global = pattern.search(sln).group(1)
            lines = solution_global.splitlines()
            lines = [s.split("=")[0].strip() for s in lines]
        except Exception:
            pass
        else:
            config = "%s|%s" % (build_type, msvc_arch)
            if config not in "".join(lines):
                self._output.warn("***** The configuration %s does not exist in this solution *****" % config)
                self._output.warn("Use 'platforms' argument to define your architectures")

        if use_env:
            command.append('/p:UseEnv=true')

        if msvc_arch:
            command.append('/p:Platform="%s"' % msvc_arch)

        if parallel:
            command.append('/m:%s' % cpu_count())

        if targets:
            command.append("/target:%s" % ";".join(targets))

        if toolset:
            command.append("/p:PlatformToolset=%s" % toolset)

        if props_file_path:
            command.append('/p:ForceImportBeforeCppTargets="%s"' % props_file_path)

        return " ".join(command)
Beispiel #39
0
 def cache_no_locks(self):
     try:
         return get_env("CONAN_CACHE_NO_LOCKS", False)
     except ConanException:
         return False
Beispiel #40
0
    def _cmake_cross_build_defines(self, the_os, os_ver):
        ret = OrderedDict()
        os_ver = get_env("CONAN_CMAKE_SYSTEM_VERSION", os_ver)
        toolchain_file = get_env("CONAN_CMAKE_TOOLCHAIN_FILE", "")

        if toolchain_file != "":
            logger.info("Setting Cross build toolchain file: %s" % toolchain_file)
            ret["CMAKE_TOOLCHAIN_FILE"] = toolchain_file
            return ret

        if self._cmake_system_name is False:
            return ret

        if self._cmake_system_name is not True:  # String not empty
            ret["CMAKE_SYSTEM_NAME"] = self._cmake_system_name
            ret["CMAKE_SYSTEM_VERSION"] = os_ver
        else:  # detect if we are cross building and the system name and version
            platform_os = {"Darwin": "Macos"}.get(platform.system(), platform.system())
            if (platform_os != the_os) or os_ver:  # We are cross building
                if the_os:
                    ret["CMAKE_SYSTEM_NAME"] = the_os
                    if os_ver:
                        ret["CMAKE_SYSTEM_VERSION"] = os_ver
                else:
                    ret["CMAKE_SYSTEM_NAME"] = "Generic"

        if ret:  # If enabled cross compile
            for env_var in ["CONAN_CMAKE_SYSTEM_PROCESSOR",
                            "CONAN_CMAKE_FIND_ROOT_PATH",
                            "CONAN_CMAKE_FIND_ROOT_PATH_MODE_PROGRAM",
                            "CONAN_CMAKE_FIND_ROOT_PATH_MODE_LIBRARY",
                            "CONAN_CMAKE_FIND_ROOT_PATH_MODE_INCLUDE"]:

                value = os.getenv(env_var, None)
                if value:
                    ret[env_var] = value

            if self._conanfile and self._conanfile.deps_cpp_info.sysroot:
                sysroot_path = self._conanfile.deps_cpp_info.sysroot
            else:
                sysroot_path = os.getenv("CONAN_CMAKE_FIND_ROOT_PATH", None)

            if sysroot_path:
                # Needs to be set here, can't be managed in the cmake generator, CMake needs
                # to know about the sysroot before any other thing
                ret["CMAKE_SYSROOT"] = sysroot_path.replace("\\", "/")

            # Adjust Android stuff
            if self._os == "Android":
                arch_abi_settings = {"armv8": "arm64-v8a",
                                     "armv7": "armeabi-v7a",
                                     "armv7hf": "armeabi-v7a",
                                     "armv6": "armeabi-v6",
                                     "armv5": "armeabi"
                                     }.get(self._arch,
                                           self._arch)
                if arch_abi_settings:
                    ret["CMAKE_ANDROID_ARCH_ABI"] = arch_abi_settings

        logger.info("Setting Cross build flags: %s"
                    % ", ".join(["%s=%s" % (k, v) for k, v in ret.items()]))
        return ret
Beispiel #41
0
def get_conan_runner():
    print_commands_to_output = get_env("CONAN_PRINT_RUN_COMMANDS", False)
    generate_run_log_file = get_env("CONAN_LOG_RUN_TO_FILE", False)
    log_run_to_output = get_env("CONAN_LOG_RUN_TO_OUTPUT", True)
    runner = ConanRunner(print_commands_to_output, generate_run_log_file, log_run_to_output)
    return runner
Beispiel #42
0
def _get_env_cmake_system_name():
    env_system_name = get_env("CONAN_CMAKE_SYSTEM_NAME", "")
    return {"False": False, "True": True, "": None}.get(env_system_name, env_system_name)
Beispiel #43
0
        info_lock = client.load("conan.lock")
        self.assertEqual(lockfile, info_lock)

    def test_reproducible_lockfile_txt(self):
        client = TestClient()
        client.save({"conanfile.txt": ""})
        client.run("install .")
        lockfile = client.load("conan.lock")
        client.run("install .")
        lockfile2 = client.load("conan.lock")
        self.assertEqual(lockfile, lockfile2)
        # check that the path to local conanfile.txt is relative, reproducible in other machine
        self.assertIn('"path": "conanfile.txt"', lockfile)


@pytest.mark.skipif(not get_env("TESTING_REVISIONS_ENABLED", False), reason="Only revisions")
class GraphLockRevisionTest(unittest.TestCase):
    rrev_b = "9b64caa2465f7660e6f613b7e87f0cd7"
    pkg_b_id = "5bf1ba84b5ec8663764a406f08a7f9ae5d3d5fb5"
    prev_b = "2ec4fb334e1b4f3fd0a6f66605066ac7"

    def setUp(self):
        client = TestClient(default_server_user=True)
        # Important to activate revisions
        self.client = client
        client.save({"conanfile.py": GenConanfile("PkgA", "0.1")})
        client.run("create . PkgA/0.1@user/channel")
        client.run("upload PkgA/0.1@user/channel --all")

        consumer = textwrap.dedent("""
            from conans import ConanFile
Beispiel #44
0
def _make_files_writable(file_names):
    if not get_env("CONAN_READ_ONLY_CACHE", False):
        return

    for file_name in file_names:
        os.chmod(file_name, os.stat(file_name).st_mode | stat.S_IWRITE)
Beispiel #45
0
    def _cmake_cross_build_defines(self, cmake_version):
        os_ = self._ss("os")
        arch = self._ss("arch")
        os_ver_str = "os.api_level" if os_ == "Android" else "os.version"
        op_system_version = self._ss(os_ver_str)

        env_sn = get_env("CONAN_CMAKE_SYSTEM_NAME", "")
        env_sn = {"False": False, "True": True, "": None}.get(env_sn, env_sn)
        cmake_system_name = env_sn or self._forced_cmake_system_name

        os_build, _, _, _ = get_cross_building_settings(self._conanfile)
        compiler = self._ss("compiler")
        libcxx = self._ss("compiler.libcxx")

        definitions = OrderedDict()
        os_ver = get_env("CONAN_CMAKE_SYSTEM_VERSION", op_system_version)
        toolchain_file = get_env("CONAN_CMAKE_TOOLCHAIN_FILE", "")

        if toolchain_file != "":
            logger.info("Setting Cross build toolchain file: %s" % toolchain_file)
            definitions["CMAKE_TOOLCHAIN_FILE"] = toolchain_file
            return definitions

        if cmake_system_name is False:
            return definitions

        # System name and system version
        if cmake_system_name is not True:  # String not empty
            definitions["CMAKE_SYSTEM_NAME"] = cmake_system_name
        else:  # detect if we are cross building and the system name and version
            skip_x64_x86 = os_ in ['Windows', 'Linux']
            if cross_building(self._conanfile, skip_x64_x86=skip_x64_x86):  # We are cross building
                apple_system_name = "Darwin" if Version(cmake_version) < Version("3.14") else None
                cmake_system_name_map = {"Macos": "Darwin",
                                         "iOS": apple_system_name or "iOS",
                                         "tvOS": apple_system_name or "tvOS",
                                         "watchOS": apple_system_name or "watchOS",
                                         "Neutrino": "QNX",
                                         "": "Generic",
                                         None: "Generic"}
                definitions["CMAKE_SYSTEM_NAME"] = cmake_system_name_map.get(os_, os_)

        if os_ver:
            definitions["CMAKE_SYSTEM_VERSION"] = os_ver
            if is_apple_os(os_):
                definitions["CMAKE_OSX_DEPLOYMENT_TARGET"] = os_ver

        # system processor
        cmake_system_processor = os.getenv("CONAN_CMAKE_SYSTEM_PROCESSOR")
        if cmake_system_processor:
            definitions["CMAKE_SYSTEM_PROCESSOR"] = cmake_system_processor

        if definitions:  # If enabled cross compile
            for env_var in ["CONAN_CMAKE_FIND_ROOT_PATH",
                            "CONAN_CMAKE_FIND_ROOT_PATH_MODE_PROGRAM",
                            "CONAN_CMAKE_FIND_ROOT_PATH_MODE_LIBRARY",
                            "CONAN_CMAKE_FIND_ROOT_PATH_MODE_INCLUDE"]:

                value = os.getenv(env_var)
                if value:
                    definitions[env_var] = value

            if self._conanfile and self._conanfile.deps_cpp_info.sysroot:
                sysroot_path = self._conanfile.deps_cpp_info.sysroot
            else:
                sysroot_path = os.getenv("CONAN_CMAKE_FIND_ROOT_PATH", None)

            if sysroot_path:
                # Needs to be set here, can't be managed in the cmake generator, CMake needs
                # to know about the sysroot before any other thing
                definitions["CMAKE_SYSROOT"] = sysroot_path.replace("\\", "/")

            # Adjust Android stuff
            if str(os_) == "Android" and definitions["CMAKE_SYSTEM_NAME"] == "Android":
                arch_abi_settings = tools.to_android_abi(arch)
                if arch_abi_settings:
                    definitions["CMAKE_ANDROID_ARCH_ABI"] = arch_abi_settings
                    definitions["ANDROID_ABI"] = arch_abi_settings

                conan_cmake_android_ndk = os.getenv("CONAN_CMAKE_ANDROID_NDK")
                if conan_cmake_android_ndk:
                    definitions["ANDROID_NDK"] = conan_cmake_android_ndk

                definitions["ANDROID_PLATFORM"] = "android-%s" % op_system_version
                definitions["ANDROID_TOOLCHAIN"] = compiler

                # More details about supported stdc++ libraries here:
                # https://developer.android.com/ndk/guides/cpp-support.html
                if libcxx:
                    definitions["ANDROID_STL"] = libcxx
                else:
                    definitions["ANDROID_STL"] = 'none'

        logger.info("Setting Cross build flags: %s"
                    % ", ".join(["%s=%s" % (k, v) for k, v in definitions.items()]))
        return definitions
Beispiel #46
0
    def latest_package(self, pref):
        if not pref.ref.revision:
            raise Exception(
                "Pass a pref with .rev.revision (Testing framework)")
        prev = self.test_server.server_store.get_last_package_revision(pref)
        return pref.copy_with_revs(pref.ref.revision, prev)

    def package_revision_time(self, pref):
        if not pref:
            raise Exception("Pass a pref with revision (Testing framework)")
        tmp = self.test_server.server_store.get_package_revision_time(pref)
        return tmp


if get_env("CONAN_TEST_WITH_ARTIFACTORY", False):
    TestServer = ArtifactoryServer


def _copy_cache_folder(target_folder):
    # Some variables affect to cache population (take a different default folder)
    vars_ = [CONAN_V2_MODE_ENVVAR, 'CC', 'CXX', 'PATH']
    cache_key = hash('|'.join(
        map(str, [os.environ.get(it, None) for it in vars_])))
    master_folder = _copy_cache_folder.master.setdefault(
        cache_key, temp_folder(create_dir=False))
    if not os.path.exists(master_folder):
        # Create and populate the cache folder with the defaults
        cache = ClientCache(master_folder, TestBufferConanOutput())
        cache.initialize_config()
        cache.registry.initialize_remotes()
Beispiel #47
0
    def get_command(self,
                    project_file,
                    props_file_path=None,
                    targets=None,
                    upgrade_project=True,
                    build_type=None,
                    arch=None,
                    parallel=True,
                    toolset=None,
                    platforms=None,
                    use_env=False,
                    properties=None):

        targets = targets or []
        properties = properties or {}
        command = []

        if upgrade_project and not get_env("CONAN_SKIP_VS_PROJECTS_UPGRADE",
                                           False):
            command.append('devenv "%s" /upgrade &&' % project_file)
        else:
            self._output.info("Skipped sln project upgrade")

        build_type = build_type or self._settings.get_safe("build_type")
        arch = arch or self._settings.get_safe("arch")
        if not build_type:
            raise ConanException(
                "Cannot build_sln_command, build_type not defined")
        if not arch:
            raise ConanException("Cannot build_sln_command, arch not defined")

        command.append('msbuild "%s" /p:Configuration="%s"' %
                       (project_file, build_type))
        msvc_arch = {
            'x86': 'x86',
            'x86_64': 'x64',
            'armv7': 'ARM',
            'armv8': 'ARM64'
        }
        if platforms:
            msvc_arch.update(platforms)
        msvc_arch = msvc_arch.get(str(arch))
        try:
            sln = tools.load(project_file)
            pattern = re.compile(
                r"GlobalSection\(SolutionConfigurationPlatforms\)"
                r"(.*?)EndGlobalSection", re.DOTALL)
            solution_global = pattern.search(sln).group(1)
            lines = solution_global.splitlines()
            lines = [s.split("=")[0].strip() for s in lines]
        except Exception:
            pass
        else:
            config = "%s|%s" % (build_type, msvc_arch)
            if config not in "".join(lines):
                self._output.warn(
                    "***** The configuration %s does not exist in this solution *****"
                    % config)
                self._output.warn(
                    "Use 'platforms' argument to define your architectures")

        if use_env:
            command.append('/p:UseEnv=true')

        if msvc_arch:
            command.append('/p:Platform="%s"' % msvc_arch)

        if parallel:
            command.append('/m:%s' % cpu_count())

        if targets:
            command.append("/target:%s" % ";".join(targets))

        if toolset:
            command.append('/p:PlatformToolset="%s"' % toolset)

        if props_file_path:
            command.append('/p:ForceImportBeforeCppTargets="%s"' %
                           props_file_path)

        for name, value in properties.items():
            command.append('/p:%s="%s"' % (name, value))

        return " ".join(command)
Beispiel #48
0
    def _cmake_cross_build_defines(self):

        ret = OrderedDict()
        os_ver = get_env("CONAN_CMAKE_SYSTEM_VERSION", self._op_system_version)
        toolchain_file = get_env("CONAN_CMAKE_TOOLCHAIN_FILE", "")

        if toolchain_file != "":
            logger.info("Setting Cross build toolchain file: %s" % toolchain_file)
            ret["CMAKE_TOOLCHAIN_FILE"] = toolchain_file
            return ret

        if self._cmake_system_name is False:
            return ret

        # System name and system version
        if self._cmake_system_name is not True:  # String not empty
            ret["CMAKE_SYSTEM_NAME"] = self._cmake_system_name
            ret["CMAKE_SYSTEM_VERSION"] = os_ver
        else:  # detect if we are cross building and the system name and version
            if cross_building(self._conanfile.settings):  # We are cross building
                if self._os != self._os_build:
                    if self._os:  # the_os is the host (regular setting)
                        ret["CMAKE_SYSTEM_NAME"] = "Darwin" if self._os in ["iOS", "tvOS",
                                                                            "watchOS"] else self._os
                        if os_ver:
                            ret["CMAKE_SYSTEM_VERSION"] = os_ver
                    else:
                        ret["CMAKE_SYSTEM_NAME"] = "Generic"

        # system processor
        cmake_system_processor = os.getenv("CONAN_CMAKE_SYSTEM_PROCESSOR", None)
        if cmake_system_processor:
            ret["CMAKE_SYSTEM_PROCESSOR"] = cmake_system_processor

        if ret:  # If enabled cross compile
            for env_var in ["CONAN_CMAKE_FIND_ROOT_PATH",
                            "CONAN_CMAKE_FIND_ROOT_PATH_MODE_PROGRAM",
                            "CONAN_CMAKE_FIND_ROOT_PATH_MODE_LIBRARY",
                            "CONAN_CMAKE_FIND_ROOT_PATH_MODE_INCLUDE"]:

                value = os.getenv(env_var, None)
                if value:
                    ret[env_var] = value

            if self._conanfile and self._conanfile.deps_cpp_info.sysroot:
                sysroot_path = self._conanfile.deps_cpp_info.sysroot
            else:
                sysroot_path = os.getenv("CONAN_CMAKE_FIND_ROOT_PATH", None)

            if sysroot_path:
                # Needs to be set here, can't be managed in the cmake generator, CMake needs
                # to know about the sysroot before any other thing
                ret["CMAKE_SYSROOT"] = sysroot_path.replace("\\", "/")

            # Adjust Android stuff
            if self._os == "Android":
                arch_abi_settings = {"armv8": "arm64-v8a",
                                     "armv7": "armeabi-v7a",
                                     "armv7hf": "armeabi-v7a",
                                     "armv6": "armeabi-v6",
                                     "armv5": "armeabi"
                                     }.get(self._arch,
                                           self._arch)
                if arch_abi_settings:
                    ret["CMAKE_ANDROID_ARCH_ABI"] = arch_abi_settings

        logger.info("Setting Cross build flags: %s"
                    % ", ".join(["%s=%s" % (k, v) for k, v in ret.items()]))
        return ret
Beispiel #49
0
def path_shortener(path, short_paths):
    """ short_paths is 4-state:
    False: Never shorten the path
    True: Always shorten the path, create link if not existing
    None: Use shorten path only if already exists, not create
    """
    use_always_short_paths = get_env("CONAN_USE_ALWAYS_SHORT_PATHS", False)
    short_paths = use_always_short_paths or short_paths

    if short_paths is False or os.getenv("CONAN_USER_HOME_SHORT") == "None":
        return path
    link = os.path.join(path, CONAN_LINK)
    if os.path.exists(link):
        return load(link)
    elif short_paths is None:
        return path

    if os.path.exists(path):
        rmdir(path)

    short_home = os.getenv("CONAN_USER_HOME_SHORT")
    if not short_home:
        if OSInfo().is_cygwin:
            try:
                cmd = ['cygpath', path, '--unix']
                out, _ = subprocess.Popen(cmd,
                                          stdout=subprocess.PIPE,
                                          shell=False).communicate()
                out = decode_text(out)
                if out.startswith('/cygdrive/'):  # It was a Windows 'path'
                    _, _, drive, _ = out.split('/', 3)
                    short_home = os.path.join('/cygdrive', drive, '.conan')
                else:  # It was a cygwin path, use a path inside the user home
                    short_home = os.path.join(os.path.expanduser("~"),
                                              '.conan_short')
            except Exception:
                raise ConanException(
                    "Conan failed to create the short_paths home for path '{}'"
                    " in Cygwin. Please report this issue. You can use environment"
                    " variable 'CONAN_USER_HOME_SHORT' to set the short_paths"
                    " home.".format(path))
        else:
            drive = os.path.splitdrive(path)[0]
            short_home = os.path.join(drive, os.sep, ".conan")
    mkdir(short_home)

    # Workaround for short_home living in NTFS file systems. Give full control permission
    # to current user to avoid
    # access problems in cygwin/msys2 windows subsystems when using short_home folder
    try:
        userdomain, username = os.getenv("USERDOMAIN"), os.environ["USERNAME"]
        domainname = "%s\%s" % (userdomain,
                                username) if userdomain else username
        cmd = r'cacls %s /E /G "%s":F' % (short_home, domainname)
        subprocess.check_output(
            cmd,
            stderr=subprocess.STDOUT)  # Ignoring any returned output, quiet
    except (subprocess.CalledProcessError, EnvironmentError):
        # cmd can fail if trying to set ACL in non NTFS drives, ignoring it.
        pass

    redirect = hashed_redirect(short_home, path)
    if not redirect:
        logger.warning("Failed to create a deterministic short path in %s",
                       short_home)
        redirect = tempfile.mkdtemp(dir=short_home, prefix="")

    # Save the full path of the local cache directory where the redirect is from.
    # This file is for debugging purposes and not used by Conan.
    save(os.path.join(redirect, CONAN_REAL_PATH), path)

    # This "1" is the way to have a non-existing directory, so commands like
    # shutil.copytree() to it, works. It can be removed without compromising the
    # temp folder generator and conan-links consistency
    redirect = os.path.join(redirect, "1")
    save(link, redirect)
    return redirect
Beispiel #50
0
    def get_command(self, project_file, props_file_path=None, targets=None, upgrade_project=True,
                    build_type=None, arch=None, parallel=True, toolset=None, platforms=None,
                    use_env=False, properties=None, output_binary_log=None, verbosity=None):

        targets = targets or []
        properties = properties or {}
        command = []

        if upgrade_project and not get_env("CONAN_SKIP_VS_PROJECTS_UPGRADE", False):
            command.append('devenv "%s" /upgrade &&' % project_file)
        else:
            self._output.info("Skipped sln project upgrade")

        build_type = build_type or self._settings.get_safe("build_type")
        arch = arch or self._settings.get_safe("arch")
        toolset = toolset or tools.msvs_toolset(self._settings)
        verbosity = os.getenv("CONAN_MSBUILD_VERBOSITY") or verbosity or "minimal"
        if not build_type:
            raise ConanException("Cannot build_sln_command, build_type not defined")
        if not arch:
            raise ConanException("Cannot build_sln_command, arch not defined")

        command.append('msbuild "%s" /p:Configuration="%s"' % (project_file, build_type))
        msvc_arch = {'x86': 'x86',
                     'x86_64': 'x64',
                     'armv7': 'ARM',
                     'armv8': 'ARM64'}
        if platforms:
            msvc_arch.update(platforms)
        msvc_arch = msvc_arch.get(str(arch))
        try:
            sln = tools.load(project_file)
            pattern = re.compile(r"GlobalSection\(SolutionConfigurationPlatforms\)"
                                 r"(.*?)EndGlobalSection", re.DOTALL)
            solution_global = pattern.search(sln).group(1)
            lines = solution_global.splitlines()
            lines = [s.split("=")[0].strip() for s in lines]
        except Exception:
            pass  # TODO: !!! what are we catching here? tools.load? .group(1)? .splitlines?
        else:
            config = "%s|%s" % (build_type, msvc_arch)
            if config not in "".join(lines):
                self._output.warn("***** The configuration %s does not exist in this solution *****"
                                  % config)
                self._output.warn("Use 'platforms' argument to define your architectures")

        if output_binary_log:
            msbuild_version = MSBuild.get_version(self._settings)
            if msbuild_version >= "15.3":  # http://msbuildlog.com/
                command.append('/bl' if isinstance(output_binary_log, bool)
                               else '/bl:"%s"' % output_binary_log)
            else:
                raise ConanException("MSBuild version detected (%s) does not support "
                                     "'output_binary_log' ('/bl')" % msbuild_version)

        if use_env:
            command.append('/p:UseEnv=true')

        if msvc_arch:
            command.append('/p:Platform="%s"' % msvc_arch)

        if parallel:
            command.append('/m:%s' % cpu_count(output=self._output))

        if targets:
            command.append("/target:%s" % ";".join(targets))

        if toolset:
            command.append('/p:PlatformToolset="%s"' % toolset)

        if verbosity:
            command.append('/verbosity:%s' % verbosity)

        if props_file_path:
            command.append('/p:ForceImportBeforeCppTargets="%s"' % props_file_path)

        for name, value in properties.items():
            command.append('/p:%s="%s"' % (name, value))

        return " ".join(command)
Beispiel #51
0
 def __init__(self, base_folder, storage_folder=None, environment=os.environ):
     ConfigParser.__init__(self)
     self.conan_folder = os.path.join(base_folder, '.conan_server')
     self.config_filename = os.path.join(self.conan_folder, 'server.conf')
     self._loaded = False
     self.env_config = {"updown_secret": get_env("CONAN_UPDOWN_SECRET", None, environment),
                        "store_adapter": get_env("CONAN_STORE_ADAPTER", None, environment),
                        "authorize_timeout": get_env("CONAN_AUTHORIZE_TIMEOUT", None, environment),
                        "disk_storage_path": get_env("CONAN_STORAGE_PATH", storage_folder, environment),
                        "jwt_secret": get_env("CONAN_JWT_SECRET", None, environment),
                        "jwt_expire_minutes": get_env("CONAN_JWT_EXPIRE_MINUTES", None, environment),
                        "write_permissions": [],
                        "read_permissions": [],
                        "ssl_enabled": get_env("CONAN_SSL_ENABLED", None, environment),
                        "port": get_env("CONAN_SERVER_PORT", None, environment),
                        "public_port": get_env("CONAN_SERVER_PUBLIC_PORT", None, environment),
                        "host_name": get_env("CONAN_HOST_NAME", None, environment),
                        # "user:pass,user2:pass2"
                        "users": get_env("CONAN_SERVER_USERS", None, environment)}
Beispiel #52
0
    def _upload(self, conan_file, conan_ref, packages_ids, retry, retry_wait,
                integrity_check, policy, remote_name, recorder):
        """Uploads the recipes and binaries identified by conan_ref"""

        default_remote = self._registry.remotes.default
        cur_recipe_remote = self._registry.refs.get(conan_ref)
        if remote_name:  # If remote_name is given, use it
            recipe_remote = self._registry.remotes.get(remote_name)
        else:
            recipe_remote = cur_recipe_remote or default_remote

        conanfile_path = self._client_cache.conanfile(conan_ref)
        # FIXME: I think it makes no sense to specify a remote to "pre_upload"
        # FIXME: because the recipe can have one and the package a different one
        self._hook_manager.execute("pre_upload",
                                   conanfile_path=conanfile_path,
                                   reference=conan_ref,
                                   remote=recipe_remote)

        if policy != UPLOAD_POLICY_FORCE:
            remote_manifest = self._check_recipe_date(conan_ref, recipe_remote)
        else:
            remote_manifest = None

        self._user_io.out.info("Uploading %s to remote '%s'" %
                               (str(conan_ref), recipe_remote.name))

        metadata = self._client_cache.load_metadata(conan_ref)
        ref = conan_ref.copy_with_rev(metadata.recipe.revision)
        self._upload_recipe(ref, retry, retry_wait, policy, recipe_remote,
                            remote_manifest)

        recorder.add_recipe(ref, recipe_remote.name, recipe_remote.url)
        if packages_ids:
            # Filter packages that don't match the recipe revision
            revisions_enabled = get_env("CONAN_CLIENT_REVISIONS_ENABLED",
                                        False)
            if revisions_enabled and ref.revision:
                recipe_package_ids = []
                for package_id in packages_ids:
                    rec_rev = metadata.packages[package_id].recipe_revision
                    if ref.revision != rec_rev:
                        self._user_io.out.warn(
                            "Skipping package '%s', it doesn't belong to "
                            "the current recipe revision" % package_id)
                    else:
                        recipe_package_ids.append(package_id)
                packages_ids = recipe_package_ids

            # Can't use build_policy_always here because it's not loaded (only load_class)
            if conan_file.build_policy == "always":
                raise ConanException("Conanfile has build_policy='always', "
                                     "no packages can be uploaded")
            total = len(packages_ids)
            for index, package_id in enumerate(packages_ids):
                pref = PackageReference(ref, package_id)
                p_remote = recipe_remote
                self._upload_package(pref, metadata, index + 1, total, retry,
                                     retry_wait, integrity_check, policy,
                                     p_remote)
                recorder.add_package(pref, p_remote.name, p_remote.url)

        # FIXME: I think it makes no sense to specify a remote to "post_upload"
        # FIXME: because the recipe can have one and the package a different one
        self._hook_manager.execute("post_upload",
                                   conanfile_path=conanfile_path,
                                   reference=ref,
                                   remote=recipe_remote)
Beispiel #53
0
def vs_installation_path(version, preference=None):

    vs_installation_path = None

    if not preference:
        env_prefs = get_env("CONAN_VS_INSTALLATION_PREFERENCE", list())

        if env_prefs:
            preference = env_prefs
        else:  # default values
            preference = [
                "Enterprise", "Professional", "Community", "BuildTools"
            ]

    # Try with vswhere()
    try:
        legacy_products = vswhere(legacy=True)
        all_products = vswhere(products=["*"])
        products = legacy_products + all_products
    except ConanException:
        products = None

    vs_paths = []

    if products:
        # remove repeated products
        seen_products = []
        for product in products:
            if product not in seen_products:
                seen_products.append(product)

        # Append products with "productId" by order of preference
        for product_type in preference:
            for product in seen_products:
                product = dict(product)
                if (product["installationVersion"].startswith(
                    ("%d." % int(version))) and "productId" in product):
                    if product_type in product["productId"]:
                        vs_paths.append(product["installationPath"])

        # Append products without "productId" (Legacy installations)
        for product in seen_products:
            product = dict(product)
            if (product["installationVersion"].startswith(
                ("%d." % int(version))) and "productId" not in product):
                vs_paths.append(product["installationPath"])

    # If vswhere does not find anything or not available, try with vs_comntools()
    if not vs_paths:
        vs_path = vs_comntools(version)

        if vs_path:
            sub_path_to_remove = os.path.join("", "Common7", "Tools", "")
            # Remove '\\Common7\\Tools\\' to get same output as vswhere
            if vs_path.endswith(sub_path_to_remove):
                vs_path = vs_path[:-(len(sub_path_to_remove) + 1)]

        vs_installation_path = vs_path
    else:
        vs_installation_path = vs_paths[0]

    return vs_installation_path
Beispiel #54
0
class UploadTest(unittest.TestCase):
    def test_upload_dirty(self):
        client = TestClient(default_server_user=True)
        client.save({"conanfile.py": GenConanfile("Hello", "0.1")})
        client.run("create . lasote/testing")
        ref = ConanFileReference.loads("Hello/0.1@lasote/testing")
        pref = PackageReference(ref, NO_SETTINGS_PACKAGE_ID)
        layout = client.cache.package_layout(pref.ref)
        pkg_folder = os.path.join(layout.base_folder(), PACKAGES_FOLDER,
                                  pref.id)
        set_dirty(pkg_folder)

        client.run("upload * --all --confirm", assert_error=True)
        self.assertIn(
            "ERROR: Hello/0.1@lasote/testing:5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9: "
            "Upload package to 'default' failed: Package %s is corrupted, aborting upload"
            % str(pref), client.out)
        self.assertIn(
            "Remove it with 'conan remove Hello/0.1@lasote/testing -p=%s'" %
            NO_SETTINGS_PACKAGE_ID, client.out)

        client.run("remove Hello/0.1@lasote/testing -p=%s -f" %
                   NO_SETTINGS_PACKAGE_ID)
        client.run("upload * --all --confirm")

    @pytest.mark.artifactory_ready
    def test_upload_force(self):
        ref = ConanFileReference.loads("Hello/0.1@conan/testing")
        client = TurboTestClient(servers={"default": TestServer()})
        pref = client.create(ref,
                             conanfile=GenConanfile().with_package_file(
                                 "myfile.sh", "foo"))
        client.run("upload * --all --confirm")
        self.assertIn("Uploading conan_package.tgz", client.out)
        client.run("upload * --all --confirm")
        self.assertNotIn("Uploading conan_package.tgz", client.out)

        package_folder = client.cache.package_layout(pref.ref).package(pref)
        package_file_path = os.path.join(package_folder, "myfile.sh")

        if platform.system() == "Linux":
            client.run("remove '*' -f")
            client.create(ref,
                          conanfile=GenConanfile().with_package_file(
                              "myfile.sh", "foo"))
            os.system('chmod +x "{}"'.format(package_file_path))
            self.assertTrue(os.stat(package_file_path).st_mode & stat.S_IXUSR)
            client.run("upload * --all --confirm")
            self.assertNotIn("Uploading conan_package.tgz", client.out)
            self.assertIn("Package is up to date, upload skipped", client.out)
            self.assertIn("Compressing package...", client.out)

        client.run("upload * --all --confirm --force")
        self.assertIn("Uploading conanfile.py", client.out)
        self.assertIn("Uploading conan_package.tgz", client.out)

        if platform.system() == "Linux":
            client.run("remove '*' -f")
            client.run("install {}".format(ref))
            # Owner with execute permissions
            self.assertTrue(os.stat(package_file_path).st_mode & stat.S_IXUSR)

    def test_upload_binary_not_existing(self):
        client = TestClient(default_server_user=True)
        client.save({"conanfile.py": GenConanfile()})
        client.run("export . Hello/0.1@lasote/testing")
        client.run("upload Hello/0.1@lasote/testing -p=123", assert_error=True)
        self.assertIn(
            "ERROR: Binary package Hello/0.1@lasote/testing:123 not found",
            client.out)

    def test_not_existing_error(self):
        """ Trying to upload with pattern not matched must raise an Error
        """
        client = TestClient()
        client.run("upload some_nonsense", assert_error=True)
        self.assertIn(
            "ERROR: No packages found matching pattern 'some_nonsense'",
            client.out)

    def test_invalid_reference_error(self):
        """ Trying to upload an invalid reference must raise an Error
        """
        client = TestClient()
        client.run("upload some_nonsense -p hash1", assert_error=True)
        self.assertIn(
            "ERROR: -p parameter only allowed with a valid recipe reference",
            client.out)

    def test_non_existing_recipe_error(self):
        """ Trying to upload a non-existing recipe must raise an Error
        """
        client = TestClient(default_server_user=True)
        client.run("upload Pkg/0.1@user/channel", assert_error=True)
        self.assertIn("Recipe not found: 'Pkg/0.1@user/channel'", client.out)

    def test_non_existing_package_error(self):
        """ Trying to upload a non-existing package must raise an Error
        """
        client = TestClient(default_server_user=True)
        client.run("upload Pkg/0.1@user/channel -p hash1", assert_error=True)
        self.assertIn("ERROR: Recipe not found: 'Pkg/0.1@user/channel'",
                      client.out)

    def test_deprecated_p_arg(self):
        client = TestClient(default_server_user=True)
        client.save({"conanfile.py": conanfile})
        client.run("create . user/testing")
        client.run("upload Hello0/1.2.1@user/testing -p {} -c".format(
            NO_SETTINGS_PACKAGE_ID))
        self.assertIn(
            "WARN: Usage of `--package` argument is deprecated. "
            "Use a full reference instead: `conan upload [...] "
            "Hello0/1.2.1@user/testing:{}`".format(NO_SETTINGS_PACKAGE_ID),
            client.out)

    def test_upload_with_pref(self):
        client = TestClient(default_server_user=True)
        client.save({"conanfile.py": conanfile})
        client.run("create . user/testing")
        client.run("upload Hello0/1.2.1@user/testing:{} -c".format(
            NO_SETTINGS_PACKAGE_ID))
        self.assertNotIn(
            "WARN: Usage of `--package` argument is deprecated. "
            "Use a full reference instead: `conan upload [...] "
            "Hello0/1.2.1@user/testing:{}`".format(NO_SETTINGS_PACKAGE_ID),
            client.out)
        self.assertIn(
            "Uploading package 1/1: {} to 'default'".format(
                NO_SETTINGS_PACKAGE_ID), client.out)

    def test_upload_with_pref_and_p(self):
        client = TestClient(default_server_user=True)
        client.save({"conanfile.py": conanfile})
        client.run("create . user/testing")
        client.run("upload Hello0/1.2.1@user/testing:{} -c -p {}".format(
            NO_SETTINGS_PACKAGE_ID, NO_SETTINGS_PACKAGE_ID),
                   assert_error=True)

        self.assertIn(
            "Use a full package reference (preferred) or the "
            "`--package` command argument, but not both.", client.out)

    def test_pattern_upload(self):
        client = TestClient(default_server_user=True)
        client.save({"conanfile.py": conanfile})
        client.run("create . user/testing")
        client.run("upload Hello0/*@user/testing --confirm --all")
        self.assertIn("Uploading conanmanifest.txt", client.out)
        self.assertIn("Uploading conan_package.tgz", client.out)
        self.assertIn("Uploading conanfile.py", client.out)

    def test_query_upload(self):
        client = TestClient(default_server_user=True)
        conanfile_upload_query = textwrap.dedent("""
            from conans import ConanFile
            class MyPkg(ConanFile):
                name = "Hello1"
                version = "1.2.1"
                exports_sources = "*"
                settings = "os", "arch"

                def package(self):
                    self.copy("*")
            """)
        client.save({"conanfile.py": conanfile_upload_query})

        for _os, arch in itertools.product(["Macos", "Linux", "Windows"],
                                           ["armv8", "x86_64"]):
            client.run("create . user/testing -s os=%s -s arch=%s" %
                       (_os, arch))

        # Check that the right number of packages are picked up by the queries
        client.run(
            "upload Hello1/*@user/testing --confirm -q 'os=Windows or os=Macos'"
        )
        for i in range(1, 5):
            self.assertIn("Uploading package %d/4" % i, client.out)
        self.assertNotIn("Package is up to date, upload skipped", client.out)

        client.run(
            "upload Hello1/*@user/testing --confirm -q 'os=Linux and arch=x86_64'"
        )
        self.assertIn("Uploading package 1/1", client.out)

        client.run("upload Hello1/*@user/testing --confirm -q 'arch=armv8'")
        for i in range(1, 4):
            self.assertIn("Uploading package %d/3" % i, client.out)
        self.assertIn("Package is up to date, upload skipped", client.out)

        # Check that a query not matching any packages doesn't upload any packages
        client.run("upload Hello1/*@user/testing --confirm -q 'arch=sparc'")
        self.assertNotIn("Uploading package", client.out)

        # Check that an invalid query fails
        client.run(
            "upload Hello1/*@user/testing --confirm -q 'blah blah blah'",
            assert_error=True)
        self.assertIn("Invalid package query", client.out)

    def test_broken_sources_tgz(self):
        # https://github.com/conan-io/conan/issues/2854
        client = TestClient(default_server_user=True)
        client.save({"conanfile.py": conanfile, "source.h": "my source"})
        client.run("create . user/testing")
        ref = ConanFileReference.loads("Hello0/1.2.1@user/testing")

        def gzopen_patched(name, mode="r", fileobj=None, **kwargs):
            raise ConanException("Error gzopen %s" % name)

        with patch('conans.client.cmd.uploader.gzopen_without_timestamps',
                   new=gzopen_patched):
            client.run("upload * --confirm", assert_error=True)
            self.assertIn(
                "ERROR: Hello0/1.2.1@user/testing: Upload recipe to 'default' failed: "
                "Error gzopen conan_sources.tgz", client.out)

            export_download_folder = client.cache.package_layout(
                ref).download_export()
            tgz = os.path.join(export_download_folder, EXPORT_SOURCES_TGZ_NAME)
            self.assertTrue(os.path.exists(tgz))
            self.assertTrue(is_dirty(tgz))

        client.run("upload * --confirm")
        self.assertIn(
            "WARN: Hello0/1.2.1@user/testing: Removing conan_sources.tgz, "
            "marked as dirty", client.out)
        self.assertTrue(os.path.exists(tgz))
        self.assertFalse(is_dirty(tgz))

    def test_broken_package_tgz(self):
        # https://github.com/conan-io/conan/issues/2854
        client = TestClient(default_server_user=True)
        client.save({"conanfile.py": conanfile, "source.h": "my source"})
        client.run("create . user/testing")
        pref = PackageReference.loads("Hello0/1.2.1@user/testing:" +
                                      NO_SETTINGS_PACKAGE_ID)

        def gzopen_patched(name, mode="r", fileobj=None, **kwargs):
            if name == PACKAGE_TGZ_NAME:
                raise ConanException("Error gzopen %s" % name)
            return gzopen_without_timestamps(name, mode, fileobj, **kwargs)

        with patch('conans.client.cmd.uploader.gzopen_without_timestamps',
                   new=gzopen_patched):
            client.run("upload * --confirm --all", assert_error=True)
            self.assertIn(
                "ERROR: Hello0/1.2.1@user/testing:5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9"
                ": Upload package to 'default' failed: Error gzopen conan_package.tgz",
                client.out)

            download_folder = client.cache.package_layout(
                pref.ref).download_package(pref)
            tgz = os.path.join(download_folder, PACKAGE_TGZ_NAME)
            self.assertTrue(os.path.exists(tgz))
            self.assertTrue(is_dirty(tgz))

        client.run("upload * --confirm --all")
        self.assertIn(
            "WARN: Hello0/1.2.1@user/testing:%s: "
            "Removing conan_package.tgz, marked as dirty" %
            NO_SETTINGS_PACKAGE_ID, client.out)
        self.assertTrue(os.path.exists(tgz))
        self.assertFalse(is_dirty(tgz))

    def test_corrupt_upload(self):
        client = TestClient(default_server_user=True)

        client.save({"conanfile.py": conanfile, "include/hello.h": ""})
        client.run("create . frodo/stable")
        ref = ConanFileReference.loads("Hello0/1.2.1@frodo/stable")
        packages_folder = client.cache.package_layout(ref).packages()
        pkg_id = os.listdir(packages_folder)[0]
        package_folder = os.path.join(packages_folder, pkg_id)
        save(os.path.join(package_folder, "added.txt"), "")
        os.remove(os.path.join(package_folder, "include/hello.h"))
        client.run("upload Hello0/1.2.1@frodo/stable --all --check",
                   assert_error=True)
        self.assertIn("WARN: Mismatched checksum 'added.txt'", client.out)
        self.assertIn("WARN: Mismatched checksum 'include/hello.h'",
                      client.out)
        self.assertIn(
            "ERROR: Hello0/1.2.1@frodo/stable:5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9: "
            "Upload package to 'default' failed: Cannot upload corrupted package",
            client.out)

    def test_upload_modified_recipe(self):
        client = TestClient(default_server_user=True)

        client.save({"conanfile.py": conanfile, "hello.cpp": "int i=0"})
        client.run("export . frodo/stable")
        client.run("upload Hello0/1.2.1@frodo/stable")
        self.assertIn("Uploading conanmanifest.txt", client.out)
        assert "Uploading Hello0/1.2.1@frodo/stable to remote" in client.out

        client2 = TestClient(servers=client.servers, users=client.users)
        client2.save({
            "conanfile.py": conanfile + "\r\n#end",
            "hello.cpp": "int i=1"
        })
        client2.run("export . frodo/stable")
        ref = ConanFileReference.loads("Hello0/1.2.1@frodo/stable")
        manifest = client2.cache.package_layout(ref).recipe_manifest()
        manifest.time += 10
        manifest.save(client2.cache.package_layout(ref).export())
        client2.run("upload Hello0/1.2.1@frodo/stable")
        self.assertIn("Uploading conanmanifest.txt", client2.out)
        assert "Uploading Hello0/1.2.1@frodo/stable to remote" in client2.out

        # first client tries to upload again
        if not client.cache.config.revisions_enabled:
            client.run("upload Hello0/1.2.1@frodo/stable", assert_error=True)
            self.assertIn("Remote recipe is newer than local recipe",
                          client.out)
            self.assertIn("Local 'conanfile.py' using '\\n' line-ends",
                          client.out)
            self.assertIn("Remote 'conanfile.py' using '\\r\\n' line-ends",
                          client.out)
        else:
            # The client tries to upload exactly the same revision already uploaded, so no changes
            client.run("upload Hello0/1.2.1@frodo/stable")
            self.assertIn("Recipe is up to date, upload skipped", client.out)

    def test_upload_unmodified_recipe(self):
        client = TestClient(default_server_user=True)
        files = {"conanfile.py": GenConanfile("Hello0", "1.2.1")}
        client.save(files)
        client.run("export . frodo/stable")
        client.run("upload Hello0/1.2.1@frodo/stable")
        self.assertIn("Uploading conanmanifest.txt", client.out)
        assert "Uploading Hello0/1.2.1@frodo/stable to remote" in client.out

        client2 = TestClient(servers=client.servers, users=client.users)
        client2.save(files)
        client2.run("export . frodo/stable")
        ref = ConanFileReference.loads("Hello0/1.2.1@frodo/stable")
        manifest = client2.cache.package_layout(ref).recipe_manifest()
        manifest.time += 10
        manifest.save(client2.cache.package_layout(ref).export())
        client2.run("upload Hello0/1.2.1@frodo/stable")
        self.assertNotIn("Uploading conanmanifest.txt", client2.out)
        assert "Uploading Hello0/1.2.1@frodo/stable to remote" in client2.out
        self.assertIn("Recipe is up to date, upload skipped", client2.out)

        # first client tries to upload again
        client.run("upload Hello0/1.2.1@frodo/stable")
        self.assertNotIn("Uploading conanmanifest.txt", client.out)
        assert "Uploading Hello0/1.2.1@frodo/stable to remote" in client.out
        self.assertIn("Recipe is up to date, upload skipped", client.out)

    def test_upload_unmodified_package(self):
        client = TestClient(default_server_user=True)

        client.save({"conanfile.py": conanfile, "hello.cpp": ""})
        client.run("create . frodo/stable")
        client.run("upload Hello0/1.2.1@frodo/stable --all")

        client2 = TestClient(servers=client.servers, users=client.users)
        client2.save({"conanfile.py": conanfile, "hello.cpp": ""})
        client2.run("create . frodo/stable")
        client2.run("upload Hello0/1.2.1@frodo/stable --all")
        self.assertIn("Recipe is up to date, upload skipped", client2.out)
        self.assertNotIn("Uploading conanfile.py", client2.out)
        self.assertNotIn("Uploading conan_sources.tgz", client2.out)
        self.assertNotIn(
            "Uploaded conan recipe 'Hello0/1.2.1@frodo/stable' to 'default'",
            client2.out)
        self.assertNotIn("Uploading conaninfo.txt",
                         client2.out)  # conaninfo NOT changed
        self.assertNotIn("Uploading conan_package.tgz", client2.out)
        self.assertIn("Package is up to date, upload skipped", client2.out)

        # first client tries to upload again
        client.run("upload Hello0/1.2.1@frodo/stable --all")
        self.assertIn("Recipe is up to date, upload skipped", client.out)
        self.assertNotIn("Uploading conanfile.py", client.out)
        self.assertNotIn("Uploading conan_sources.tgz", client.out)
        self.assertNotIn(
            "Uploaded conan recipe 'Hello0/1.2.1@frodo/stable' to 'default'",
            client.out)
        self.assertNotIn("Uploading conaninfo.txt",
                         client.out)  # conaninfo NOT changed
        self.assertNotIn("Uploading conan_package.tgz", client2.out)
        self.assertIn("Package is up to date, upload skipped", client2.out)

    def test_no_overwrite_argument_collision(self):
        client = TestClient(default_server_user=True)
        client.save({"conanfile.py": conanfile, "hello.cpp": ""})
        client.run("create . frodo/stable")

        # Not valid values as arguments
        client.run("upload Hello0/1.2.1@frodo/stable --no-overwrite kk",
                   assert_error=True)
        self.assertIn("ERROR", client.out)

        # --force not valid with --no-overwrite
        client.run("upload Hello0/1.2.1@frodo/stable --no-overwrite --force",
                   assert_error=True)
        self.assertIn(
            "ERROR: '--no-overwrite' argument cannot be used together with '--force'",
            client.out)

    def test_upload_no_overwrite_all(self):
        conanfile_new = """from conans import ConanFile, tools
class MyPkg(ConanFile):
    name = "Hello0"
    version = "1.2.1"
    exports_sources = "*"
    options = {"shared": [True, False]}
    default_options = "shared=False"

    def build(self):
        if tools.get_env("MY_VAR", False):
            open("file.h", 'w').close()

    def package(self):
        self.copy("*.h")
"""
        client = TestClient(default_server_user=True)
        client.save({
            "conanfile.py": conanfile_new,
            "hello.h": "",
            "hello.cpp": ""
        })
        client.run("create . frodo/stable")

        # First time upload
        client.run("upload Hello0/1.2.1@frodo/stable --all --no-overwrite")
        self.assertNotIn("Forbidden overwrite", client.out)
        self.assertIn("Uploading Hello0/1.2.1@frodo/stable", client.out)

        # CASE: Upload again
        client.run("upload Hello0/1.2.1@frodo/stable --all --no-overwrite")
        self.assertIn("Recipe is up to date, upload skipped", client.out)
        self.assertIn("Package is up to date, upload skipped", client.out)
        self.assertNotIn("Forbidden overwrite", client.out)

        # CASE: Without changes
        client.run("create . frodo/stable")
        # upload recipe and packages
        client.run("upload Hello0/1.2.1@frodo/stable --all --no-overwrite")
        self.assertIn("Recipe is up to date, upload skipped", client.out)
        self.assertIn("Package is up to date, upload skipped", client.out)
        self.assertNotIn("Forbidden overwrite", client.out)

        # CASE: When recipe and package changes
        new_recipe = conanfile_new.replace(
            "self.copy(\"*.h\")",
            "self.copy(\"*.h\")\n        self.copy(\"*.cpp\")")
        client.save({"conanfile.py": new_recipe})
        client.run("create . frodo/stable")
        # upload recipe and packages
        # *1
        client.run("upload Hello0/1.2.1@frodo/stable --all --no-overwrite",
                   assert_error=not client.cache.config.revisions_enabled)
        if not client.cache.config.revisions_enabled:
            # The --no-overwrite makes no sense with revisions
            self.assertIn("Forbidden overwrite", client.out)
            self.assertNotIn("Uploading conan_package.tgz", client.out)

        # CASE: When package changes
        client.run("upload Hello0/1.2.1@frodo/stable --all")
        with environment_append({"MY_VAR": "True"}):
            client.run("create . frodo/stable")
        # upload recipe and packages
        client.run("upload Hello0/1.2.1@frodo/stable --all --no-overwrite",
                   assert_error=not client.cache.config.revisions_enabled)
        if not client.cache.config.revisions_enabled:
            self.assertIn("Recipe is up to date, upload skipped", client.out)
            self.assertIn(
                "ERROR: Hello0/1.2.1@frodo/stable:5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9"
                ": Upload package to 'default' failed: "
                "Local package is different from the remote package",
                client.out)
            self.assertIn("Forbidden overwrite", client.out)
            self.assertNotIn("Uploading conan_package.tgz", client.out)
        else:
            self.assertIn("Uploading conan_package.tgz", client.out)

    def test_upload_no_overwrite_recipe(self):
        conanfile_new = """from conans import ConanFile, tools
class MyPkg(ConanFile):
    name = "Hello0"
    version = "1.2.1"
    exports_sources = "*"
    options = {"shared": [True, False]}
    default_options = "shared=False"

    def build(self):
        if tools.get_env("MY_VAR", False):
            open("file.h", 'w').close()

    def package(self):
        self.copy("*.h")
"""
        client = TestClient(default_server_user=True)
        client.save({
            "conanfile.py": conanfile_new,
            "hello.h": "",
            "hello.cpp": ""
        })
        client.run("create . frodo/stable")

        # First time upload
        client.run(
            "upload Hello0/1.2.1@frodo/stable --all --no-overwrite recipe")
        self.assertNotIn("Forbidden overwrite", client.out)
        self.assertIn("Uploading Hello0/1.2.1@frodo/stable", client.out)

        # Upload again
        client.run(
            "upload Hello0/1.2.1@frodo/stable --all --no-overwrite recipe")
        self.assertIn("Recipe is up to date, upload skipped", client.out)
        self.assertIn("Package is up to date, upload skipped", client.out)
        self.assertNotIn("Forbidden overwrite", client.out)

        # Create without changes
        # *1
        client.run("create . frodo/stable")
        client.run(
            "upload Hello0/1.2.1@frodo/stable --all --no-overwrite recipe")
        self.assertIn("Recipe is up to date, upload skipped", client.out)
        self.assertIn("Package is up to date, upload skipped", client.out)
        self.assertNotIn("Forbidden overwrite", client.out)

        # Create with recipe and package changes
        new_recipe = conanfile_new.replace(
            "self.copy(\"*.h\")",
            "self.copy(\"*.h\")\n        self.copy(\"*.cpp\")")
        client.save({"conanfile.py": new_recipe})
        client.run("create . frodo/stable")
        # upload recipe and packages
        client.run(
            "upload Hello0/1.2.1@frodo/stable --all --no-overwrite recipe",
            assert_error=not client.cache.config.revisions_enabled)
        if not client.cache.config.revisions_enabled:
            self.assertIn("Forbidden overwrite", client.out)
            self.assertNotIn("Uploading package", client.out)

            # Create with package changes
            client.run("upload Hello0/1.2.1@frodo/stable --all")
            with environment_append({"MY_VAR": "True"}):
                client.run("create . frodo/stable")
            # upload recipe and packages
            client.run(
                "upload Hello0/1.2.1@frodo/stable --all --no-overwrite recipe")
            self.assertIn("Recipe is up to date, upload skipped", client.out)
            self.assertIn("Uploading conan_package.tgz", client.out)
            self.assertNotIn("Forbidden overwrite", client.out)
        else:
            self.assertIn("Uploading conan_package.tgz", client.out)

    def test_skip_upload(self):
        """ Check that the option --dry does not upload anything
        """
        client = TestClient(default_server_user=True)

        files = {
            "conanfile.py": GenConanfile("Hello0", "1.2.1").with_exports("*"),
            "file.txt": ""
        }
        client.save(files)
        client.run("create . frodo/stable")
        client.run(
            "upload Hello0/1.2.1@frodo/stable -r default --all --skip-upload")

        # dry run should not upload
        self.assertNotIn("Uploading conan_package.tgz", client.out)

        # but dry run should compress
        self.assertIn("Compressing recipe...", client.out)
        self.assertIn("Compressing package...", client.out)

        client.run("search -r default")
        # after dry run nothing should be on the server ...
        self.assertNotIn("Hello0/1.2.1@frodo/stable", client.out)

        # now upload, the stuff should NOT be recompressed
        client.run("upload Hello0/1.2.1@frodo/stable -r default --all")

        # check for upload message
        self.assertIn("Uploading conan_package.tgz", client.out)

        # check if compressed files are re-used
        self.assertNotIn("Compressing recipe...", client.out)
        self.assertNotIn("Compressing package...", client.out)

        # now it should be on the server
        client.run("search -r default")
        self.assertIn("Hello0/1.2.1@frodo/stable", client.out)

    def test_upload_without_sources(self):
        client = TestClient(default_server_user=True)
        client.save({"conanfile.py": GenConanfile()})
        client.run("create . Pkg/0.1@user/testing")
        client.run("upload * --all --confirm")
        client2 = TestClient(servers=client.servers, users=client.users)
        client2.run("install Pkg/0.1@user/testing")
        client2.run("remote remove default")
        server2 = TestServer([("*/*@*/*", "*")], [("*/*@*/*", "*")],
                             users={"lasote": "mypass"})
        client2.users = {"server2": [("lasote", "mypass")]}
        client2.servers = {"server2": server2}
        client2.update_servers()
        client2.run("upload * --all --confirm -r=server2")
        self.assertIn("Uploading conanfile.py", client2.out)
        self.assertIn("Uploading conan_package.tgz", client2.out)

    def test_upload_login_prompt_disabled_no_user(self):
        """ Without user info, uploads should fail when login prompt has been disabled.
        """
        files = {"conanfile.py": GenConanfile("Hello0", "1.2.1")}
        client = TestClient(default_server_user=True)
        client.save(files)
        client.run("config set general.non_interactive=True")
        client.run("create . user/testing")
        client.run("user -c")
        client.run("upload Hello0/1.2.1@user/testing", assert_error=True)

        self.assertIn(
            "ERROR: Hello0/1.2.1@user/testing: Upload recipe to 'default' failed: "
            "Conan interactive mode disabled", client.out)
        self.assertNotIn("Uploading conanmanifest.txt", client.out)
        self.assertNotIn("Uploading conanfile.py", client.out)
        self.assertNotIn("Uploading conan_export.tgz", client.out)

    def test_upload_login_prompt_disabled_user_not_authenticated(self):
        # When a user is not authenticated, uploads should fail when login prompt has been disabled.
        files = {"conanfile.py": GenConanfile("Hello0", "1.2.1")}
        client = TestClient(default_server_user=True)
        client.save(files)
        client.run("config set general.non_interactive=True")
        client.run("create . user/testing")
        client.run("user -c")
        client.run("user lasote")
        client.run("upload Hello0/1.2.1@user/testing", assert_error=True)
        self.assertIn(
            "ERROR: Hello0/1.2.1@user/testing: Upload recipe to 'default' failed: "
            "Conan interactive mode disabled", client.out)
        self.assertNotIn("Uploading conanmanifest.txt", client.out)
        self.assertNotIn("Uploading conanfile.py", client.out)
        self.assertNotIn("Uploading conan_export.tgz", client.out)
        self.assertNotIn("Please enter a password for", client.out)

    def test_upload_login_prompt_disabled_user_authenticated(self):
        #  When user is authenticated, uploads should work even when login prompt has been disabled.
        client = TestClient(default_server_user=True)
        client.save({"conanfile.py": GenConanfile("Hello0", "1.2.1")})
        client.run("config set general.non_interactive=True")
        client.run("create . user/testing")
        client.run("user -c")
        client.run("user user -p password")
        client.run("upload Hello0/1.2.1@user/testing")
        self.assertIn("Uploading conanmanifest.txt", client.out)
        self.assertIn("Uploading conanfile.py", client.out)

    @pytest.mark.skipif(not get_env("TESTING_REVISIONS_ENABLED", False),
                        reason="Only revisions")
    def test_upload_key_error(self):
        files = {"conanfile.py": GenConanfile("Hello0", "1.2.1")}
        server1 = TestServer([("*/*@*/*", "*")], [("*/*@*/*", "*")],
                             users={"lasote": "mypass"})
        server2 = TestServer([("*/*@*/*", "*")], [("*/*@*/*", "*")],
                             users={"lasote": "mypass"})
        servers = OrderedDict()
        servers["server1"] = server1
        servers["server2"] = server2
        client = TestClient(servers=servers)
        client.save(files)
        client.run("create . user/testing")
        client.run("user lasote -p mypass")
        client.run("user lasote -p mypass -r server2")
        client.run("upload Hello0/1.2.1@user/testing --all -r server1")
        client.run("remove * --force")
        client.run("install Hello0/1.2.1@user/testing -r server1")
        client.run("remote remove server1")
        client.run("upload Hello0/1.2.1@user/testing --all -r server2")
        self.assertNotIn("ERROR: 'server1'", client.out)

    def test_upload_export_pkg(self):
        """
        Package metadata created when doing an export-pkg and then uploading the package works
        """
        server1 = TestServer([("*/*@*/*", "*")], [("*/*@*/*", "*")],
                             users={"lasote": "mypass"})
        servers = OrderedDict()
        servers["server1"] = server1
        client = TestClient(servers=servers)
        client.save({"release/kk.lib": ""})
        client.run("user lasote -r server1 -p mypass")
        client.run("new hello/1.0 --header")
        client.run("export-pkg . user/testing -pf release")
        client.run("upload hello/1.0@user/testing --all -r server1")
        self.assertNotIn(
            "Binary package hello/1.0@user/testing:5%s not found" %
            NO_SETTINGS_PACKAGE_ID, client.out)
        ref = ConanFileReference("hello", "1.0", "user", "testing")
        metadata = client.cache.package_layout(ref).load_metadata()
        self.assertIn(NO_SETTINGS_PACKAGE_ID, metadata.packages)
        self.assertTrue(metadata.packages[NO_SETTINGS_PACKAGE_ID].revision)

    def test_no_remote_recipe_manifest(self):
        # https://github.com/conan-io/conan/issues/4953
        server = TestServer()
        servers = OrderedDict([("default", server)])
        client = TurboTestClient(servers=servers)
        client2 = TurboTestClient(servers=servers)

        ref = ConanFileReference.loads("lib/1.0@conan/testing")
        client.create(ref)
        complete_ref = client.upload_all(ref)
        # Simulate a missing manifest, maybe because it hasn't been uploaded yet
        export_folder = server.server_store.export(complete_ref)
        os.unlink(os.path.join(export_folder, "conanmanifest.txt"))

        # Upload same with client2
        client2.create(ref)
        client2.upload_all(ref)
        self.assertIn(
            "WARN: The remote recipe doesn't have the 'conanmanifest.txt' file "
            "and will be uploaded: 'lib/1.0@conan/testing'", client2.out)

    def test_concurrent_upload(self):
        # https://github.com/conan-io/conan/issues/4953
        server = TestServer()
        servers = OrderedDict([("default", server)])
        client = TurboTestClient(servers=servers)
        client2 = TurboTestClient(servers=servers)

        ref = ConanFileReference.loads("lib/1.0@conan/testing")
        client.create(ref)
        client.upload_all(ref)
        # The _check_recipe_date returns None, but later it will get the manifest ok
        with patch.object(CmdUpload, "_check_recipe_date") as check_date:
            check_date.return_value = None
            # Upload same with client2
            client2.create(ref)
            client2.run("upload lib/1.0@conan/testing")
            self.assertIn("Recipe is up to date, upload skipped", client2.out)
            self.assertNotIn("WARN", client2.out)

    def test_upload_with_pref_and_query(self):
        client = TestClient(default_server_user=True)
        client.save({"conanfile.py": conanfile})
        client.run("create . user/testing")
        client.run(
            "upload Hello0/1.2.1@user/testing:{} "
            "-q 'os=Windows or os=Macos'".format(NO_SETTINGS_PACKAGE_ID),
            assert_error=True)

        self.assertIn(
            "'--query' argument cannot be used together with full reference",
            client.out)

    def test_upload_with_package_id_and_query(self):
        client = TestClient(default_server_user=True)
        client.save({"conanfile.py": conanfile})
        client.run("create . user/testing")
        client.run(
            "upload Hello0/1.2.1@user/testing -p {} "
            "-q 'os=Windows or os=Macos'".format(NO_SETTINGS_PACKAGE_ID),
            assert_error=True)

        self.assertIn(
            "'--query' argument cannot be used together with '--package'",
            client.out)

    def test_upload_without_user_channel(self):
        server = TestServer(users={"user": "******"},
                            write_permissions=[("*/*@*/*", "*")])
        servers = {"default": server}
        client = TestClient(servers=servers,
                            users={"default": [("user", "password")]})

        client.save({"conanfile.py": GenConanfile()})

        client.run('create . lib/1.0@')
        self.assertIn(
            "lib/1.0: Package '{}' created".format(NO_SETTINGS_PACKAGE_ID),
            client.out)
        client.run('upload lib/1.0 -c --all')
        assert "Uploading lib/1.0 to remote" in client.out

        # Verify that in the remote it is stored as "_"
        pref = PackageReference.loads(
            "lib/1.0@#0:{}#0".format(NO_SETTINGS_PACKAGE_ID))
        path = server.server_store.export(pref.ref)
        self.assertIn("/lib/1.0/_/_/0/export", path.replace("\\", "/"))

        path = server.server_store.package(pref)
        self.assertIn("/lib/1.0/_/_/0/package", path.replace("\\", "/"))

        # Should be possible with explicit package
        client.run('upload lib/1.0:5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9')
        self.assertIn(
            "Uploading package 1/1: 5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9 to 'default'",
            client.out)

    def test_checksums_metadata(self):
        client = TestClient(default_server_user=True)
        client.save({"conanfile.py": GenConanfile()})
        client.run('create . lib/1.0@user/channel')
        client.run('upload lib/1.0 -c --all -r default')
        ref = ConanFileReference("lib", "1.0", "user", "channel")
        metadata = client.cache.package_layout(ref).load_metadata()
        package_md5 = metadata.packages[NO_SETTINGS_PACKAGE_ID].checksums[
            "conan_package.tgz"]["md5"]
        package_sha1 = metadata.packages[NO_SETTINGS_PACKAGE_ID].checksums[
            "conan_package.tgz"]["sha1"]
        recipe_md5 = metadata.recipe.checksums["conanfile.py"]["md5"]
        recipe_sha1 = metadata.recipe.checksums["conanfile.py"]["sha1"]
        self.assertEqual(package_md5, "25f53ac9685e07815b990e7c6f21bfd0")
        self.assertEqual(package_sha1,
                         "be152c82859285658a06816aaaec529a159c33d3")
        self.assertEqual(recipe_md5, "8eda41e0997f3eacc436fb6c621d7396")
        self.assertEqual(recipe_sha1,
                         "b97d6b26be5bd02252a44c265755f873cf5ec70b")
        client.run('remove * -f')
        client.run('install lib/1.0@user/channel -r default')
        metadata = client.cache.package_layout(ref).load_metadata()
        self.assertEqual(
            metadata.packages[NO_SETTINGS_PACKAGE_ID].
            checksums["conan_package.tgz"]["md5"], package_md5)
        self.assertEqual(
            metadata.packages[NO_SETTINGS_PACKAGE_ID].
            checksums["conan_package.tgz"]["sha1"], package_sha1)
        self.assertEqual(metadata.recipe.checksums["conanfile.py"]["md5"],
                         recipe_md5)
        self.assertEqual(metadata.recipe.checksums["conanfile.py"]["sha1"],
                         recipe_sha1)

    def test_upload_without_cleaned_user(self):
        """ When a user is not authenticated, uploads failed first time
        https://github.com/conan-io/conan/issues/5878
        """
        class EmptyCapabilitiesResponse(object):
            def __init__(self):
                self.ok = False
                self.headers = {
                    "X-Conan-Server-Capabilities": "",
                    "Content-Type": "application/json"
                }
                self.status_code = 401
                self.content = b''

        class ErrorApiResponse(object):
            def __init__(self):
                self.ok = False
                self.status_code = 400
                self.content = "Unsupported Conan v1 repository request for 'conan'"

        class ServerCapabilitiesRequester(TestRequester):
            def __init__(self, *args, **kwargs):
                self._first_ping = True
                super(ServerCapabilitiesRequester,
                      self).__init__(*args, **kwargs)

            def get(self, url, **kwargs):
                app, url = self._prepare_call(url, kwargs)
                if app:
                    if url.endswith("ping") and self._first_ping:
                        self._first_ping = False
                        return EmptyCapabilitiesResponse()
                    elif "Hello0" in url and "1.2.1" in url and "v1" in url:
                        return ErrorApiResponse()
                    else:
                        response = app.get(url, **kwargs)
                        return TestingResponse(response)
                else:
                    return requests.get(url, **kwargs)

        server = TestServer(users={"user": "******"},
                            write_permissions=[("*/*@*/*", "*")],
                            server_capabilities=[REVISIONS])
        servers = {"default": server}
        client = TestClient(requester_class=ServerCapabilitiesRequester,
                            servers=servers,
                            revisions_enabled=True)
        files = {"conanfile.py": GenConanfile("Hello0", "1.2.1")}
        client.save(files)
        client.run("create . user/testing")
        client.run("user -c")
        client.run("upload Hello0/1.2.1@user/testing --all -r default")
        assert "Uploading Hello0/1.2.1@user/testing to remote" in client.out

    @pytest.mark.skipif(get_env("TESTING_REVISIONS_ENABLED", False),
                        reason="No sense with revs")
    def test_upload_with_rev_revs_disabled(self):
        client = TestClient(default_server_user=True, revisions_enabled=False)
        client.run("upload pkg/1.0@user/channel#fakerevision --confirm",
                   assert_error=True)
        self.assertIn(
            "ERROR: Revisions not enabled in the client, specify a reference without revision",
            client.out)

    @pytest.mark.skipif(not get_env("TESTING_REVISIONS_ENABLED", False),
                        reason="Only revisions")
    def test_upload_with_recipe_revision(self):
        ref = ConanFileReference.loads("pkg/1.0@user/channel")
        client = TurboTestClient(default_server_user=True,
                                 revisions_enabled=True)
        pref = client.create(ref, conanfile=GenConanfile())
        client.run("upload pkg/1.0@user/channel#fakerevision --confirm",
                   assert_error=True)
        self.assertIn(
            "ERROR: Recipe revision fakerevision does not match the one stored in "
            "the cache {}".format(pref.ref.revision), client.out)

        client.run("upload pkg/1.0@user/channel#{} --confirm".format(
            pref.ref.revision))
        search_result = client.search(
            "pkg/1.0@user/channel --revisions -r default")[0]
        self.assertIn(pref.ref.revision, search_result["revision"])

    @pytest.mark.skipif(not get_env("TESTING_REVISIONS_ENABLED", False),
                        reason="Only revisions")
    def test_upload_with_package_revision(self):
        ref = ConanFileReference.loads("pkg/1.0@user/channel")
        client = TurboTestClient(default_server_user=True,
                                 revisions_enabled=True)
        pref = client.create(ref, conanfile=GenConanfile())
        client.run(
            "upload pkg/1.0@user/channel#{}:{}#fakeprev --confirm".format(
                pref.ref.revision, pref.id),
            assert_error=True)
        self.assertIn(
            "ERROR: Binary package pkg/1.0@user/channel:{}#fakeprev not found".
            format(pref.id), client.out)

        client.run("upload pkg/1.0@user/channel#{}:{}#{} --confirm".format(
            pref.ref.revision, pref.id, pref.revision))
        search_result = client.search(
            "pkg/1.0@user/channel --revisions -r default")[0]
        self.assertIn(pref.ref.revision, search_result["revision"])
        search_result = client.search(
            "pkg/1.0@user/channel#{}:{} --revisions  -r default".format(
                pref.ref.revision, pref.id))[0]
        self.assertIn(pref.revision, search_result["revision"])
Beispiel #55
0
class InstallOutdatedPackagesTest(unittest.TestCase):
    def setUp(self):
        test_server = TestServer()
        self.servers = {"default": test_server}
        self.client = TestClient(servers=self.servers,
                                 users={"default": [("lasote", "mypass")]})
        self.new_client = TestClient(servers=self.servers,
                                     users={"default": [("lasote", "mypass")]})

        self.ref = ConanFileReference.loads("Hello0/0.1@lasote/stable")
        files = cpp_hello_conan_files("Hello0", "0.1", build=False)
        self.client.save(files)
        self.client.run("export . lasote/stable")

        self.client.run("install Hello0/0.1@lasote/stable --build missing")
        self.client.run("upload  Hello0/0.1@lasote/stable --all")

    @unittest.skipIf(get_env("TESTING_REVISIONS_ENABLED", False),
                     "No sense with revs")
    def test_install_outdated(self):
        # If we try to install the same package with --build oudated it's already ok
        self.client.run("install Hello0/0.1@lasote/stable --build outdated")
        self.assertIn("Hello0/0.1@lasote/stable: Package is up to date",
                      self.client.out)

        # Then we can export a modified recipe and try to install without --build outdated
        files = cpp_hello_conan_files("Hello0", "0.1", build=False)
        files["conanfile.py"] += "\n#Otherline"
        self.client.save(files)
        self.client.run("export . lasote/stable")
        self.client.run("install Hello0/0.1@lasote/stable")
        self.assertIn("Hello0/0.1@lasote/stable: Already installed!",
                      self.client.out)
        self.assertNotIn("Package is up to date", self.client.out)
        self.assertNotIn("Outdated package!", self.client.out)

        # Try now with the --build outdated
        self.client.run("install Hello0/0.1@lasote/stable --build outdated")
        self.assertNotIn("Package is up to date", self.client.out)
        self.assertIn("Outdated package!", self.client.out)
        self.assertIn("Building your package", self.client.out)

        # Remove all local references, export again (the modified version not uploaded)
        # and try to install, it will discard the remote package too
        self.client.run("remove Hello0* -f")
        self.client.save(files)
        self.client.run("export . lasote/stable")
        self.client.run("remote add_ref Hello0/0.1@lasote/stable default")
        self.client.run("install Hello0/0.1@lasote/stable --build outdated")
        self.assertNotIn("Hello0/0.1@lasote/stable: Already installed!",
                         self.client.out)
        self.assertNotIn("Package is up to date", self.client.out)
        self.assertIn("Building your package", self.client.out)

    def test_install_outdated_dep(self):
        # A new recipe that depends on Hello0/0.1
        new_client = TestClient(servers=self.servers,
                                users={"default": [("lasote", "mypass")]})
        files = cpp_hello_conan_files("Hello1",
                                      "0.1", ["Hello0/0.1@lasote/stable"],
                                      build=False)
        new_client.save(files)
        new_client.run("export . lasote/stable")
        self.assertIn("A new conanfile.py version was exported",
                      new_client.out)
        # It will retrieve from the remote Hello0 and build Hello1
        new_client.run("install Hello1/0.1@lasote/stable --build missing")

        # Then modify REMOTE Hello0 recipe files (WITH THE OTHER CLIENT)
        files = cpp_hello_conan_files("Hello0", "0.1", build=False)
        files["conanfile.py"] += "\n#MODIFIED RECIPE"
        self.client.save(files)
        self.client.run("export . lasote/stable")
        self.assertIn("A new conanfile.py version was exported",
                      self.client.out)
        self.client.run("install Hello0/0.1@lasote/stable --build missing")
        # Upload only the recipe, so the package is outdated in the server
        self.client.run("upload Hello0/0.1@lasote/stable")

        # Now, with the new_client, remove only the binary package from Hello0
        rmdir(new_client.cache.package_layout(self.ref).packages())
        # And try to install Hello1 again, should not complain because the remote
        # binary is in the "same version" than local cached Hello0
        new_client.run("install Hello1/0.1@lasote/stable --build outdated")
        self.assertIn("Downloading conan_package.tgz", new_client.out)
        self.assertIn("Hello0/0.1@lasote/stable: Package is up to date",
                      new_client.out)

        # With revisions makes no sense, it won't download an outdated package, it belongs to
        # a different recipe
        if not new_client.cache.config.revisions_enabled:
            # But if we remove the full Hello0 local package, will retrieve the updated
            # recipe and the outdated package
            new_client.run("remove Hello0* -f")
            new_client.run("install Hello1/0.1@lasote/stable --build outdated")
            self.assertIn("Hello0/0.1@lasote/stable: Outdated package!",
                          new_client.out)
            self.assertIn("Hello0/0.1@lasote/stable: Building your package",
                          new_client.out)

    def test_install_outdated_and_dep(self):
        # regression test for https://github.com/conan-io/conan/issues/1053
        # A new recipe that depends on Hello0/0.1
        new_client = TestClient(servers=self.servers,
                                users={"default": [("lasote", "mypass")]})
        files = cpp_hello_conan_files("Hello1",
                                      "0.1", ["Hello0/0.1@lasote/stable"],
                                      build=False)
        new_client.save(files)
        new_client.run("export . lasote/stable")
        self.assertIn("A new conanfile.py version was exported",
                      new_client.out)
        # It will retrieve from the remote Hello0 and build Hello1
        new_client.run("install Hello1/0.1@lasote/stable --build missing")

        # Then modify REMOTE Hello0 recipe files (WITH THE OTHER CLIENT)
        files = cpp_hello_conan_files("Hello0", "0.1", build=False)
        files["conanfile.py"] += "\n#MODIFIED RECIPE"
        self.client.save(files)
        self.client.run("export . lasote/stable")
        self.assertIn("A new conanfile.py version was exported",
                      self.client.out)
        self.client.run("install Hello0/0.1@lasote/stable --build missing")
        # Upload only the recipe, so the package is outdated in the server
        self.client.run("upload Hello0/0.1@lasote/stable")

        # Now, with the new_client, remove only the binary package from Hello0
        rmdir(new_client.cache.package_layout(self.ref).packages())
        # And try to install Hello1 again, should not complain because the remote
        # binary is in the "same version" than local cached Hello0
        new_client.run(
            "install Hello1/0.1@lasote/stable --build outdated --build Hello1")
        self.assertIn("Downloading conan_package.tgz", new_client.out)
        self.assertIn("Hello1/0.1@lasote/stable: Forced build from source",
                      new_client.out)

    def test_install_outdated_checking_updates(self):
        server = TestServer()
        servers = OrderedDict([("default", server)])
        client = TurboTestClient(servers=servers)
        client2 = TurboTestClient(servers=servers)

        ref = ConanFileReference.loads("lib/1.0@conan/testing")
        client.create(ref)
        client.upload_all(ref)

        # Generate a new recipe, the binary becomes outdated
        time.sleep(1)
        client2.create(
            ref,
            conanfile=GenConanfile().with_build_msg("Some modified stuff"))
        client2.run("upload {} -r default".format(ref))

        # Update, building the outdated
        client.run("install -u -b outdated {}".format(ref))
        # The outdated is built
        self.assertIn("Some modified stuff", client.out)
Beispiel #56
0
def _get_env_cmake_system_name():
    env_system_name = get_env("CONAN_CMAKE_SYSTEM_NAME", "")
    return {"False": False, "True": True, "": None}.get(env_system_name, env_system_name)