Repository: conan-io/conan

Issue:
[TFS-Git repo] can't install config
When specifying a git repo hosted on TFS 2017, the "conan config install" fails withouth trying to do a "git clone".
It does work when pointing to a github repo
Git repos URL on TFS don't end by ".git"

Conan version : 1.4.5
OS :  Ubuntu 16.04 (xenial)
 
```/home/jfrog/.local/bin/conan config install  --verify-ssl=False http://<TFS_HOST>:8080/tfs/DefaultCollection/Conan-Demo/_git/Conan-config
Trying to download  http://<TFS_HOST>:8080/tfs/DefaultCollection/Conan-Demo/_git/Conan-config

Traceback (most recent call last):
  File "/home/jfrog/.local/lib/python3.5/site-packages/conans/client/command.py", line 1182, in run
    method(args[0][1:])
  File "/home/jfrog/.local/lib/python3.5/site-packages/conans/client/command.py", line 377, in config
    return self._conan.config_install(args.item, verify_ssl)
  File "/home/jfrog/.local/lib/python3.5/site-packages/conans/client/conan_api.py", line 78, in wrapper
    return f(*args, **kwargs)
  File "/home/jfrog/.local/lib/python3.5/site-packages/conans/client/conan_api.py", line 509, in config_install
    return configuration_install(item, self._client_cache, self._user_io.out, verify_ssl)
  File "/home/jfrog/.local/lib/python3.5/site-packages/conans/client/conf/config_installer.py", line 126, in configuration_install
    _process_download(item, client_cache, output, tmp_folder, verify_ssl)
  File "/home/jfrog/.local/lib/python3.5/site-packages/conans/client/conf/config_installer.py", line 104, in _process_download
    _process_zip_file(zippath, client_cache, output, tmp_folder, remove=True)
  File "/home/jfrog/.local/lib/python3.5/site-packages/conans/client/conf/config_installer.py", line 58, in _process_zip_file
    unzip(zippath, tmp_folder)
  File "/home/jfrog/.local/lib/python3.5/site-packages/conans/client/tools/files.py", line 81, in unzip
    with zipfile.ZipFile(filename, "r") as z:
  File "/usr/lib/python3.5/zipfile.py", line 1026, in __init__
    self._RealGetContents()
  File "/usr/lib/python3.5/zipfile.py", line 1093, in _RealGetContents
    raise BadZipFile("File is not a zip file")
zipfile.BadZipFile: File is not a zip file
ERROR: File is not a zip file
```




Discussion:
Quick question. Even if the URL provided by TFS, what happens if you add ".git" to the end of that http URL? And if you add "/.git" to the end of the URL? Could you please paste here the errors that happen?
Thanks!
so what seems to be happening is that in configuration_install we have:
         if item.endswith(".git"):
            _process_git_repo(item, client_cache, output, tmp_folder, verify_ssl)

and otherwise it falls to process zip file if it is a URL -- but since the file isn't a zip file, we are getting this stack trace.  We might be able to look for the _git and/or the tfs in the URL to make this distinction for TFS repos?
Yeah, we could look for git or tfs in the url, but seems a bit fragile too (what if /ip/path/to/magit/file).
``git`` itself migth be smart to strip the last ".git" or "/.git" from an URL. Otherwise, I'll suggest some additional syntax to define it is a git repo.

Resolving patch:
diff --git a/conans/client/command.py b/conans/client/command.py
--- a/conans/client/command.py
+++ b/conans/client/command.py
@@ -359,6 +359,8 @@ def config(self, *args):
 
         install_subparser.add_argument("--verify-ssl", nargs="?", default="True",
                                        help='Verify SSL connection when downloading file')
+        install_subparser.add_argument("--type", "-t", choices=["git"],
+                                       help='Type of remote config')
 
         args = parser.parse_args(*args)
 
@@ -374,7 +376,7 @@ def config(self, *args):
             return self._conan.config_rm(args.item)
         elif args.subcommand == "install":
             verify_ssl = get_bool_from_text(args.verify_ssl)
-            return self._conan.config_install(args.item, verify_ssl)
+            return self._conan.config_install(args.item, verify_ssl, args.type)
 
     def info(self, *args):
         """Gets information about the dependency graph of a recipe. It can be used with a recipe
diff --git a/conans/client/conan_api.py b/conans/client/conan_api.py
--- a/conans/client/conan_api.py
+++ b/conans/client/conan_api.py
@@ -505,9 +505,9 @@ def config_rm(self, item):
         self._client_cache.invalidate()
 
     @api_method
-    def config_install(self, item, verify_ssl):
+    def config_install(self, item, verify_ssl, config_type=None):
         from conans.client.conf.config_installer import configuration_install
-        return configuration_install(item, self._client_cache, self._user_io.out, verify_ssl)
+        return configuration_install(item, self._client_cache, self._user_io.out, verify_ssl, config_type)
 
     def _info_get_profile(self, reference, install_folder, profile_name, settings, options, env):
         cwd = get_cwd()
diff --git a/conans/client/conf/config_installer.py b/conans/client/conf/config_installer.py
--- a/conans/client/conf/config_installer.py
+++ b/conans/client/conf/config_installer.py
@@ -100,11 +100,14 @@ def _process_folder(folder, client_cache, output):
 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")
-    tools.download(item, zippath, out=output, verify=verify_ssl)
-    _process_zip_file(zippath, client_cache, output, tmp_folder, remove=True)
+    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):
+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)
@@ -117,7 +120,7 @@ def configuration_install(item, client_cache, output, verify_ssl):
                 raise ConanException("Called config install without arguments and "
                                      "'general.config_install' not defined in conan.conf")
 
-        if item.endswith(".git"):
+        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


Test patch:
diff --git a/conans/test/command/config_install_test.py b/conans/test/command/config_install_test.py
--- a/conans/test/command/config_install_test.py
+++ b/conans/test/command/config_install_test.py
@@ -199,6 +199,14 @@ def failed_install_repo_test(self):
         self.assertTrue(error)
         self.assertIn("ERROR: config install error. Can't clone repo", self.client.out)
 
+    def failed_install_http_test(self):
+        """ should install from a http zip
+        """
+        error = self.client.run('config install httpnonexisting', ignore_error=True)
+        self.assertTrue(error)
+        self.assertIn("ERROR: Error while installing config from httpnonexisting",
+                      self.client.out)
+
     def install_repo_test(self):
         """ should install from a git repo
         """
@@ -214,6 +222,12 @@ def install_repo_test(self):
         self.client.run('config install "%s/.git"' % folder)
         self._check("%s/.git" % folder)
 
+    def force_git_type_test(self):
+        client = TestClient()
+        error = client.run('config install httpnonexisting --type=git', ignore_error=True)
+        self.assertTrue(error)
+        self.assertIn("Can't clone repo", client.out)
+
     def reinstall_test(self):
         """ should use configured URL in conan.conf
         """