فهرست منبع

Use https fallback for github private repos if ssh protocol fails and we can ask the user's password

Jordi Boggiano 13 سال پیش
والد
کامیت
a9fe883827
2فایلهای تغییر یافته به همراه40 افزوده شده و 2 حذف شده
  1. 30 0
      src/Composer/Downloader/GitDownloader.php
  2. 10 2
      tests/Composer/Test/Downloader/GitDownloaderTest.php

+ 30 - 0
src/Composer/Downloader/GitDownloader.php

@@ -46,6 +46,12 @@ class GitDownloader extends VcsDownloader
         $this->io->write("    Checking out ".$target->getSourceReference());
         $command = 'cd %s && git remote set-url composer %s && git fetch composer && git fetch --tags composer && git checkout %3$s && git reset --hard %3$s';
 
+        // capture username/password from github URL if there is one
+        $this->process->execute(sprintf('cd %s && git remote -v', escapeshellarg($path)), $output);
+        if (preg_match('{^composer\s+https://(.+):(.+)@github.com/}im', $output, $match)) {
+            $this->io->setAuthorization('github.com', $match[1], $match[2]);
+        }
+
         // TODO: BC for the composer remote that didn't exist, to be remove after May 18th.
         $this->process->execute(sprintf('cd %s && git remote add composer %s', escapeshellarg($path), escapeshellarg($initial->getSourceUrl())), $ignoredOutput);
 
@@ -102,6 +108,30 @@ class GitDownloader extends VcsDownloader
 
         $command = call_user_func($commandCallable, $url);
         if (0 !== $this->process->execute($command, $handler)) {
+            if (preg_match('{^git@github.com:(.+?)\.git$}i', $url, $match) && $this->io->isInteractive()) {
+                // private repository without git access, try https with auth
+                $retries = 3;
+                $retrying = false;
+                do {
+                    if ($retrying) {
+                        $this->io->write('Invalid credentials');
+                    }
+                    if (!$this->io->hasAuthorization('github.com') || $retrying) {
+                        $username = $this->io->ask('Username: ');
+                        $password = $this->io->askAndHideAnswer('Password: ');
+                        $this->io->setAuthorization('github.com', $username, $password);
+                    }
+
+                    $auth = $this->io->getAuthorization('github.com');
+                    $url = 'https://'.$auth['username'] . ':' . $auth['password'] . '@github.com/'.$match[1].'.git';
+
+                    $command = call_user_func($commandCallable, $url);
+                    if (0 === $this->process->execute($command, $handler)) {
+                        return;
+                    }
+                    $retrying = true;
+                } while (--$retries);
+            }
             $this->throwException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput(), $url);
         }
     }

+ 10 - 2
tests/Composer/Test/Downloader/GitDownloaderTest.php

@@ -156,9 +156,13 @@ class GitDownloaderTest extends \PHPUnit_Framework_TestCase
             ->will($this->returnValue(0));
         $processExecutor->expects($this->at(1))
             ->method('execute')
-            ->with($this->equalTo($this->getCmd("cd 'composerPath' && git remote add composer 'https://github.com/composer/composer'")))
+            ->with($this->equalTo($this->getCmd("cd 'composerPath' && git remote -v")))
             ->will($this->returnValue(0));
         $processExecutor->expects($this->at(2))
+            ->method('execute')
+            ->with($this->equalTo($this->getCmd("cd 'composerPath' && git remote add composer 'https://github.com/composer/composer'")))
+            ->will($this->returnValue(0));
+        $processExecutor->expects($this->at(3))
             ->method('execute')
             ->with($this->equalTo($expectedGitUpdateCommand))
             ->will($this->returnValue(0));
@@ -189,9 +193,13 @@ class GitDownloaderTest extends \PHPUnit_Framework_TestCase
             ->will($this->returnValue(0));
         $processExecutor->expects($this->at(1))
             ->method('execute')
-            ->with($this->equalTo($this->getCmd("cd 'composerPath' && git remote add composer 'https://github.com/composer/composer'")))
+            ->with($this->equalTo($this->getCmd("cd 'composerPath' && git remote -v")))
             ->will($this->returnValue(0));
         $processExecutor->expects($this->at(2))
+            ->method('execute')
+            ->with($this->equalTo($this->getCmd("cd 'composerPath' && git remote add composer 'https://github.com/composer/composer'")))
+            ->will($this->returnValue(0));
+        $processExecutor->expects($this->at(3))
             ->method('execute')
             ->with($this->equalTo($expectedGitUpdateCommand))
             ->will($this->returnValue(1));