Repository: Cog-Creators/Red-DiscordBot

Issue:
[Downloader] Show more specific message, when repo can't be found
<!-- 
Please be sure to use the correct template, 
if your report doesn't have the correct template please open an issue describing your issue in detail
For support regarding the bot itself please visit the discord server over at https://discord.gg/red
-->
Currently when using command for nonexistent repo:
```
[p]repo add oof https://github.com/non-existent-user/non-existent-repo
```
Bot responds with "Something went wrong during the cloning process."
I think the message should be more specific than that.


Discussion:
Also if you try to use (only user exists):
```
[p]repo add oof https://github.com/jack1142/non-existent-repo
```
git will ask you for github credentials, even though the repo doesn't exist at all. This is a little more tricky though, because you can't possibly know if that person doesn't have private repo under that name, but I think it would still better to tell something more specific in the error message.

Resolving patch:
diff --git a/redbot/cogs/downloader/downloader.py b/redbot/cogs/downloader/downloader.py
--- a/redbot/cogs/downloader/downloader.py
+++ b/redbot/cogs/downloader/downloader.py
@@ -566,6 +566,20 @@ async def _repo_add(
             await ctx.send(
                 _("The repo name you provided is already in use. Please choose another name.")
             )
+        except errors.AuthenticationError as err:
+            await ctx.send(
+                _(
+                    "Failed to authenticate or repository does not exist."
+                    " See logs for more information."
+                )
+            )
+            log.exception(
+                "Something went wrong whilst cloning %s (to revision: %s)",
+                repo_url,
+                branch,
+                exc_info=err,
+            )
+
         except errors.CloningError as err:
             await ctx.send(
                 _(
diff --git a/redbot/cogs/downloader/errors.py b/redbot/cogs/downloader/errors.py
--- a/redbot/cogs/downloader/errors.py
+++ b/redbot/cogs/downloader/errors.py
@@ -13,6 +13,7 @@
     "CopyingError",
     "ExistingGitRepo",
     "MissingGitRepo",
+    "AuthenticationError",
     "CloningError",
     "CurrentHashError",
     "HardResetError",
@@ -79,6 +80,15 @@ class MissingGitRepo(DownloaderException):
     pass
 
 
+class AuthenticationError(GitException):
+    """
+    Thrown when git failed to authenticate with
+    the server
+    """
+
+    pass
+
+
 class CloningError(GitException):
     """
     Thrown when git clone returns a non zero exit code.
diff --git a/redbot/cogs/downloader/repo_manager.py b/redbot/cogs/downloader/repo_manager.py
--- a/redbot/cogs/downloader/repo_manager.py
+++ b/redbot/cogs/downloader/repo_manager.py
@@ -188,6 +188,17 @@ def _existing_git_repo(self) -> Tuple[bool, Path]:
         git_path = self.folder_path / ".git"
         return git_path.exists(), git_path
 
+    def _parse_git_error(self, git_command: str, stderr: str) -> errors.GitException:
+        stderr = stderr.lower()
+        # Expected to catch:
+        #   Could not read from remote repository
+        #   could not read X for 'URL': terminal prompts disabled
+        #   Authentication failed
+        if "could not read" in stderr or "authentication failed" in stderr:
+            return errors.AuthenticationError("Failed to Authenticate", git_command)
+
+        return errors.CloningError("Error when running git clone.", git_command)
+
     async def is_ancestor(self, maybe_ancestor_rev: str, descendant_rev: str) -> bool:
         """
         Check if the first is an ancestor of the second.
@@ -548,13 +559,20 @@ async def _run(
         """
         env = os.environ.copy()
         env["GIT_TERMINAL_PROMPT"] = "0"
+        env["GIT_TRACE"] = "0"
+        # make sure we never enter an askpass routine
+        # https://github.com/git/git/blob/1424303/prompt.c#L56
         env.pop("GIT_ASKPASS", None)
+        env.pop("SSH_ASKPASS", None)
         # attempt to force all output to plain ascii english
         # some methods that parse output may expect it
         # according to gettext manual both variables have to be set:
         # https://www.gnu.org/software/gettext/manual/gettext.html#Locale-Environment-Variables
         env["LC_ALL"] = "C"
         env["LANGUAGE"] = "C"
+        # Make sure git does not consider us smart
+        # https://github.com/git/git/blob/a7312d1a2/editor.c#L11-L15
+        env["TERM"] = "dumb"
         kwargs["env"] = env
         async with self._repo_lock:
             p: CompletedProcess = await asyncio.get_running_loop().run_in_executor(
@@ -659,7 +677,7 @@ async def clone(self) -> Tuple[Installable, ...]:
         if p.returncode:
             # Try cleaning up folder
             shutil.rmtree(str(self.folder_path), ignore_errors=True)
-            raise errors.CloningError("Error when running git clone.", git_command)
+            raise self._parse_git_error(git_command, p.stderr.decode(**DECODE_PARAMS))
 
         if self.branch is None:
             self.branch = await self.current_branch()


Test patch: