Преглед на файлове

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));