import os
import shutil
from six.moves.urllib.parse import urlparse

from conans.tools import unzip
from conans.util.files import rmdir, mkdir
from conans.client.remote_registry import RemoteRegistry
from conans import tools
from conans.errors import ConanException
import subprocess


def _hide_password(resource):
    """
    Hide password from url/file path

    :param resource: string with url or file path
    :return: resource with hidden password if present
    """
    password = urlparse(resource).password
    return resource.replace(password, "<hidden>") if password else resource


def _handle_remotes(registry_path, remote_file, output):
    registry = RemoteRegistry(registry_path, output)
    new_registry = RemoteRegistry(remote_file, output)
    registry.define_remotes(new_registry.remotes)


def _handle_profiles(source_folder, target_folder, output):
    mkdir(target_folder)
    for root, _, files in os.walk(source_folder):
        relative_path = os.path.relpath(root, source_folder)
        if relative_path == ".":
            relative_path = ""
        for f in files:
            profile = os.path.join(relative_path, f)
            output.info("    Installing profile %s" % profile)
            shutil.copy(os.path.join(root, f), os.path.join(target_folder, profile))


def _process_git_repo(repo_url, client_cache, output, tmp_folder, verify_ssl):
    output.info("Trying to clone repo  %s" % repo_url)

    with tools.chdir(tmp_folder):
        try:
            subprocess.check_output('git -c http.sslVerify=%s clone "%s" config' % (verify_ssl, repo_url),
                                    shell=True)
            output.info("Repo cloned")
        except Exception as e:
            raise ConanException("config install error. Can't clone repo: %s" % str(e))

    tmp_folder = os.path.join(tmp_folder, "config")
    _process_folder(tmp_folder, client_cache, output)


def _process_zip_file(zippath, client_cache, output, tmp_folder, remove=False):
    unzip(zippath, tmp_folder)
    if remove:
        os.unlink(zippath)
    _process_folder(tmp_folder, client_cache, output)


def _handle_conan_conf(current_conan_conf, new_conan_conf_path):
    current_conan_conf.read(new_conan_conf_path)
    with open(current_conan_conf.filename, "w") as f:
        current_conan_conf.write(f)


def _process_folder(folder, client_cache, output):
    for root, dirs, files in os.walk(folder):
        for f in files:
            if f == "settings.yml":
                output.info("Installing settings.yml")
                settings_path = client_cache.settings_path
                shutil.copy(os.path.join(root, f), settings_path)
            elif f == "conan.conf":
                output.info("Processing conan.conf")
                conan_conf = client_cache.conan_config
                _handle_conan_conf(conan_conf, os.path.join(root, f))
            elif f == "remotes.txt":
                output.info("Defining remotes")
                registry_path = client_cache.registry
                _handle_remotes(registry_path, os.path.join(root, f), output)
            else:
                relpath = os.path.relpath(root, folder)
                target_folder = os.path.join(client_cache.conan_folder, relpath)
                mkdir(target_folder)
                output.info("Copying file %s to %s" % (f, target_folder))
                shutil.copy(os.path.join(root, f), target_folder)
        for d in dirs:
            if d == "profiles":
                output.info("Installing profiles")
                profiles_path = client_cache.profiles_path
                _handle_profiles(os.path.join(root, d), profiles_path, output)
                break
        dirs[:] = [d for d in dirs if d not in ("profiles", ".git")]


def _process_download(item, client_cache, output, tmp_folder, verify_ssl):
    output.info("Trying to download  %s" % _hide_password(item))
    zippath = os.path.join(tmp_folder, "config.zip")
    try:
        tools.download(item, zippath, out=output, verify=verify_ssl)
        _process_zip_file(zippath, client_cache, output, tmp_folder, remove=True)
    except Exception as e:
        raise ConanException("Error while installing config from %s\n%s" % (item, str(e)))


def configuration_install(item, client_cache, output, verify_ssl, config_type=None):
    tmp_folder = os.path.join(client_cache.conan_folder, "tmp_config_install")
    # necessary for Mac OSX, where the temp folders in /var/ are symlinks to /private/var/
    tmp_folder = os.path.realpath(tmp_folder)
    mkdir(tmp_folder)
    try:
        if item is None:
            try:
                item = client_cache.conan_config.get_item("general.config_install")
            except ConanException:
                raise ConanException("Called config install without arguments and "
                                     "'general.config_install' not defined in conan.conf")

        if item.endswith(".git") or config_type == "git":
            _process_git_repo(item, client_cache, output, tmp_folder, verify_ssl)
        elif os.path.exists(item):
            # is a local file
            _process_zip_file(item, client_cache, output, tmp_folder)
        elif item.startswith("http"):
            _process_download(item, client_cache, output, tmp_folder, verify_ssl)
        else:
            raise ConanException("I don't know how to process %s" % item)
    finally:
        if item:
            client_cache.conan_config.set_item("general.config_install", item)
        rmdir(tmp_folder)

conans/client/conf/config_installer.py
import os
import shutil
from six.moves.urllib.parse import urlparse

from conans.tools import unzip
from conans.util.files import rmdir, mkdir
from conans.client.remote_registry import RemoteRegistry
from conans import tools
from conans.errors import ConanException
import subprocess


def _hide_password(resource):
    """
    Hide password from url/file path

    :param resource: string with url or file path
    :return: resource with hidden password if present
    """
    password = urlparse(resource).password
    return resource.replace(password, "<hidden>") if password else resource


def _handle_remotes(registry_path, remote_file, output):
    registry = RemoteRegistry(registry_path, output)
    new_registry = RemoteRegistry(remote_file, output)
    registry.define_remotes(new_registry.remotes)


def _handle_profiles(source_folder, target_folder, output):
    mkdir(target_folder)
    for root, _, files in os.walk(source_folder):
        relative_path = os.path.relpath(root, source_folder)
        if relative_path == ".":
            relative_path = ""
        for f in files:
            profile = os.path.join(relative_path, f)
            output.info("    Installing profile %s" % profile)
            shutil.copy(os.path.join(root, f), os.path.join(target_folder, profile))


def _process_git_repo(repo_url, client_cache, output, tmp_folder, verify_ssl):
    output.info("Trying to clone repo  %s" % repo_url)

    with tools.chdir(tmp_folder):
        try:
            subprocess.check_output('git -c http.sslVerify=%s -c init.templateDir= clone "%s" config' % (verify_ssl, repo_url),
                                    shell=True)
            output.info("Repo cloned")
        except Exception as e:
            raise ConanException("config install error. Can't clone repo: %s" % str(e))

    tmp_folder = os.path.join(tmp_folder, "config")
    _process_folder(tmp_folder, client_cache, output)


def _process_zip_file(zippath, client_cache, output, tmp_folder, remove=False):
    unzip(zippath, tmp_folder)
    if remove:
        os.unlink(zippath)
    _process_folder(tmp_folder, client_cache, output)


def _handle_conan_conf(current_conan_conf, new_conan_conf_path):
    current_conan_conf.read(new_conan_conf_path)
    with open(current_conan_conf.filename, "w") as f:
        current_conan_conf.write(f)


def _process_folder(folder, client_cache, output):
    for root, dirs, files in os.walk(folder):
        for f in files:
            if f == "settings.yml":
                output.info("Installing settings.yml")
                settings_path = client_cache.settings_path
                shutil.copy(os.path.join(root, f), settings_path)
            elif f == "conan.conf":
                output.info("Processing conan.conf")
                conan_conf = client_cache.conan_config
                _handle_conan_conf(conan_conf, os.path.join(root, f))
            elif f == "remotes.txt":
                output.info("Defining remotes")
                registry_path = client_cache.registry
                _handle_remotes(registry_path, os.path.join(root, f), output)
            else:
                relpath = os.path.relpath(root, folder)
                target_folder = os.path.join(client_cache.conan_folder, relpath)
                mkdir(target_folder)
                output.info("Copying file %s to %s" % (f, target_folder))
                shutil.copy(os.path.join(root, f), target_folder)
        for d in dirs:
            if d == "profiles":
                output.info("Installing profiles")
                profiles_path = client_cache.profiles_path
                _handle_profiles(os.path.join(root, d), profiles_path, output)
                break
        dirs[:] = [d for d in dirs if d not in ("profiles", ".git")]


def _process_download(item, client_cache, output, tmp_folder, verify_ssl):
    output.info("Trying to download  %s" % _hide_password(item))
    zippath = os.path.join(tmp_folder, "config.zip")
    try:
        tools.download(item, zippath, out=output, verify=verify_ssl)
        _process_zip_file(zippath, client_cache, output, tmp_folder, remove=True)
    except Exception as e:
        raise ConanException("Error while installing config from %s\n%s" % (item, str(e)))


def configuration_install(item, client_cache, output, verify_ssl, config_type=None):
    tmp_folder = os.path.join(client_cache.conan_folder, "tmp_config_install")
    # necessary for Mac OSX, where the temp folders in /var/ are symlinks to /private/var/
    tmp_folder = os.path.realpath(tmp_folder)
    mkdir(tmp_folder)
    try:
        if item is None:
            try:
                item = client_cache.conan_config.get_item("general.config_install")
            except ConanException:
                raise ConanException("Called config install without arguments and "
                                     "'general.config_install' not defined in conan.conf")

        if item.endswith(".git") or config_type == "git":
            _process_git_repo(item, client_cache, output, tmp_folder, verify_ssl)
        elif os.path.exists(item):
            # is a local file
            _process_zip_file(item, client_cache, output, tmp_folder)
        elif item.startswith("http"):
            _process_download(item, client_cache, output, tmp_folder, verify_ssl)
        else:
            raise ConanException("I don't know how to process %s" % item)
    finally:
        if item:
            client_cache.conan_config.set_item("general.config_install", item)
        rmdir(tmp_folder)

conans/client/conf/config_installer.py
diff --git a/conans/client/conf/config_installer.py b/conans/client/conf/config_installer.py
index 73af07c8789..04aa640e820 100644
--- a/conans/client/conf/config_installer.py
+++ b/conans/client/conf/config_installer.py
@@ -44,7 +44,7 @@ def _process_git_repo(repo_url, client_cache, output, tmp_folder, verify_ssl):
 
     with tools.chdir(tmp_folder):
         try:
-            subprocess.check_output('git -c http.sslVerify=%s clone "%s" config' % (verify_ssl, repo_url),
+            subprocess.check_output('git -c http.sslVerify=%s -c init.templateDir= clone "%s" config' % (verify_ssl, repo_url),
                                     shell=True)
             output.info("Repo cloned")
         except Exception as e:

Consider turning off template directories in Git for conan config install
To help us debug your issue please explain:

- [x] I've read the [CONTRIBUTING guide](https://raw.githubusercontent.com/conan-io/conan/develop/.github/CONTRIBUTING.md).
- [x] I've specified the Conan version, operating system version and any tool that can be relevant.
- [x] I've explained the steps to reproduce the error or the motivation/use case of the question/suggestion.

This is with Conan 1.6.0 on Windows 10.

To see this in progress, have a Git installation set up with automatic ctags generation akin to what's described in [Effortless Ctags with Git](https://tbaggery.com/2011/08/08/effortless-ctags-with-git.html).

When doing `conan config install` with a Git URL, I get error messages like this:

```
Traceback (most recent call last):
  File "c:\users\kam\.virtualenvs\skel-hv6zqtfh\lib\shutil.py", line 391, in _rmtree_unsafe
    os.rmdir(path)
OSError: [WinError 145] The directory is not empty: 'C:\\Users\\kam\\.conan\\tmp_config_install\\config\\.git\\hooks'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "c:\users\kam\.virtualenvs\skel-hv6zqtfh\lib\site-packages\conans\client\command.py", line 1230, in run
    method(args[0][1:])
  File "c:\users\kam\.virtualenvs\skel-hv6zqtfh\lib\site-packages\conans\client\command.py", line 379, in config
    return self._conan.config_install(args.item, verify_ssl, args.type)
  File "c:\users\kam\.virtualenvs\skel-hv6zqtfh\lib\site-packages\conans\client\conan_api.py", line 79, in wrapper
    return f(*args, **kwargs)
  File "c:\users\kam\.virtualenvs\skel-hv6zqtfh\lib\site-packages\conans\client\conan_api.py", line 510, in config_install
    return configuration_install(item, self._client_cache, self._user_io.out, verify_ssl, config_type)
  File "c:\users\kam\.virtualenvs\skel-hv6zqtfh\lib\site-packages\conans\client\conf\config_installer.py", line 135, in configuration_install
    rmdir(tmp_folder)
  File "c:\users\kam\.virtualenvs\skel-hv6zqtfh\lib\site-packages\conans\util\files.py", line 202, in rmdir
    shutil.rmtree(path, onerror=_change_permissions)
  File "c:\users\kam\.virtualenvs\skel-hv6zqtfh\lib\shutil.py", line 494, in rmtree
    return _rmtree_unsafe(path, onerror)
  File "c:\users\kam\.virtualenvs\skel-hv6zqtfh\lib\shutil.py", line 384, in _rmtree_unsafe
    _rmtree_unsafe(fullname, onerror)
  File "c:\users\kam\.virtualenvs\skel-hv6zqtfh\lib\shutil.py", line 384, in _rmtree_unsafe
    _rmtree_unsafe(fullname, onerror)
  File "c:\users\kam\.virtualenvs\skel-hv6zqtfh\lib\shutil.py", line 384, in _rmtree_unsafe
    _rmtree_unsafe(fullname, onerror)
  File "c:\users\kam\.virtualenvs\skel-hv6zqtfh\lib\shutil.py", line 393, in _rmtree_unsafe
    onerror(os.rmdir, path, sys.exc_info())
  File "c:\users\kam\.virtualenvs\skel-hv6zqtfh\lib\site-packages\conans\util\files.py", line 197, in _change_permissions
    raise OSError("Cannot change permissions for {}! Exception info: {}".format(path, exc_info))
OSError: Cannot change permissions for C:\Users\kam\.conan\tmp_config_install\config\.git\hooks! Exception info: (<class 'OSError'>, OSError(41, 'The directory is not empty'), <traceback object at 0x0000016409078548>)

ERROR: Cannot change permissions for C:\Users\kam\.conan\tmp_config_install\config\.git\hooks! Exception info: (<class 'OSError'>, OSError(41, 'The directory is not empty'), <traceback object at 0x0000016409078548>)
```

The problem boils down to the way files are locked on Windows. It's not possible to delete open files. But the hook starts a background process which has the script files open, and the cleanup of the directory fails. Of course, a second later, the directory can be deleted as files are closed and unlocked.

I've since started reworking my Git template to not start background processes by default, and only run `ctags` in checkouts that I'm actually developing on. This fixes my problem with `conan config install`.

It may make sense, though, to add `-c init.templateDir=` to the `git` command line when working on temporary downloads. It's part of sanitizing the process against user configuration: In a hook, _anything_ can happen, and the errors are obscure and difficult to understand.

`conan config install` is mostly treating a Git repository as a sophisticated form of file archive, and probably doesn't want the user's hooks or other unusual setups from the template.

