PK ?V
.editorconfignu W+A ; top-most EditorConfig file
root = true
; Unix-style newlines
[*]
end_of_line = LF
[*.php]
indent_style = space
indent_size = 4
PK ?V 7 7 LICENSEnu W+A The MIT License (MIT)
Copyright (c) 2013 Acquia, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
PK ?Vc .travis.ymlnu W+A language: php
php:
- "5.6"
- "5.5"
- "5.4"
- "5.3"
before_script:
- composer install --prefer-dist --dev
after_script:
- php vendor/bin/coveralls -v
PK ?Vs4` ` .coveralls.ymlnu W+A # for php-coveralls
service_name: travis-ci
src_dir: src
coverage_clover: build/logs/clover.xml
PK ?V\Mh h bin/git-ssh-wrapper.shnu W+A #!/bin/sh
ssh -i $GIT_SSH_KEY -p $GIT_SSH_PORT -o StrictHostKeyChecking=no -o IdentitiesOnly=yes $1 $2
PK ?V;{$' ' build.xmlnu W+A
PK ?V
S5
composer.jsonnu W+A {
"name": "cpliakas/git-wrapper",
"type": "library",
"description": "A PHP wrapper around the Git command line utility.",
"keywords": ["git"],
"homepage": "https://github.com/cpliakas/git-wrapper",
"license": "MIT",
"authors": [
{
"name": "Chris Pliakas",
"email": "opensource@chrispliakas.com"
}
],
"require": {
"php": ">=5.3.0",
"symfony/process": ">=2.3",
"symfony/event-dispatcher": ">=2.3"
},
"require-dev": {
"pdepend/pdepend": "~1.0",
"phploc/phploc": "~2.0",
"phpmd/phpmd": "~1.0",
"phpunit/phpunit": "~3.0",
"psr/log": "~1.0",
"satooshi/php-coveralls": "*",
"sebastian/phpcpd": "~2.0",
"symfony/filesystem": "~2.0"
},
"suggest": {
"monolog/monolog": "Enables logging of executed git commands"
},
"autoload": {
"psr-0": {
"GitWrapper": "src/"
}
}
}
PK ?V* 7 7 test/bootstrap.phpnu W+A add('GitWrapper\Test', 'test');
$loader->register();
PK ?V test/id_rsanu W+A PK ?V # test/GitWrapper/Test/TestLogger.phpnu W+A messages[] = $message;
$this->levels[] = $level;
$this->contexts[] = $context;
}
public function clearMessages()
{
$this->messages = $this->levels = $this->contexts = array();
}
}
PK ?Vqa/ / + test/GitWrapper/Test/GitWorkingCopyTest.phpnu W+A wrapper->init(self::REPO_DIR, array('bare' => true));
// Clone the local repository.
$directory = 'build/test/wc_init';
$git = $this->wrapper->clone('file://' . realpath(self::REPO_DIR), $directory);
$git->config('user.email', self::CONFIG_EMAIL);
$git->config('user.name', self::CONFIG_NAME);
// Create the initial structure.
file_put_contents($directory . '/change.me', "unchanged\n");
$this->filesystem->touch($directory . '/move.me');
$this->filesystem->mkdir($directory . '/a.directory', 0755);
$this->filesystem->touch($directory . '/a.directory/remove.me');
// Initial commit.
$git
->add('*')
->commit('Initial commit.')
->push('origin', 'master', array('u' => true))
;
// Create a branch, add a file.
$branch = 'test-branch';
file_put_contents($directory . '/branch.txt', "$branch\n");
$git
->checkoutNewBranch($branch)
->add('branch.txt')
->commit('Committed testing branch.')
->push('origin', $branch, array('u' => true))
;
// Create a tag of the branch.
$git
->tag('test-tag')
->pushTags()
;
$this->filesystem->remove($directory);
}
/**
* Removes the local repository.
*/
public function tearDown()
{
parent::tearDown();
$this->filesystem->remove(self::REPO_DIR);
if (is_dir(self::WORKING_DIR)) {
$this->filesystem->remove(self::WORKING_DIR);
}
}
/**
* Clones the local repo and returns an initialized GitWorkingCopy object.
*
* @param string $directory
* The directory that the repository is being cloned to, defaults to
* "test/wc".
*
* @return \GitWrapper\GitWorkingCopy
*/
public function getWorkingCopy($directory = self::WORKING_DIR)
{
$git = $this->wrapper->workingCopy($directory);
$git
->cloneRepository('file://' . realpath(self::REPO_DIR))
->config('user.email', self::CONFIG_EMAIL)
->config('user.name', self::CONFIG_NAME)
->clearOutput()
;
return $git;
}
/**
* @expectedException \BadMethodCallException
*/
public function testCallError()
{
$git = $this->getWorkingCopy();
$git->badMethod();
}
public function testIsCloned()
{
$git = $this->getWorkingCopy();
$this->assertTrue($git->isCloned());
}
public function testGetOutput()
{
$git = $this->getWorkingCopy();
// Test getting output of a simple status command.
$output = (string) $git->status();
$this->assertTrue(strpos($output, 'nothing to commit') !== false);
// Getting output should clear the buffer.
$cleared = (string) $git;
$this->assertEmpty($cleared);
}
public function testClearOutput()
{
$git = $this->getWorkingCopy();
// Put stuff in the output buffer.
$git->status();
$git->clearOutput();
$output = $git->getOutput();
$this->assertEmpty($output);
}
public function testHasChanges()
{
$git = $this->getWorkingCopy();
$this->assertFalse($git->hasChanges());
file_put_contents(self::WORKING_DIR . '/change.me', "changed\n");
$this->assertTrue($git->hasChanges());
}
public function testGetBranches()
{
$git = $this->getWorkingCopy();
$branches = $git->getBranches();
$this->assertTrue($branches instanceof \GitWrapper\GitBranches);
// Dumb count checks. Is there a better way to do this?
$allBranches = 0;
foreach ($branches as $branch) {
$allBranches++;
}
$this->assertEquals($allBranches, 4);
$remoteBranches = $branches->remote();
$this->assertEquals(count($remoteBranches), 3);
}
public function testFetchAll()
{
$git = $this->getWorkingCopy();
$output = rtrim((string) $git->fetchAll());
$this->assertEquals('Fetching origin', $output);
}
public function testGitAdd()
{
$git = $this->getWorkingCopy();
$this->filesystem->touch(self::WORKING_DIR . '/add.me');
$git->add('add.me');
$match = (bool) preg_match('@A\\s+add\\.me@s', $git->getStatus());
$this->assertTrue($match);
}
public function testGitApply()
{
$git = $this->getWorkingCopy();
$patch = <<apply('patch.txt');
$this->assertRegExp('@\?\?\\s+FileCreatedByPatch\\.txt@s', $git->getStatus());
$this->assertEquals("contents\n", file_get_contents(self::WORKING_DIR . '/FileCreatedByPatch.txt'));
}
public function testGitRm()
{
$git = $this->getWorkingCopy();
$git->rm('a.directory/remove.me');
$this->assertFalse(is_file(self::WORKING_DIR . '/a.directory/remove.me'));
}
public function testGitMv()
{
$git = $this->getWorkingCopy();
$git->mv('move.me', 'moved');
$this->assertFalse(is_file(self::WORKING_DIR . '/move.me'));
$this->assertTrue(is_file(self::WORKING_DIR . '/moved'));
}
public function testGitBranch()
{
$branchName = $this->randomString();
// Create the branch.
$git = $this->getWorkingCopy();
$git->branch($branchName);
// Get list of local branches.
$branches = (string) $git->branch();
// Check that our branch is there.
$this->assertTrue(strpos($branches, $branchName) !== false);
}
public function testGitLog()
{
$git = $this->getWorkingCopy();
$output = (string) $git->log();
return $this->assertTrue(strpos($output, 'Initial commit.') !== false);
}
public function testGitConfig()
{
$git = $this->getWorkingCopy();
$email = rtrim((string) $git->config('user.email'));
$this->assertEquals('opensource@chrispliakas.com', $email);
}
public function testGitTag()
{
$tag = $this->randomString();
$git = $this->getWorkingCopy();
$git
->tag($tag)
->pushTag($tag)
;
$tags = (string) $git->tag();
$this->assertTrue(strpos($tags, $tag) !== false);
}
public function testGitClean()
{
$git = $this->getWorkingCopy();
file_put_contents(self::WORKING_DIR . '/untracked.file', "untracked\n");
$result = $git
->clean('-d', '-f')
;
$this->assertSame($git, $result);
$this->assertFileNotExists(self::WORKING_DIR . '/untracked.file');
}
public function testGitReset()
{
$git = $this->getWorkingCopy();
file_put_contents(self::WORKING_DIR . '/change.me', "changed\n");
$this->assertTrue($git->hasChanges());
$git->reset(array('hard' => true));
$this->assertFalse($git->hasChanges());
}
public function testGitStatus()
{
$git = $this->getWorkingCopy();
file_put_contents(self::WORKING_DIR . '/change.me', "changed\n");
$output = (string) $git->status(array('s' => true));
$this->assertEquals(" M change.me\n", $output);
}
public function testGitPull()
{
$git = $this->getWorkingCopy();
$output = (string) $git->pull();
$this->assertEquals("Already up-to-date.\n", $output);
}
/**
* This tests an odd case where sometimes even though a command fails and an exception is thrown
* the result of Process::getErrorOutput() is empty because the output is sent to STDOUT instead of STDERR. So
* there's a code path in GitProcess::run() to check the output from Process::getErrorOutput() and if it's empty use
* the result from Process::getOutput() instead
*/
public function testGitPullErrorWithEmptyErrorOutput()
{
$git = $this->getWorkingCopy();
try {
$git->commit('Nothing to commit so generates an error / not error');
} catch(GitException $exception) {
$errorOutput = $exception->getMessage();
}
$this->assertEquals("On branch master\nYour branch is up-to-date with 'origin/master'.\n\nnothing to commit, working directory clean\n", $errorOutput);
}
public function testGitDiff()
{
$git = $this->getWorkingCopy();
file_put_contents(self::WORKING_DIR . '/change.me', "changed\n");
$output = (string) $git->diff();
$this->assertTrue(strpos($output, 'diff --git a/change.me b/change.me') === 0);
}
public function testGitGrep()
{
$git = $this->getWorkingCopy();
$output = (string) $git->grep('changed', '--', '*.me');
$this->assertTrue(strpos($output, 'change.me') === 0);
}
public function testGitShow()
{
$git = $this->getWorkingCopy();
$output = (string) $git->show('test-tag');
$this->assertTrue(strpos($output, 'commit ') === 0);
}
public function testGitBisect()
{
$git = $this->getWorkingCopy();
$output = (string) $git->bisect('help');
$this->assertTrue(stripos($output, 'usage: git bisect') === 0);
}
public function testGitRemote()
{
$git = $this->getWorkingCopy();
$output = (string) $git->remote();
$this->assertEquals(rtrim($output), 'origin');
}
public function testRebase()
{
$git = $this->getWorkingCopy();
$git
->checkout('test-branch')
->clearOutput()
;
$output = (string) $git->rebase('test-branch', 'master');
$this->assertTrue(strpos($output, 'First, rewinding head') === 0);
}
public function testMerge()
{
$git = $this->getWorkingCopy();
$git
->checkout('test-branch')
->checkout('master')
->clearOutput()
;
$output = (string) $git->merge('test-branch');
$this->assertTrue(strpos($output, 'Updating ') === 0);
}
public function testOutputListener()
{
$git = $this->getWorkingCopy();
$listener = new Event\TestOutputListener();
$git->getWrapper()->addOutputListener($listener);
$git->status();
$event = $listener->getLastEvent();
$expectedType = Process::OUT;
$this->assertEquals($expectedType, $event->getType());
$this->assertTrue(stripos($event->getBuffer(), 'nothing to commit') !== false);
}
public function testLiveOutput()
{
$git = $this->getWorkingCopy();
// Capture output written to STDOUT and use echo so we can suppress and
// capture it using normal output buffering.
stream_filter_register('suppress', '\GitWrapper\Test\StreamSuppressFilter');
$stdoutSuppress = stream_filter_append(STDOUT, 'suppress');
$git->getWrapper()->streamOutput(true);
ob_start();
$git->status();
$contents = ob_get_contents();
ob_end_clean();
$this->assertTrue(stripos($contents, 'nothing to commit') !== false);
$git->clearOutput();
$git->getWrapper()->streamOutput(false);
ob_start();
$git->status();
$empty = ob_get_contents();
ob_end_clean();
$this->assertEmpty($empty);
stream_filter_remove($stdoutSuppress);
}
}
PK ?Vl ( test/GitWrapper/Test/GitListenerTest.phpnu W+A addListener();
$this->wrapper->version();
$this->assertTrue($listener->methodCalled('onPrepare'));
$this->assertTrue($listener->methodCalled('onSuccess'));
$this->assertFalse($listener->methodCalled('onError'));
$this->assertFalse($listener->methodCalled('onBypass'));
}
public function testListenerError()
{
$listener = $this->addListener();
$this->runBadCommand(true);
$this->assertTrue($listener->methodCalled('onPrepare'));
$this->assertFalse($listener->methodCalled('onSuccess'));
$this->assertTrue($listener->methodCalled('onError'));
$this->assertFalse($listener->methodCalled('onBypass'));
}
public function testGitBypass()
{
$this->addBypassListener();
$listener = $this->addListener();
$output = $this->wrapper->version();
$this->assertTrue($listener->methodCalled('onPrepare'));
$this->assertFalse($listener->methodCalled('onSuccess'));
$this->assertFalse($listener->methodCalled('onError'));
$this->assertTrue($listener->methodCalled('onBypass'));
$this->assertEmpty($output);
}
public function testEvent()
{
$process = new Process('');
$command = GitCommand::getInstance();
$event = new GitEvent($this->wrapper, $process, $command);
$this->assertEquals($this->wrapper, $event->getWrapper());
$this->assertEquals($process, $event->getProcess());
$this->assertEquals($command, $event->getCommand());
}
}
PK ?V^^ _, , - test/GitWrapper/Test/StreamSuppressFilter.phpnu W+A data;
$bucket->data = '';
$consumed += $bucket->datalen;
stream_bucket_append($out, $bucket);
}
return PSFS_PASS_ON;
}
}
PK ?V
>
>
+ test/GitWrapper/Test/GitWrapperTestCase.phpnu W+A filesystem = new Filesystem();
$this->wrapper = new GitWrapper();
}
/**
* Generates a random string.
*
* @param type $length
* The string length, defaults to 8 characters.
*
* @return string
*
* @see http://api.drupal.org/api/drupal/modules%21simpletest%21drupal_web_test_case.php/function/DrupalTestCase%3A%3ArandomName/7
*/
public function randomString($length = 8)
{
$values = array_merge(range(65, 90), range(97, 122), range(48, 57));
$max = count($values) - 1;
$str = chr(mt_rand(97, 122));
for ($i = 1; $i < $length; $i++) {
$str .= chr($values[mt_rand(0, $max)]);
}
return $str;
}
/**
* Adds the test listener for all events, returns the listener.
*
* @return \GitWrapper\Test\Event\TestListener
*/
public function addListener()
{
$dispatcher = $this->wrapper->getDispatcher();
$listener = new TestListener();
$dispatcher->addListener(GitEvents::GIT_PREPARE, array($listener, 'onPrepare'));
$dispatcher->addListener(GitEvents::GIT_SUCCESS, array($listener, 'onSuccess'));
$dispatcher->addListener(GitEvents::GIT_ERROR, array($listener, 'onError'));
$dispatcher->addListener(GitEvents::GIT_BYPASS, array($listener, 'onBypass'));
return $listener;
}
/**
* Adds the bypass listener so that Git commands are not run.
*
* @return \GitWrapper\Test\Event\TestBypassListener
*/
public function addBypassListener()
{
$listener = new TestBypassListener();
$dispatcher = $this->wrapper->getDispatcher();
$dispatcher->addListener(GitEvents::GIT_PREPARE, array($listener, 'onPrepare'), -5);
return $listener;
}
/**
* Asserts a correct Git version string was returned.
*
* @param type $version
* The version returned by the `git --version` command.
*/
public function assertGitVersion($version)
{
$match = preg_match('/^git version [.0-9]+/', $version);
$this->assertNotEmpty($match);
}
/**
* Executes a bad command.
*
* @param bool $catchException
* Whether to catch the exception to continue script execution, defaults
* to false.
*/
public function runBadCommand($catchException = false)
{
try {
$this->wrapper->git('a-bad-command');
} catch (GitException $e) {
if (!$catchException) {
throw $e;
}
}
}
}PK ?Vʓ 1 test/GitWrapper/Test/Event/TestBypassListener.phpnu W+A getCommand()->bypass();
}
}
PK ?VY
1 test/GitWrapper/Test/Event/TestOutputListener.phpnu W+A event;
}
public function handleOutput(GitOutputEvent $event)
{
$this->event = $event;
}
}
PK ?VbC - test/GitWrapper/Test/Event/TestDispatcher.phpnu W+A methods);
}
/**
* @return \GitWrapper\Event\GitEvent
*/
public function getEvent()
{
return $this->event;
}
public function onPrepare(GitEvent $event)
{
$this->methods[] = 'onPrepare';
$this->event = $event;
}
public function onSuccess(GitEvent $event)
{
$this->methods[] = 'onSuccess';
}
public function onError(GitEvent $event)
{
$this->methods[] = 'onError';
}
public function onBypass(GitEvent $event)
{
$this->methods[] = 'onBypass';
}
}
PK ?V/ . test/GitWrapper/Test/GitLoggerListenerTest.phpnu W+A assertEquals($log, $listener->getLogger());
}
public function testSetLogLevelMapping()
{
$listener = new GitLoggerListener(new NullLogger());
$listener->setLogLevelMapping('test.event', 'test-level');
$this->assertEquals('test-level', $listener->getLogLevelMapping('test.event'));
}
/**
* @expectedException \DomainException
*/
public function testGetInvalidLogLevelMapping()
{
$listener = new GitLoggerListener(new NullLogger());
$listener->getLogLevelMapping('bad.event');
}
public function testRegisterLogger()
{
$logger = new TestLogger();
$this->wrapper->addLoggerListener(new GitLoggerListener($logger));
$git = $this->wrapper->init(self::REPO_DIR, array('bare' => true));
$this->assertEquals('Git command preparing to run', $logger->messages[0]);
$this->assertEquals('Initialized empty Git repository in ' . realpath(self::REPO_DIR) . "/\n", $logger->messages[1]);
$this->assertEquals('Git command successfully run', $logger->messages[2]);
$this->assertArrayHasKey('command', $logger->contexts[0]);
$this->assertArrayHasKey('command', $logger->contexts[1]);
$this->assertArrayHasKey('error', $logger->contexts[1]);
$this->assertArrayHasKey('command', $logger->contexts[2]);
$this->assertEquals(LogLevel::INFO, $logger->levels[0]);
$this->assertEquals(LogLevel::DEBUG, $logger->levels[1]);
$this->assertEquals(LogLevel::INFO, $logger->levels[2]);
try {
$logger->clearMessages();
$git->commit('fatal: This operation must be run in a work tree');
} catch (\Exception $e) {
// Nothing to do, this is expected.
}
$this->assertEquals('Error running Git command', $logger->messages[2]);
$this->assertArrayHasKey('command', $logger->contexts[2]);
$this->assertEquals(LogLevel::ERROR, $logger->levels[2]);
}
public function testLogBypassedCommand()
{
$logger = new TestLogger();
$this->wrapper->addLoggerListener(new GitLoggerListener($logger));
$command = GitCommand::getInstance('status', array('s' => true));
$command->bypass();
$this->wrapper->run($command);
$this->assertEquals('Git command bypassed', $logger->messages[1]);
$this->assertArrayHasKey('command', $logger->contexts[1]);
$this->assertEquals(LogLevel::INFO, $logger->levels[1]);
}
public function tearDown()
{
parent::tearDown();
if (is_dir(self::REPO_DIR)) {
$this->filesystem->remove(self::REPO_DIR);
}
}
}
PK ?VTxK ' test/GitWrapper/Test/GitCommandTest.phpnu W+A randomString();
$argument = $this->randomString();
$flag = $this->randomString();
$optionName = $this->randomString();
$optionValue = $this->randomString();
$git = GitCommand::getInstance($command)
->addArgument($argument)
->setFlag($flag)
->setOption($optionName, $optionValue);
$expected = "$command --$flag --$optionName='$optionValue' '$argument'";
$commandLine = $git->getCommandLine();
$this->assertEquals($expected, $commandLine);
}
public function testOption()
{
$optionName = $this->randomString();
$optionValue = $this->randomString();
$git = GitCommand::getInstance()
->setOption($optionName, $optionValue);
$this->assertEquals($optionValue, $git->getOption($optionName));
$git->unsetOption($optionName);
$this->assertNull($git->getOption($optionName));
}
/**
* @see https://github.com/cpliakas/git-wrapper/issues/50
*/
public function testMultiOption()
{
$git = GitCommand::getInstance('test-command')
->setOption('test-arg', array(true, true));
$expected = 'test-command --test-arg --test-arg';
$commandLine = $git->getCommandLine();
$this->assertEquals($expected, $commandLine);
}
}
PK ?Vzi ' test/GitWrapper/Test/GitWrapperTest.phpnu W+A wrapper->setGitBinary($binary);
$this->assertEquals($binary, $this->wrapper->getGitBinary());
}
public function testSetDispatcher()
{
$dispatcher = new TestDispatcher();
$this->wrapper->setDispatcher($dispatcher);
$this->assertEquals($dispatcher, $this->wrapper->getDispatcher());
}
public function testSetTimeout()
{
$timeout = mt_rand(1, 60);
$this->wrapper->setTimeout($timeout);
$this->assertEquals($timeout, $this->wrapper->getTimeout());
}
public function testEnvVar()
{
$var = $this->randomString();
$value = $this->randomString();
$this->wrapper->setEnvVar($var, $value);
$this->assertEquals($value, $this->wrapper->getEnvVar($var));
$envvars = $this->wrapper->getEnvVars();
$this->assertEquals($value, $envvars[$var]);
$this->wrapper->unsetEnvVar($var);
$this->assertNull($this->wrapper->getEnvVar($var));
}
public function testEnvVarDefault()
{
$var = $this->randomString();
$default = $this->randomString();
$this->assertEquals($default, $this->wrapper->getEnvVar($var, $default));
}
public function testProcOptions()
{
$value = (bool) mt_rand(0, 1);
$options = array('suppress_errors' => $value);
$this->wrapper->setProcOptions($options);
$this->assertEquals($options, $this->wrapper->getProcOptions());
}
public function testGitVersion()
{
$version = $this->wrapper->version();
$this->assertGitVersion($version);
}
public function testSetPrivateKey()
{
$key = './test/id_rsa';
$keyExpected = realpath($key);
$sshWrapperExpected = realpath(__DIR__ . '/../../../bin/git-ssh-wrapper.sh');
$this->wrapper->setPrivateKey($key);
$this->assertEquals($keyExpected, $this->wrapper->getEnvVar('GIT_SSH_KEY'));
$this->assertEquals(22, $this->wrapper->getEnvVar('GIT_SSH_PORT'));
$this->assertEquals($sshWrapperExpected, $this->wrapper->getEnvVar('GIT_SSH'));
}
public function testSetPrivateKeyPort()
{
$port = mt_rand(1024, 10000);
$this->wrapper->setPrivateKey('./test/id_rsa', $port);
$this->assertEquals($port, $this->wrapper->getEnvVar('GIT_SSH_PORT'));
}
public function testSetPrivateKeyWrapper()
{
$sshWrapper = './test/dummy-wrapper.sh';
$sshWrapperExpected = realpath($sshWrapper);
$this->wrapper->setPrivateKey('./test/id_rsa', 22, $sshWrapper);
$this->assertEquals($sshWrapperExpected, $this->wrapper->getEnvVar('GIT_SSH'));
}
/**
* @expectedException \GitWrapper\GitException
*/
public function testSetPrivateKeyError()
{
$badKey = './test/id_rsa_bad';
$this->wrapper->setPrivateKey($badKey);
}
/**
* @expectedException \GitWrapper\GitException
*/
public function testSetPrivateKeyWrapperError()
{
$badWrapper = './test/dummy-wrapper-bad.sh';
$this->wrapper->setPrivateKey('./test/id_rsa', 22, $badWrapper);
}
public function testUnsetPrivateKey()
{
// Set and unset the private key.
$key = './test/id_rsa';
$sshWrapper = './test/dummy-wrapper.sh';
$this->wrapper->setPrivateKey($key, 22, $sshWrapper);
$this->wrapper->unsetPrivateKey();
$this->assertNull($this->wrapper->getEnvVar('GIT_SSH_KEY'));
$this->assertNull($this->wrapper->getEnvVar('GIT_SSH_PORT'));
$this->assertNull($this->wrapper->getEnvVar('GIT_SSH'));
}
public function testGitCommand()
{
$version = $this->wrapper->git('--version');
$this->assertGitVersion($version);
}
/**
* @expectedException \GitWrapper\GitException
*/
public function testGitCommandError()
{
$this->runBadCommand();
}
public function testGitRun()
{
$command = GitCommand::getInstance();
$command->setFlag('version');
$command->setDirectory('./test'); // Directory just has to exist.
$version = $this->wrapper->run($command);
$this->assertGitVersion($version);
}
/**
* @expectedException \GitWrapper\GitException
*/
public function testGitRunDirectoryError()
{
$command = GitCommand::getInstance();
$command->setFlag('version');
$command->setDirectory('/some/bad/directory');
$this->wrapper->run($command);
}
public function testWrapperExecutable()
{
$sshWrapper = realpath(__DIR__ . '/../../../bin/git-ssh-wrapper.sh');
$this->assertTrue(is_executable($sshWrapper));
}
/**
* @expectedException \BadMethodCallException
*/
public function testCallError()
{
$this->wrapper->badMethod();
}
public function testWorkingCopy()
{
$directory = './' . $this->randomString();
$git = $this->wrapper->workingCopy($directory);
$this->assertTrue($git instanceof GitWorkingCopy);
$this->assertEquals($directory, $git->getDirectory());
$this->assertEquals($this->wrapper, $git->getWrapper());
}
public function testParseRepositoryName()
{
$nameGit = GitWrapper::parseRepositoryName('git@github.com:cpliakas/git-wrapper.git');
$this->assertEquals($nameGit, 'git-wrapper');
$nameHttps = GitWrapper::parseRepositoryName('https://github.com/cpliakas/git-wrapper.git');
$this->assertEquals($nameHttps, 'git-wrapper');
}
public function testCloneWothoutDirectory()
{
$this->addBypassListener();
$this->wrapper->clone('file:///' . $this->randomString());
}
}
PK ?V test/dummy-wrapper.shnu W+A PK ?VT T phpmd.xmlnu W+A
PHP Project Starter Rulset: Adopted From Jenkins for Symfony 2
PK ?VĆNP' '
.gitignorenu W+A build/
composer.lock
nbproject
vendor/
PK ?Vr'ӻ README.mdnu W+A # Overview
[![Build Status](https://travis-ci.org/cpliakas/git-wrapper.png)](https://travis-ci.org/cpliakas/git-wrapper)
[![Coverage Status](https://coveralls.io/repos/cpliakas/git-wrapper/badge.png?branch=master)](https://coveralls.io/r/cpliakas/git-wrapper?branch=master)
[![Total Downloads](https://poser.pugx.org/cpliakas/git-wrapper/downloads.png)](https://packagist.org/packages/cpliakas/git-wrapper)
[![Latest Stable Version](https://poser.pugx.org/cpliakas/git-wrapper/v/stable.png)](https://packagist.org/packages/cpliakas/git-wrapper)
This library is a PHP wrapper around the Git command line tool.
Its purpose is to provide a readable API that abstracts some of the challenges
of executing Git commands from within a PHP process. Specifically, this library
builds upon the Symfony framework's Process component to execute the Git command
in a way that works across platforms and uses the best-in-breed techniques
available to PHP. This library also provides an SSH wrapper script and API
method for developers to easily specify a private key other than one of the
defaults by using the technique in [this thread on StackOverflow](http://stackoverflow.com/a/3500308/870667).
Finally, various commands are expected to be executed in the directory
containing the working copy. Although this a fairly simple challenge to
overcome, the library handles this transparently so the developer doesn't have
to think about it.
## Usage
```php
use GitWrapper\GitWrapper;
// Initialize the library. If the path to the Git binary is not passed as
// the first argument when instantiating GitWrapper, it is auto-discovered.
require_once 'vendor/autoload.php';
$wrapper = new GitWrapper();
// Optionally specify a private key other than one of the defaults.
$wrapper->setPrivateKey('/path/to/private/key');
// Clone a repo into `/path/to/working/copy`, get a working copy object.
$git = $wrapper->clone('git://github.com/cpliakas/git-wrapper.git', '/path/to/working/copy');
// Create a file in the working copy.
touch('/path/to/working/copy/text.txt');
// Add it, commit it, and push the change.
$git
->add('test.txt')
->commit('Added the test.txt file as per the examples.')
->push();
// Render the output.
print $git->getOutput();
// Stream output of subsequent Git commands in real time to STDOUT and STDERR.
$wrapper->streamOutput();
// Execute an arbitrary git command.
// The following is synonymous with `git config -l`
$wrapper->git('config -l');
```
All command methods adhere to the following paradigm:
```php
$git->command($arg1, $arg2, ..., $options);
```
Replace `command` with the Git command being executed, e.g. `checkout`, `push`,
etc. The `$arg*` parameters are a variable number of arguments as they would be
passed to the Git command line tool. `$options` is an optional array of command
line options in the following format:
```php
$options = array(
'verbose' => true, // Passes the "--verbose" flag.
't' => 'my-branch', // Passes the "-t my-branch" option.
);
```
#### Logging
Use the logger listener with [PSR-3](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md)
compatible loggers such as [Monolog](https://github.com/Seldaek/monolog) to log
commands that are executed.
```php
use GitWrapper\Event\GitLoggerListener;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
// Log to a file named "git.log"
$log = new Logger('git');
$log->pushHandler(new StreamHandler('git.log', Logger::DEBUG));
// Instantiate the listener, add the logger to it, and register it.
$listener = new GitLoggerListener($log);
$wrapper->addLoggerListener($listener);
$git = $wrapper->clone('git://github.com/cpliakas/git-wrapper.git', '/path/to/working/copy');
// The "git.log" file now has info about the command that was executed above.
```
## Installation
Git Wrapper can be installed with [Composer](http://getcomposer.org) by adding
the library as a dependency to your composer.json file.
```json
{
"require": {
"cpliakas/git-wrapper": "~1.0"
}
}
```
Please refer to [Composer's documentation](https://github.com/composer/composer/blob/master/doc/00-intro.md#introduction)
for installation and usage instructions.
## Gotchas
There are a few "gotchas" that are out of scope for this library to solve but
might prevent a successful implementation of running Git via PHP. The following
is an incomplete list of challenges that are often encountered when executing
Git from PHP.
### Missing HOME Environment Variable
Sometimes the `HOME` environment variable is not set in the Git process that is
spawned by PHP. This will cause many Git operations to fail. It is advisable to
set the `HOME` environment variable to a path outside of the document root that
the web server has write access to. Note that this environment variable is only
set for the process running Git and NOT the PHP process that is spawns it.
```php
$wrapper->setEnvVar('HOME', '/path/to/a/private/writable/dir');
```
It is important that the storage is persistent as the ~/.gitconfig file will be
written to this location. See the following "gotcha" for why this is important.
### Missing Identity And Configurations
Many repositories require that a name and email address are specified. This data
is set by running `git config [name] [value]` on the command line, and the
configurations are usually stored in the `~/.gitconfig file`. When executing Git
via PHP, however, the process might have a different home directory than the
user who normally runs git via the command line. Therefore no identity is sent
to the repository, and it will likely throw an error.
```php
// Set configuration options globally.
$wrapper->git('config --global user.name "User name"');
$wrapper->git('config --global user.email user@example.com');
// Set configuration options per repository.
$git
->config('user.name', 'User name')
->config('user.email', 'user@example.com');
```
### Commits To Repositories With No Changes
Running `git commit` on a repository with no changes returns no output but exits
with a status of 1. Therefore the library will throw a `GitException` since it
correctly detected an error. It is advisable to check whether a working copy has
any changes prior to running the commit operation in order to prevent unwanted
exceptions.
```php
if ($git->hasChanges()) {
$git->commit('Committed the changes.');
}
```
### Permissions Of The GIT_SSH Wrapper Script
On checkout, the bin/git-ssh-wrapper.sh script should be executable. If it is
not, git commands with fail if a non-default private key is specified.
$> chmod 0755 ./bin/git-ssh-wrapper.sh
## For Developers
Refer to [PHP Project Starter's documentation](https://github.com/cpliakas/php-project-starter#using-apache-ant)
for the Apache Ant targets supported by this project.
PK ?V>^
=
= src/GitWrapper/GitWrapper.phpnu W+A find('git');
if (!$gitBinary) {
throw new GitException('Unable to find the Git executable.');
}
// @codeCoverageIgnoreEnd
}
$this->setGitBinary($gitBinary);
}
/**
* Gets the dispatcher used by this library to dispatch events.
*
* @return \Symfony\Component\EventDispatcher\EventDispatcherInterface
*/
public function getDispatcher()
{
if (!isset($this->dispatcher)) {
$this->dispatcher = new EventDispatcher();
}
return $this->dispatcher;
}
/**
* Sets the dispatcher used by this library to dispatch events.
*
* @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $dispatcher
* The Symfony event dispatcher object.
*
* @return \GitWrapper\GitWrapper
*/
public function setDispatcher(EventDispatcherInterface $dispatcher)
{
$this->dispatcher = $dispatcher;
return $this;
}
/**
* Sets the path to the Git binary.
*
* @param string $gitBinary
* Path to the Git binary.
*
* @return \GitWrapper\GitWrapper
*/
public function setGitBinary($gitBinary)
{
$this->gitBinary = $gitBinary;
return $this;
}
/**
* Returns the path to the Git binary.
*
* @return string
*/
public function getGitBinary()
{
return $this->gitBinary;
}
/**
* Sets an environment variable that is defined only in the scope of the Git
* command.
*
* @param string $var
* The name of the environment variable, e.g. "HOME", "GIT_SSH".
* @param mixed $default
* The value of the environment variable is not set, defaults to null.
*
* @return \GitWrapper\GitWrapper
*/
public function setEnvVar($var, $value)
{
$this->env[$var] = $value;
return $this;
}
/**
* Unsets an environment variable that is defined only in the scope of the
* Git command.
*
* @param string $var
* The name of the environment variable, e.g. "HOME", "GIT_SSH".
*
* @return \GitWrapper\GitWrapper
*/
public function unsetEnvVar($var)
{
unset($this->env[$var]);
return $this;
}
/**
* Returns an environment variable that is defined only in the scope of the
* Git command.
*
* @param string $var
* The name of the environment variable, e.g. "HOME", "GIT_SSH".
* @param mixed $default
* The value returned if the environment variable is not set, defaults to
* null.
*
* @return mixed
*/
public function getEnvVar($var, $default = null)
{
return isset($this->env[$var]) ? $this->env[$var] : $default;
}
/**
* Returns the associative array of environment variables that are defined
* only in the scope of the Git command.
*
* @return array
*/
public function getEnvVars()
{
return $this->env;
}
/**
* Sets the timeout of the Git command.
*
* @param int $timeout
* The timeout in seconds.
*
* @return \GitWrapper\GitWrapper
*/
public function setTimeout($timeout)
{
$this->timeout = (int) $timeout;
return $this;
}
/**
* Gets the timeout of the Git command.
*
* @return int
* The timeout in seconds.
*/
public function getTimeout()
{
return $this->timeout;
}
/**
* Sets the options passed to proc_open() when executing the Git command.
*
* @param array $timeout
* The options passed to proc_open().
*
* @return \GitWrapper\GitWrapper
*/
public function setProcOptions(array $options)
{
$this->procOptions = $options;
return $this;
}
/**
* Gets the options passed to proc_open() when executing the Git command.
*
* @return array
*/
public function getProcOptions()
{
return $this->procOptions;
}
/**
* Set an alternate private key used to connect to the repository.
*
* This method sets the GIT_SSH environment variable to use the wrapper
* script included with this library. It also sets the custom GIT_SSH_KEY
* and GIT_SSH_PORT environment variables that are used by the script.
*
* @param string $privateKey
* Path to the private key.
* @param int $port
* Port that the SSH server being connected to listens on, defaults to 22.
* @param string|null $wrapper
* Path the the GIT_SSH wrapper script, defaults to null which uses the
* script included with this library.
*
* @return \GitWrapper\GitWrapper
*
* @throws \GitWrapper\GitException
* Thrown when any of the paths cannot be resolved.
*/
public function setPrivateKey($privateKey, $port = 22, $wrapper = null)
{
if (null === $wrapper) {
$wrapper = __DIR__ . '/../../bin/git-ssh-wrapper.sh';
}
if (!$wrapperPath = realpath($wrapper)) {
throw new GitException('Path to GIT_SSH wrapper script could not be resolved: ' . $wrapper);
}
if (!$privateKeyPath = realpath($privateKey)) {
throw new GitException('Path private key could not be resolved: ' . $privateKey);
}
return $this
->setEnvVar('GIT_SSH', $wrapperPath)
->setEnvVar('GIT_SSH_KEY', $privateKeyPath)
->setEnvVar('GIT_SSH_PORT', (int) $port)
;
}
/**
* Unsets the private key by removing the appropriate environment variables.
*
* @return \GitWrapper\GitWrapper
*/
public function unsetPrivateKey()
{
return $this
->unsetEnvVar('GIT_SSH')
->unsetEnvVar('GIT_SSH_KEY')
->unsetEnvVar('GIT_SSH_PORT')
;
}
/**
* Adds output listener.
*
* @param \GitWrapper\Event\GitOutputListenerInterface $listener
*
* @return \GitWrapper\GitWrapper
*/
public function addOutputListener(Event\GitOutputListenerInterface $listener)
{
$this
->getDispatcher()
->addListener(Event\GitEvents::GIT_OUTPUT, array($listener, 'handleOutput'))
;
return $this;
}
/**
* Adds logger listener listener.
*
* @param Event\GitLoggerListener $listener
*
* @return GitWrapper
*/
public function addLoggerListener(Event\GitLoggerListener $listener)
{
$this
->getDispatcher()
->addSubscriber($listener)
;
return $this;
}
/**
* Removes an output listener.
*
* @param \GitWrapper\Event\GitOutputListenerInterface $listener
*
* @return \GitWrapper\GitWrapper
*/
public function removeOutputListener(Event\GitOutputListenerInterface $listener)
{
$this
->getDispatcher()
->removeListener(Event\GitEvents::GIT_OUTPUT, array($listener, 'handleOutput'))
;
return $this;
}
/**
* Set whether or not to stream real-time output to STDOUT and STDERR.
*
* @param boolean $streamOutput
*
* @return \GitWrapper\GitWrapper
*/
public function streamOutput($streamOutput = true)
{
if ($streamOutput && !isset($this->streamListener)) {
$this->streamListener = new Event\GitOutputStreamListener();
$this->addOutputListener($this->streamListener);
}
if (!$streamOutput && isset($this->streamListener)) {
$this->removeOutputListener($this->streamListener);
unset($this->streamListener);
}
return $this;
}
/**
* Returns an object that interacts with a working copy.
*
* @param string $directory
* Path to the directory containing the working copy.
*
* @return GitWorkingCopy
*/
public function workingCopy($directory)
{
return new GitWorkingCopy($this, $directory);
}
/**
* Returns the version of the installed Git client.
*
* @return string
*
* @throws \GitWrapper\GitException
*/
public function version()
{
return $this->git('--version');
}
/**
* Parses name of the repository from the path.
*
* For example, passing the "git@github.com:cpliakas/git-wrapper.git"
* repository would return "git-wrapper".
*
* @param string $repository
* The repository URL.
*
* @return string
*/
public static function parseRepositoryName($repository)
{
$scheme = parse_url($repository, PHP_URL_SCHEME);
if (null === $scheme) {
$parts = explode('/', $repository);
$path = end($parts);
} else {
$strpos = strpos($repository, ':');
$path = substr($repository, $strpos + 1);
}
return basename($path, '.git');
}
/**
* Executes a `git init` command.
*
* Create an empty git repository or reinitialize an existing one.
*
* @param string $directory
* The directory being initialized.
* @param array $options
* (optional) An associative array of command line options.
*
* @return \GitWrapper\GitWorkingCopy
*
* @throws \GitWrapper\GitException
*
* @see GitWorkingCopy::cloneRepository()
*
* @ingroup commands
*/
public function init($directory, array $options = array())
{
$git = $this->workingCopy($directory);
$git->init($options);
$git->setCloned(true);
return $git;
}
/**
* Executes a `git clone` command and returns a working copy object.
*
* Clone a repository into a new directory. Use GitWorkingCopy::clone()
* instead for more readable code.
*
* @param string $repository
* The Git URL of the repository being cloned.
* @param string $directory
* The directory that the repository will be cloned into. If null is
* passed, the directory will automatically be generated from the URL via
* the GitWrapper::parseRepositoryName() method.
* @param array $options
* (optional) An associative array of command line options.
*
* @return \GitWrapper\GitWorkingCopy
*
* @throws \GitWrapper\GitException
*
* @see GitWorkingCopy::cloneRepository()
*
* @ingroup commands
*/
public function cloneRepository($repository, $directory = null, array $options = array())
{
if (null === $directory) {
$directory = self::parseRepositoryName($repository);
}
$git = $this->workingCopy($directory);
$git->clone($repository, $options);
$git->setCloned(true);
return $git;
}
/**
* Runs an arbitrary Git command.
*
* The command is simply a raw command line entry for everything after the
* Git binary. For example, a `git config -l` command would be passed as
* `config -l` via the first argument of this method.
*
* Note that no events are thrown by this method.
*
* @param string $commandLine
* The raw command containing the Git options and arguments. The Git
* binary should not be in the command, for example `git config -l` would
* translate to "config -l".
* @param string|null $cwd
* The working directory of the Git process. Defaults to null which uses
* the current working directory of the PHP process.
*
* @return string
* The STDOUT returned by the Git command.
*
* @throws \GitWrapper\GitException
*
* @see GitWrapper::run()
*/
public function git($commandLine, $cwd = null)
{
$command = GitCommand::getInstance($commandLine);
$command->setDirectory($cwd);
return $this->run($command);
}
/**
* Runs a Git command.
*
* @param \GitWrapper\GitCommand $command
* The Git command being executed.
* @param string|null $cwd
* Explicitly specify the working directory of the Git process. Defaults
* to null which automatically sets the working directory based on the
* command being executed relative to the working copy.
*
* @return string
* The STDOUT returned by the Git command.
*
* @throws \GitWrapper\GitException
*
* @see Process
*/
public function run(GitCommand $command, $cwd = null)
{
$wrapper = $this;
$process = new GitProcess($this, $command, $cwd);
$process->run(function ($type, $buffer) use ($wrapper, $process, $command) {
$event = new Event\GitOutputEvent($wrapper, $process, $command, $type, $buffer);
$wrapper->getDispatcher()->dispatch(Event\GitEvents::GIT_OUTPUT, $event);
});
return $command->notBypassed() ? $process->getOutput() : '';
}
/**
* Hackish, allows us to use "clone" as a method name.
*
* $throws \BadMethodCallException
* @throws \GitWrapper\GitException
*/
public function __call($method, $args)
{
if ('clone' == $method) {
return call_user_func_array(array($this, 'cloneRepository'), $args);
} else {
$class = get_called_class();
$message = "Call to undefined method $class::$method()";
throw new \BadMethodCallException($message);
}
}
}
PK ?VAl2 2 " src/GitWrapper/Event/GitEvents.phpnu W+A isError() ? STDERR : STDOUT;
fputs($handler, $event->getBuffer());
}
}
PK ?Ve(3 3 ! src/GitWrapper/Event/GitEvent.phpnu W+A wrapper = $wrapper;
$this->process = $process;
$this->command = $command;
}
/**
* Gets the GitWrapper object that likely instantiated this class.
*
* @return \GitWrapper\GitWrapper
*/
public function getWrapper()
{
return $this->wrapper;
}
/**
* Gets the Process object being run.
*
* @return \Symfony\Component\Process\Process
*/
public function getProcess()
{
return $this->process;
}
/**
* Gets the GitCommand object being executed.
*
* @return \GitWrapper\GitCommand
*/
public function getCommand()
{
return $this->command;
}
}
PK ?VxG) ) * src/GitWrapper/Event/GitLoggerListener.phpnu W+A LogLevel::INFO,
GitEvents::GIT_OUTPUT => LogLevel::DEBUG,
GitEvents::GIT_SUCCESS => LogLevel::INFO,
GitEvents::GIT_ERROR => LogLevel::ERROR,
GitEvents::GIT_BYPASS => LogLevel::INFO,
);
/**
* @param \Psr\Log\LoggerInterface $logger
*/
public function __construct(LoggerInterface $logger)
{
$this->setLogger($logger);
}
/**
* {@inheritDoc}
*/
public function setLogger(LoggerInterface $logger)
{
$this->logger = $logger;
}
/**
* @return \Psr\Log\LoggerInterface
*/
public function getLogger()
{
return $this->logger;
}
/**
* Sets the log level mapping for an event.
*
* @param string $eventName
* @param string|false $logLevel
*
* @return \GitWrapper\Event\GitLoggerListener
*/
public function setLogLevelMapping($eventName, $logLevel)
{
$this->logLevelMappings[$eventName] = $logLevel;
return $this;
}
/**
* Returns the log level mapping for an event.
*
* @param string $eventName
*
* @return string
*
* @throws \DomainException
*/
public function getLogLevelMapping($eventName)
{
if (!isset($this->logLevelMappings[$eventName])) {
throw new \DomainException('Unknown event: ' . $eventName);
}
return $this->logLevelMappings[$eventName];
}
/**
* {@inheritDoc}
*/
public static function getSubscribedEvents()
{
return array(
GitEvents::GIT_PREPARE => array('onPrepare', 0),
GitEvents::GIT_OUTPUT => array('handleOutput', 0),
GitEvents::GIT_SUCCESS => array('onSuccess', 0),
GitEvents::GIT_ERROR => array('onError', 0),
GitEvents::GIT_BYPASS => array('onBypass', 0),
);
}
/**
* Adds a logg message using the level defined in the mappings.
*
* @param \GitWrapper\Event\GitEvent $event
* @param string $message
* @param array $context
*
* @throws \DomainException
*/
public function log(GitEvent $event, $message, array $context = array())
{
$method = $this->getLogLevelMapping($event->getName());
if ($method !== false) {
$context += array('command' => $event->getProcess()->getCommandLine());
$this->logger->$method($message, $context);
}
}
public function onPrepare(GitEvent $event)
{
$this->log($event, 'Git command preparing to run');
}
public function handleOutput(GitOutputEvent $event)
{
$context = array('error' => $event->isError() ? true : false);
$this->log($event, $event->getBuffer(), $context);
}
public function onSuccess(GitEvent $event)
{
$this->log($event, 'Git command successfully run');
}
public function onError(GitEvent $event)
{
$this->log($event, 'Error running Git command');
}
public function onBypass(GitEvent $event)
{
$this->log($event, 'Git command bypassed');
}
}
PK ?V I I ' src/GitWrapper/Event/GitOutputEvent.phpnu W+A type = $type;
$this->buffer = $buffer;
}
/**
* @return string
*/
public function getType()
{
return $this->type;
}
/**
* @return string
*/
public function getBuffer()
{
return $this->buffer;
}
/**
* Tests wheter the buffer was captured from STDERR.
*/
public function isError()
{
return (Process::ERR == $this->type);
}
}
PK ?V-ۼ 3 src/GitWrapper/Event/GitOutputListenerInterface.phpnu W+A command = array_shift($args);
// If the last element is an array, set it as the options.
$options = end($args);
if (is_array($options)) {
$this->setOptions($options);
array_pop($args);
}
// Pass all other method arguments as the Git command arguments.
foreach ($args as $arg) {
$this->addArgument($arg);
}
}
}
/**
* Constructs a GitCommand object.
*
* Accepts a variable number of arguments to model the arguments passed to
* the Git command line utility. If the last argument is an array, it is
* passed as the command options.
*
* @param string $command
* The Git command being run, e.g. "clone", "commit", etc.
* @param string ...
* Zero or more arguments passed to the Git command.
* @param array $options
* An optional array of arguments to pass to the command.
*
* @return \GitWrapper\GitCommand
*/
public static function getInstance()
{
$args = func_get_args();
return new static($args);
}
/**
* Returns Git command being run, e.g. "clone", "commit", etc.
*
* @return string
*/
public function getCommand()
{
return $this->command;
}
/**
* Sets the path to the directory containing the working copy.
*
* @param string $directory
* The path to the directory containing the working copy.
*
* @return \GitWrapper\GitCommand
*/
public function setDirectory($directory)
{
$this->directory = $directory;
return $this;
}
/**
* Gets the path to the directory containing the working copy.
*
* @return string|null
* The path, null if no path is set.
*/
public function getDirectory()
{
return $this->directory;
}
/**
* A boolean flagging whether to skip running the command.
*
* @param boolean $bypass
* Whether to bypass execution of the command. The parameter defaults to
* true for code readability, however the default behavior of this class
* is to run the command.
*
* @return \GitWrapper\GitCommand
*/
public function bypass($bypass = true)
{
$this->bypass = (bool) $bypass;
return $this;
}
/**
* Returns true if the Git command should be run.
*
* The return value is the boolean opposite $this->bypass. Although this
* seems complex, it makes the code more readable when checking whether the
* command should be run or not.
*
* @return boolean
* If true, the command should be run.
*/
public function notBypassed()
{
return !$this->bypass;
}
/**
* Builds the command line options for use in the Git command.
*
* @return string
*/
public function buildOptions()
{
$options = array();
foreach ($this->options as $option => $values) {
foreach ((array) $values as $value) {
$prefix = (strlen($option) != 1) ? '--' : '-';
$rendered = $prefix . $option;
if ($value !== true) {
$rendered .= ('--' == $prefix) ? '=' : ' ';
$rendered .= ProcessUtils::escapeArgument($value);
}
$options[] = $rendered;
}
}
return join(' ', $options);
}
/**
* Sets a command line option.
*
* Option names are passed as-is to the command line, whereas the values are
* escaped using \Symfony\Component\Process\ProcessUtils.
*
* @param string $option
* The option name, e.g. "branch", "q".
* @param string|true $value
* The option's value, pass true if the options is a flag.
*
* @reutrn \GitWrapper\GitCommand
*/
public function setOption($option, $value)
{
$this->options[$option] = $value;
return $this;
}
/**
* Sets multiple command line options.
*
* @param array $options
* An associative array of command line options.
*
* @reutrn \GitWrapper\GitCommand
*/
public function setOptions(array $options)
{
foreach ($options as $option => $value) {
$this->setOption($option, $value);
}
return $this;
}
/**
* Sets a command line flag.
*
* @param string $flag
* The flag name, e.g. "q", "a".
*
* @reutrn \GitWrapper\GitCommand
*
* @see \GitWrapper\GitCommand::setOption()
*/
public function setFlag($option)
{
return $this->setOption($option, true);
}
/**
* Gets a command line option.
*
* @param string $option
* The option name, e.g. "branch", "q".
* @param mixed $default
* Value that is returned if the option is not set, defaults to null.
*
* @return mixed
*/
public function getOption($option, $default = null)
{
return (isset($this->options[$option])) ? $this->options[$option] : $default;
}
/**
* Unsets a command line option.
*
* @param string $option
* The option name, e.g. "branch", "q".
*
* @return \GitWrapper\GitCommand
*/
public function unsetOption($option)
{
unset($this->options[$option]);
return $this;
}
/**
* Adds a command line argument passed to the Git command.
*
* @param string $arg
* The argument, e.g. the repo URL, directory, etc.
*
* @return \GitWrapper\GitCommand
*/
public function addArgument($arg)
{
$this->args[] = $arg;
return $this;
}
/**
* Renders the arguments and options for the Git command.
*
* @return string
*
* @see GitCommand::getCommand()
* @see GitCommand::buildOptions()
*/
public function getCommandLine()
{
$command = array(
$this->getCommand(),
$this->buildOptions(),
join(' ', array_map(array('\Symfony\Component\Process\ProcessUtils', 'escapeArgument'), $this->args)),
);
return join(' ', array_filter($command));
}
}
PK ?VLz'4c 4c ! src/GitWrapper/GitWorkingCopy.phpnu W+A wrapper = $wrapper;
$this->directory = $directory;
}
/**
* Returns the GitWrapper object that likely instantiated this class.
*
* @return \GitWrapper\GitWrapper
*/
public function getWrapper()
{
return $this->wrapper;
}
/**
* Gets the path to the directory containing the working copy.
*
* @return string
*/
public function getDirectory()
{
return $this->directory;
}
/**
* Gets the output captured by the last run Git commnd(s).
*
* @return string
*/
public function getOutput()
{
$output = $this->output;
$this->output = '';
return $output;
}
/**
* Clears the stored output captured by the last run Git command(s).
*
* @return \GitWrapper\GitWorkingCopy
*/
public function clearOutput()
{
$this->output = '';
return $this;
}
/**
* Manually sets the cloned flag.
*
* @param boolean $cloned
* Whether the repository is cloned into the directory or not.
*
* @return \GitWrapper\GitWorkingCopy
*/
public function setCloned($cloned)
{
$this->cloned = (bool) $cloned;
return $this;
}
/**
* Checks whether a repository has already been cloned to this directory.
*
* If the flag is not set, test if it looks like we're at a git directory.
*
* @return boolean
*/
public function isCloned()
{
if (!isset($this->cloned)) {
$gitDir = $this->directory;
if (is_dir($gitDir . '/.git')) {
$gitDir .= '/.git';
};
$this->cloned = (is_dir($gitDir . '/objects') && is_dir($gitDir . '/refs') && is_file($gitDir . '/HEAD'));
}
return $this->cloned;
}
/**
* Runs a Git command and captures the output.
*
* @param array $args
* The arguments passed to the command method.
* @param boolean $setDirectory
* Set the working directory, defaults to true.
*
* @return \GitWrapper\GitWorkingCopy
*
* @throws \GitWrapper\GitException
*
* @see GitWrapper::run()
*/
public function run($args, $setDirectory = true)
{
$command = call_user_func_array(array('GitWrapper\GitCommand', 'getInstance'), $args);
if ($setDirectory) {
$command->setDirectory($this->directory);
}
$this->output .= $this->wrapper->run($command);
return $this;
}
/**
* @defgroup command_helpers Git Command Helpers
*
* Helper methods that wrap common Git commands.
*
* @{
*/
/**
* Returns the output of a `git status -s` command.
*
* @return string
*
* @throws \GitWrapper\GitException
*/
public function getStatus()
{
return $this->wrapper->git('status -s', $this->directory);
}
/**
* Returns true if there are changes to commit.
*
* @return bool
*
* @throws \GitWrapper\GitException
*/
public function hasChanges()
{
$output = $this->getStatus();
return !empty($output);
}
/**
* Returns a GitBranches object containing information on the repository's
* branches.
*
* @return GitBranches
*/
public function getBranches()
{
return new GitBranches($this);
}
/**
* Helper method that pushes a tag to a repository.
*
* This is synonymous with `git push origin tag v1.2.3`.
*
* @param string $tag
* The tag being pushed.
* @param string $repository
* The destination of the push operation, which is either a URL or name of
* the remote. Defaults to "origin".
* @param array $options
* (optional) An associative array of command line options.
*
* @see GitWorkingCopy::push()
*/
public function pushTag($tag, $repository = 'origin', array $options = array())
{
return $this->push($repository, 'tag', $tag, $options);
}
/**
* Helper method that pushes all tags to a repository.
*
* This is synonymous with `git push --tags origin`.
*
* @param string $repository
* The destination of the push operation, which is either a URL or name of
* the remote. Defaults to "origin".
* @param array $options
* (optional) An associative array of command line options.
*
* @see GitWorkingCopy::push()
*/
public function pushTags($repository = 'origin', array $options = array())
{
$options['tags'] = true;
return $this->push($repository, $options);
}
/**
* Fetches all remotes.
*
* This is synonymous with `git fetch --all`.
*
* @param array $options
* (optional) An associative array of command line options.
*
* @see GitWorkingCopy::fetch()
*/
public function fetchAll(array $options = array())
{
$options['all'] = true;
return $this->fetch($options);
}
/**
* Create a new branch and check it out.
*
* This is synonymous with `git checkout -b`.
*
* @param string $branch
* The new branch being created.
*
* @see GitWorkingCopy::checkout()
*/
public function checkoutNewBranch($branch, array $options = array())
{
$options['b'] = true;
return $this->checkout($branch, $options);
}
/**
* @} End of "defgroup command_helpers".
*/
/**
* @defgroup commands Git Commands
*
* All methods in this group correspond with Git commands, for example
* "git add", "git commit", "git push", etc.
*
* @{
*/
/**
* Executes a `git add` command.
*
* Add file contents to the index.
*
* @code
* $git->add('some/file.txt');
* @endcode
*
* @param string $filepattern
* Files to add content from. Fileglobs (e.g. *.c) can be given to add
* all matching files. Also a leading directory name (e.g. dir to add
* dir/file1 and dir/file2) can be given to add all files in the
* directory, recursively.
* @param array $options
* An optional array of command line options.
*
* @return \GitWrapper\GitWorkingCopy
*
* @throws \GitWrapper\GitException
*/
public function add($filepattern, array $options = array())
{
$args = array(
'add',
$filepattern,
$options,
);
return $this->run($args);
}
/**
* Executes a `git apply` command.
*
* Apply a patch to files and/or to the index
*
* @code
* $git->apply('the/file/to/read/the/patch/from');
* @endcode
*
* @param string ...
* (optional) Additional command line arguments.
* @param array $options
* (optional) An associative array of command line options.
*
* @return GitWorkingCopy
*
* @throws GitException
*/
public function apply()
{
$args = func_get_args();
array_unshift($args, 'apply');
return $this->run($args);
}
/**
* Executes a `git bisect` command.
*
* Find by binary search the change that introduced a bug.
*
* @code
* $git->bisect('good', '2.6.13-rc2');
* $git->bisect('view', array('stat' => true));
* @endcode
*
* @param string $sub_command
* The subcommand passed to `git bisect`.
* @param string ...
* (optional) Additional command line arguments.
* @param array $options
* (optional) An associative array of command line options.
*
* @return \GitWrapper\GitWorkingCopy
*
* @throws \GitWrapper\GitException
*/
public function bisect($sub_command)
{
$args = func_get_args();
$args[0] = 'bisect ' . ProcessUtils::escapeArgument($sub_command);
return $this->run($args);
}
/**
* Executes a `git branch` command.
*
* List, create, or delete branches.
*
* @code
* $git->branch('my2.6.14', 'v2.6.14');
* $git->branch('origin/html', 'origin/man', array('d' => true, 'r' => 'origin/todo'));
* @endcode
*
* @param string ...
* (optional) Additional command line arguments.
* @param array $options
* (optional) An associative array of command line options.
*
* @return \GitWrapper\GitWorkingCopy
*
* @throws \GitWrapper\GitException
*/
public function branch()
{
$args = func_get_args();
array_unshift($args, 'branch');
return $this->run($args);
}
/**
* Executes a `git checkout` command.
*
* Checkout a branch or paths to the working tree.
*
* @code
* $git->checkout('new-branch', array('b' => true));
* @endcode
*
* @param string ...
* (optional) Additional command line arguments.
* @param array $options
* (optional) An associative array of command line options.
*
* @return \GitWrapper\GitWorkingCopy
*
* @throws \GitWrapper\GitException
*/
public function checkout()
{
$args = func_get_args();
array_unshift($args, 'checkout');
return $this->run($args);
}
/**
* Executes a `git clone` command.
*
* Clone a repository into a new directory. Use GitWorkingCopy::clone()
* instead for more readable code.
*
* @code
* $git->clone('git://github.com/cpliakas/git-wrapper.git');
* @endcode
*
* @param string $repository
* The Git URL of the repository being cloned.
* @param array $options
* (optional) An associative array of command line options.
*
* @param string $repository
* The URL of the repository being cloned.
*
* @return \GitWrapper\GitWorkingCopy
*
* @throws \GitWrapper\GitException
*/
public function cloneRepository($repository, $options = array())
{
$args = array(
'clone',
$repository,
$this->directory,
$options,
);
return $this->run($args, false);
}
/**
* Executes a `git commit` command.
*
* Record changes to the repository. If only one argument is passed, it is
* assumed to be the commit message. Therefore `$git->commit('Message');`
* yields a `git commit -am "Message"` command.
*
* @code
* $git->commit('My commit message');
* $git->commit('Makefile', array('m' => 'My commit message'));
* @endcode
*
* @param string ...
* (optional) Additional command line arguments.
* @param array $options
* (optional) An associative array of command line options.
*
* @return \GitWrapper\GitWorkingCopy
*
* @throws \GitWrapper\GitException
*/
public function commit()
{
$args = func_get_args();
if (isset($args[0]) && is_string($args[0]) && !isset($args[1])) {
$args[0] = array(
'm' => $args[0],
'a' => true,
);
}
array_unshift($args, 'commit');
return $this->run($args);
}
/**
* Executes a `git config` command.
*
* Get and set repository options.
*
* @code
* $git->config('user.email', 'opensource@chrispliakas.com');
* $git->config('user.name', 'Chris Pliakas');
* @endcode
*
* @param string ...
* (optional) Additional command line arguments.
* @param array $options
* (optional) An associative array of command line options.
*
* @return \GitWrapper\GitWorkingCopy
*
* @throws \GitWrapper\GitException
*/
public function config()
{
$args = func_get_args();
array_unshift($args, 'config');
return $this->run($args);
}
/**
* Executes a `git diff` command.
*
* Show changes between commits, commit and working tree, etc.
*
* @code
* $git->diff();
* $git->diff('topic', 'master');
* @endcode
*
* @param string ...
* (optional) Additional command line arguments.
* @param array $options
* (optional) An associative array of command line options.
*
* @return \GitWrapper\GitWorkingCopy
*
* @throws \GitWrapper\GitException
*/
public function diff()
{
$args = func_get_args();
array_unshift($args, 'diff');
return $this->run($args);
}
/**
* Executes a `git fetch` command.
*
* Download objects and refs from another repository.
*
* @code
* $git->fetch('origin');
* $git->fetch(array('all' => true));
* @endcode
*
* @param string ...
* (optional) Additional command line arguments.
* @param array $options
* (optional) An associative array of command line options.
*
* @return \GitWrapper\GitWorkingCopy
*
* @throws \GitWrapper\GitException
*/
public function fetch()
{
$args = func_get_args();
array_unshift($args, 'fetch');
return $this->run($args);
}
/**
* Executes a `git grep` command.
*
* Print lines matching a pattern.
*
* @code
* $git->grep('time_t', '--', '*.[ch]');
* @endcode
*
* @param string ...
* (optional) Additional command line arguments.
* @param array $options
* (optional) An associative array of command line options.
*
* @return \GitWrapper\GitWorkingCopy
*
* @throws \GitWrapper\GitException
*/
public function grep()
{
$args = func_get_args();
array_unshift($args, 'grep');
return $this->run($args);
}
/**
* Executes a `git init` command.
*
* Create an empty git repository or reinitialize an existing one.
*
* @code
* $git->init(array('bare' => true));
* @endcode
*
* @param array $options
* (optional) An associative array of command line options.
*
* @return \GitWrapper\GitWorkingCopy
*
* @throws \GitWrapper\GitException
*/
public function init(array $options = array())
{
$args = array(
'init',
$this->directory,
$options,
);
return $this->run($args, false);
}
/**
* Executes a `git log` command.
*
* Show commit logs.
*
* @code
* $git->log(array('no-merges' => true));
* $git->log('v2.6.12..', 'include/scsi', 'drivers/scsi');
* @endcode
*
* @param string ...
* (optional) Additional command line arguments.
* @param array $options
* (optional) An associative array of command line options.
*
* @return \GitWrapper\GitWorkingCopy
*
* @throws \GitWrapper\GitException
*/
public function log()
{
$args = func_get_args();
array_unshift($args, 'log');
return $this->run($args);
}
/**
* Executes a `git merge` command.
*
* Join two or more development histories together.
*
* @code
* $git->merge('fixes', 'enhancements');
* @endcode
*
* @param string ...
* (optional) Additional command line arguments.
* @param array $options
* (optional) An associative array of command line options.
*
* @return \GitWrapper\GitWorkingCopy
*
* @throws \GitWrapper\GitException
*/
public function merge()
{
$args = func_get_args();
array_unshift($args, 'merge');
return $this->run($args);
}
/**
* Executes a `git mv` command.
*
* Move or rename a file, a directory, or a symlink.
*
* @code
* $git->mv('orig.txt', 'dest.txt');
* @endcode
*
* @param string $source
* The file / directory being moved.
* @param string $destination
* The target file / directory that the source is being move to.
* @param array $options
* (optional) An associative array of command line options.
*
* @return \GitWrapper\GitWorkingCopy
*
* @throws \GitWrapper\GitException
*/
public function mv($source, $destination, array $options = array())
{
$args = array(
'mv',
$source,
$destination,
$options,
);
return $this->run($args);
}
/**
* Executes a `git pull` command.
*
* Fetch from and merge with another repository or a local branch.
*
* @code
* $git->pull('upstream', 'master');
* @endcode
*
* @param string ...
* (optional) Additional command line arguments.
* @param array $options
* (optional) An associative array of command line options.
*
* @return \GitWrapper\GitWorkingCopy
*
* @throws \GitWrapper\GitException
*/
public function pull()
{
$args = func_get_args();
array_unshift($args, 'pull');
return $this->run($args);
}
/**
* Executes a `git push` command.
*
* Update remote refs along with associated objects.
*
* @code
* $git->push('upstream', 'master');
* @endcode
*
* @param string ...
* (optional) Additional command line arguments.
* @param array $options
* (optional) An associative array of command line options.
*
* @return \GitWrapper\GitWorkingCopy
*
* @throws \GitWrapper\GitException
*/
public function push()
{
$args = func_get_args();
array_unshift($args, 'push');
return $this->run($args);
}
/**
* Executes a `git rebase` command.
*
* Forward-port local commits to the updated upstream head.
*
* @code
* $git->rebase('subsystem@{1}', array('onto' => 'subsystem'));
* @endcode
*
* @param string ...
* (optional) Additional command line arguments.
* @param array $options
* (optional) An associative array of command line options.
*
* @return \GitWrapper\GitWorkingCopy
*
* @throws \GitWrapper\GitException
*/
public function rebase()
{
$args = func_get_args();
array_unshift($args, 'rebase');
return $this->run($args);
}
/**
* Executes a `git remote` command.
*
* Manage the set of repositories ("remotes") whose branches you track.
*
* @code
* $git->remote('add', 'upstream', 'git://github.com/cpliakas/git-wrapper.git');
* @endcode
*
* @param string ...
* (optional) Additional command line arguments.
* @param array $options
* (optional) An associative array of command line options.
*
* @return \GitWrapper\GitWorkingCopy
*
* @throws \GitWrapper\GitException
*/
public function remote()
{
$args = func_get_args();
array_unshift($args, 'remote');
return $this->run($args);
}
/**
* Executes a `git reset` command.
*
* Reset current HEAD to the specified state.
*
* @code
* $git->reset(array('hard' => true));
* @endcode
*
* @param string ...
* (optional) Additional command line arguments.
* @param array $options
* (optional) An associative array of command line options.
*
* @return \GitWrapper\GitWorkingCopy
*
* @throws \GitWrapper\GitException
*/
public function reset()
{
$args = func_get_args();
array_unshift($args, 'reset');
return $this->run($args);
}
/**
* Executes a `git rm` command.
*
* Remove files from the working tree and from the index.
*
* @code
* $git->rm('oldfile.txt');
* @endcode
*
* @param string $filepattern
* Files to remove from version control. Fileglobs (e.g. *.c) can be
* given to add all matching files. Also a leading directory name (e.g.
* dir to add dir/file1 and dir/file2) can be given to add all files in
* the directory, recursively.
* @param array $options
* (optional) An associative array of command line options.
*
* @return \GitWrapper\GitWorkingCopy
*
* @throws \GitWrapper\GitException
*/
public function rm($filepattern, array $options = array())
{
$args = array(
'rm',
$filepattern,
$options,
);
return $this->run($args);
}
/**
* Executes a `git show` command.
*
* Show various types of objects.
*
* @code
* $git->show('v1.0.0');
* @endcode
*
* @param string $object
* The names of objects to show. For a more complete list of ways to spell
* object names, see "SPECIFYING REVISIONS" section in gitrevisions(7).
* @param array $options
* (optional) An associative array of command line options.
*
* @return \GitWrapper\GitWorkingCopy
*
* @throws \GitWrapper\GitException
*/
public function show($object, array $options = array())
{
$args = array('show', $object, $options);
return $this->run($args);
}
/**
* Executes a `git status` command.
*
* Show the working tree status.
*
* @code
* $git->status(array('s' => true));
* @endcode
*
* @param string ...
* (optional) Additional command line arguments.
* @param array $options
* (optional) An associative array of command line options.
*
* @return \GitWrapper\GitWorkingCopy
*
* @throws \GitWrapper\GitException
*/
public function status()
{
$args = func_get_args();
array_unshift($args, 'status');
return $this->run($args);
}
/**
* Executes a `git tag` command.
*
* Create, list, delete or verify a tag object signed with GPG.
* @code
* $git->tag('v1.0.0');
* @endcode
*
* @param string ...
* (optional) Additional command line arguments.
* @param array $options
* (optional) An associative array of command line options.
*
* @return \GitWrapper\GitWorkingCopy
*
* @throws \GitWrapper\GitException
*/
public function tag()
{
$args = func_get_args();
array_unshift($args, 'tag');
return $this->run($args);
}
/**
* Executes a `git clean` command.
*
* Remove untracked files from the working tree
*
* @code
* $git->clean('-d', '-f');
* @endcode
*
* @param string ...
* (optional) Additional command line arguments.
* @param array $options
* (optional) An associative array of command line options.
*
* @return \GitWrapper\GitWorkingCopy
*
* @throws \GitWrapper\GitException
*/
public function clean()
{
$args = func_get_args();
array_unshift($args, 'clean');
return $this->run($args);
}
/**
* @} End of "defgroup command".
*/
/**
* Hackish, allows us to use "clone" as a method name.
*
* $throws \BadMethodCallException
* @throws \GitWrapper\GitException
*/
public function __call($method, $args)
{
if ('clone' == $method) {
return call_user_func_array(array($this, 'cloneRepository'), $args);
} else {
$class = get_called_class();
$message = "Call to undefined method $class::$method()";
throw new \BadMethodCallException($message);
}
}
/**
* Gets the output captured by the last run Git commnd(s).
*
* @return string
*
* @see GitWorkingCopy::getOutput()
*/
public function __toString()
{
return $this->getOutput();
}
}
PK ?VI src/GitWrapper/GitProcess.phpnu W+A git = $git;
$this->command = $command;
// Build the command line options, flags, and arguments.
$binary = ProcessUtils::escapeArgument($git->getGitBinary());
$commandLine = rtrim($binary . ' ' . $command->getCommandLine());
// Resolve the working directory of the Git process. Use the directory
// in the command object if it exists.
if (null === $cwd) {
if (null !== $directory = $command->getDirectory()) {
if (!$cwd = realpath($directory)) {
throw new GitException('Path to working directory could not be resolved: ' . $directory);
}
}
}
// Finalize the environment variables, an empty array is converted
// to null which enherits the environment of the PHP process.
$env = $git->getEnvVars();
if (!$env) {
$env = null;
}
parent::__construct($commandLine, $cwd, $env, null, $git->getTimeout(), $git->getProcOptions());
}
/**
* {@inheritdoc}
*/
public function run($callback = null)
{
$event = new Event\GitEvent($this->git, $this, $this->command);
$dispatcher = $this->git->getDispatcher();
try {
// Throw the "git.command.prepare" event prior to executing.
$dispatcher->dispatch(Event\GitEvents::GIT_PREPARE, $event);
// Execute command if it is not flagged to be bypassed and throw the
// "git.command.success" event, otherwise do not execute the comamnd
// and throw the "git.command.bypass" event.
if ($this->command->notBypassed()) {
parent::run($callback);
if ($this->isSuccessful()) {
$dispatcher->dispatch(Event\GitEvents::GIT_SUCCESS, $event);
} else {
$output = $this->getErrorOutput();
if(trim($output) == '') {
$output = $this->getOutput();
}
throw new \RuntimeException($output);
}
} else {
$dispatcher->dispatch(Event\GitEvents::GIT_BYPASS, $event);
}
} catch (\RuntimeException $e) {
$dispatcher->dispatch(Event\GitEvents::GIT_ERROR, $event);
throw new GitException($e->getMessage());
}
}
}
PK ?V-& src/GitWrapper/GitException.phpnu W+A git = clone $git;
$output = (string) $git->branch(array('a' => true));
}
/**
* Fetches the branches via the `git branch` command.
*
* @param boolean $onlyRemote
* Whether to fetch only remote branches, defaults to false which returns
* all branches.
*
* @return array
*/
public function fetchBranches($onlyRemote = false)
{
$this->git->clearOutput();
$options = ($onlyRemote) ? array('r' => true) : array('a' => true);
$output = (string) $this->git->branch($options);
$branches = preg_split("/\r\n|\n|\r/", rtrim($output));
return array_map(array($this, 'trimBranch'), $branches);
}
/**
* Strips unwanted characters from the branch.
*
* @param string $branch
* The raw branch returned in the output of the Git command.
*
* @return string
* The processed branch name.
*/
public function trimBranch($branch)
{
return ltrim($branch, ' *');
}
/**
* Implements \IteratorAggregate::getIterator().
*/
public function getIterator()
{
$branches = $this->all();
return new \ArrayIterator($branches);
}
/**
* Returns all branches.
*
* @return array
*/
public function all()
{
return $this->fetchBranches();
}
/**
* Returns only remote branches.
*
* @return array
*/
public function remote()
{
return $this->fetchBranches(true);
}
}
PK ?Vg̙ phpunit.xmlnu W+A
test
src
PK ?V
.editorconfignu W+A PK ?V 7 7 LICENSEnu W+A PK ?Vc . .travis.ymlnu W+A PK ?Vs4` `
.coveralls.ymlnu W+A PK ?V\Mh h bin/git-ssh-wrapper.shnu W+A PK ?V;{$' ' Y build.xmlnu W+A PK ?V
S5
composer.jsonnu W+A PK ?V* 7 7 test/bootstrap.phpnu W+A PK ?V H test/id_rsanu W+A PK ?V # test/GitWrapper/Test/TestLogger.phpnu W+A PK ?Vqa/ / + p test/GitWrapper/Test/GitWorkingCopyTest.phpnu W+A PK ?Vl ( WP test/GitWrapper/Test/GitListenerTest.phpnu W+A PK ?V^^ _, , - W test/GitWrapper/Test/StreamSuppressFilter.phpnu W+A PK ?V
>
>
+ PZ test/GitWrapper/Test/GitWrapperTestCase.phpnu W+A PK ?Vʓ 1 g test/GitWrapper/Test/Event/TestBypassListener.phpnu W+A PK ?VY
1 i test/GitWrapper/Test/Event/TestOutputListener.phpnu W+A PK ?VbC - zk test/GitWrapper/Test/Event/TestDispatcher.phpnu W+A PK ?Vy + hl test/GitWrapper/Test/Event/TestListener.phpnu W+A PK ?V/ . p test/GitWrapper/Test/GitLoggerListenerTest.phpnu W+A PK ?VTxK ' | test/GitWrapper/Test/GitCommandTest.phpnu W+A PK ?Vzi ' E test/GitWrapper/Test/GitWrapperTest.phpnu W+A PK ?V H test/dummy-wrapper.shnu W+A PK ?VT T phpmd.xmlnu W+A PK ?VĆNP' '
.gitignorenu W+A PK ?Vr'ӻ { README.mdnu W+A PK ?V>^
=
= o src/GitWrapper/GitWrapper.phpnu W+A PK ?VAl2 2 " src/GitWrapper/Event/GitEvents.phpnu W+A PK ?VkDx x 0 J src/GitWrapper/Event/GitOutputStreamListener.phpnu W+A PK ?Ve(3 3 ! " src/GitWrapper/Event/GitEvent.phpnu W+A PK ?VxG) ) * src/GitWrapper/Event/GitLoggerListener.phpnu W+A PK ?V I I ' ) src/GitWrapper/Event/GitOutputEvent.phpnu W+A PK ?V-ۼ 3 src/GitWrapper/Event/GitOutputListenerInterface.phpnu W+A PK ?V!UV src/GitWrapper/GitCommand.phpnu W+A PK ?VLz'4c 4c ! : src/GitWrapper/GitWorkingCopy.phpnu W+A PK ?VI src/GitWrapper/GitProcess.phpnu W+A PK ?V-& ҩ src/GitWrapper/GitException.phpnu W+A PK ?VJ\} src/GitWrapper/GitBranches.phpnu W+A PK ?Vg̙ phpunit.xmlnu W+A PK &