I have been trying to get code sniffer to act as a svn pre-commit hook following the guide from pear. However while i am 100% certain my code should be invalid i get no errors and the project commits without problem.
Is there something else that needs to be done besides following the guide given by pear?
Link to pear guide on code sniffer as pre-commit hook
My phpcs-svn-pre-commit file :
#!C:\wamp\bin\php\php5.4.3\php.exe
<?php
/**
* A commit hook for SVN.
*
* PHP version 5
*
* #category PHP
* #package PHP_CodeSniffer
* #author Jack Bates <ms419#freezone.co.uk>
* #author Greg Sherwood <gsherwood#squiz.net>
* #copyright 2006-2011 Squiz Pty Ltd (ABN 77 084 670 600)
* #license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
* #link http://pear.php.net/package/PHP_CodeSniffer
*/
if (is_file(dirname(__FILE__).'/../CodeSniffer/CLI.php') === true) {
include_once dirname(__FILE__).'/../CodeSniffer/CLI.php';
} else {
include_once 'PHP/CodeSniffer/CLI.php';
}
define('PHP_CODESNIFFER_SVNLOOK', 'C:\Program Files (x86)\VisualSVN Server\bin\svnlook');
/**
* A class to process command line options.
*
* #category PHP
* #package PHP_CodeSniffer
* #author Jack Bates <ms419#freezone.co.uk>
* #author Greg Sherwood <gsherwood#squiz.net>
* #copyright 2006-2011 Squiz Pty Ltd (ABN 77 084 670 600)
* #license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
* #version Release: 1.3.6
* #link http://pear.php.net/package/PHP_CodeSniffer
*/
class PHP_CodeSniffer_SVN_Hook extends PHP_CodeSniffer_CLI
{
/**
* Get a list of default values for all possible command line arguments.
*
* #return array
*/
public function getDefaults()
{
$defaults = parent::getDefaults();
$defaults['svnArgs'] = array();
return $defaults;
}//end getDefaults()
/**
* Processes an unknown command line argument.
*
* All unknown args are sent to SVN commands.
*
* #param string $arg The command line argument.
* #param int $pos The position of the argument on the command line.
* #param array $values An array of values determined from CLI args.
*
* #return array The updated CLI values.
* #see getCommandLineValues()
*/
public function processUnknownArgument($arg, $pos, $values)
{
$values['svnArgs'][] = escapeshellarg($arg);
return $values;
}//end processUnknownArgument()
/**
* Runs PHP_CodeSniffer over files are directories.
*
* #param array $values An array of values determined from CLI args.
*
* #return int The number of error and warning messages shown.
* #see getCommandLineValues()
*/
public function process($values=array())
{
if (empty($values) === true) {
$values = parent::getCommandLineValues();
}
// Get list of files in this transaction.
$command = PHP_CODESNIFFER_SVNLOOK.' changed '.implode(' ', $values['svnArgs']);
$handle = popen($command, 'r');
if ($handle === false) {
echo 'ERROR: Could not execute "'.$command.'"'.PHP_EOL.PHP_EOL;
exit(2);
}
$contents = stream_get_contents($handle);
fclose($handle);
// Do not check deleted paths.
$contents = preg_replace('/^D.*/m', null, $contents);
// Drop the four characters representing the action which precede the path on
// each line.
$contents = preg_replace('/^.{4}/m', null, $contents);
$values['standard'] = $this->validateStandard($values['standard']);
if (PHP_CodeSniffer::isInstalledStandard($values['standard']) === false) {
// They didn't select a valid coding standard, so help them
// out by letting them know which standards are installed.
echo 'ERROR: the "'.$values['standard'].'" coding standard is not installed. ';
$this->printInstalledStandards();
exit(2);
}
$phpcs = new PHP_CodeSniffer(
$values['verbosity'],
$values['tabWidth'],
$values['encoding']
);
// Set file extensions if they were specified. Otherwise,
// let PHP_CodeSniffer decide on the defaults.
if (empty($values['extensions']) === false) {
$phpcs->setAllowedFileExtensions($values['extensions']);
}
// Set ignore patterns if they were specified.
if (empty($values['ignored']) === false) {
$phpcs->setIgnorePatterns($values['ignored']);
}
// Set some convenience member vars.
if ($values['errorSeverity'] === null) {
$this->errorSeverity = PHPCS_DEFAULT_ERROR_SEV;
} else {
$this->errorSeverity = $values['errorSeverity'];
}
if ($values['warningSeverity'] === null) {
$this->warningSeverity = PHPCS_DEFAULT_WARN_SEV;
} else {
$this->warningSeverity = $values['warningSeverity'];
}
// Initialize PHP_CodeSniffer listeners but don't process any files.
$phpcs->setCli($this);
$phpcs->process(array(), $values['standard'], $values['sniffs']);
// Need double quotes around the following regex beause the vertical whitespace
// char is not always treated correctly for whatever reason.
foreach (preg_split("/\v|\n/", $contents, -1, PREG_SPLIT_NO_EMPTY) as $path) {
// No need to process folders as each changed file is checked.
if (substr($path, -1) === '/') {
continue;
}
// We need to check ignore rules ourself because they are
// not checked when processing a single file.
if ($phpcs->shouldProcessFile($path) === false) {
continue;
}
// Get the contents of each file, as it would be after this transaction.
$command = PHP_CODESNIFFER_SVNLOOK.' cat '.implode(' ', $values['svnArgs']).' '.escapeshellarg($path);
$handle = popen($command, 'r');
if ($handle === false) {
echo 'ERROR: Could not execute "'.$command.'"'.PHP_EOL.PHP_EOL;
exit(2);
}
$contents = stream_get_contents($handle);
fclose($handle);
$phpcs->processFile($path, $contents);
}//end foreach
return $this->printErrorReport(
$phpcs,
$values['reports'],
$values['showSources'],
$values['reportFile'],
$values['reportWidth']
);
}//end process()
/**
* Prints out the usage information for this script.
*
* #return void
*/
public function printUsage()
{
parent::printUsage();
echo PHP_EOL;
echo ' Each additional argument is passed to the `svnlook changed ...`'.PHP_EOL;
echo ' and `svnlook cat ...` commands. The report is printed on standard output,'.PHP_EOL;
echo ' however Subversion displays only standard error to the user, so in a'.PHP_EOL;
echo ' pre-commit hook, this script should be invoked as follows:'.PHP_EOL;
echo PHP_EOL;
echo ' '.basename($_SERVER['argv'][0]).' ... "$REPOS" -t "$TXN" >&2 || exit 1'.PHP_EOL;
}//end printUsage()
}//end class
$phpcs = new PHP_CodeSniffer_SVN_Hook();
$phpcs->checkRequirements();
$numErrors = $phpcs->process();
if ($numErrors !== 0) {
exit(1);
}
?>
And my pre-commit file from subversion:
#!/bin/sh
# PRE-COMMIT HOOK
#
# The pre-commit hook is invoked before a Subversion txn is
# committed. Subversion runs this hook by invoking a program
# (script, executable, binary, etc.) named 'pre-commit' (for which
# this file is a template), with the following ordered arguments:
#
# [1] REPOS-PATH (the path to this repository)
# [2] TXN-NAME (the name of the txn about to be committed)
#
# [STDIN] LOCK-TOKENS ** the lock tokens are passed via STDIN.
#
# If STDIN contains the line "LOCK-TOKENS:\n" (the "\n" denotes a
# single newline), the lines following it are the lock tokens for
# this commit. The end of the list is marked by a line containing
# only a newline character.
#
# Each lock token line consists of a URI-escaped path, followed
# by the separator character '|', followed by the lock token string,
# followed by a newline.
#
# The default working directory for the invocation is undefined, so
# the program should set one explicitly if it cares.
#
# If the hook program exits with success, the txn is committed; but
# if it exits with failure (non-zero), the txn is aborted, no commit
# takes place, and STDERR is returned to the client. The hook
# program can use the 'svnlook' utility to help it examine the txn.
#
# On a Unix system, the normal procedure is to have 'pre-commit'
# invoke other programs to do the real work, though it may do the
# work itself too.
#
# *** NOTE: THE HOOK PROGRAM MUST NOT MODIFY THE TXN, EXCEPT ***
# *** FOR REVISION PROPERTIES (like svn:log or svn:author). ***
#
# This is why we recommend using the read-only 'svnlook' utility.
# In the future, Subversion may enforce the rule that pre-commit
# hooks should not modify the versioned data in txns, or else come
# up with a mechanism to make it safe to do so (by informing the
# committing client of the changes). However, right now neither
# mechanism is implemented, so hook writers just have to be careful.
#
# Note that 'pre-commit' must be executable by the user(s) who will
# invoke it (typically the user httpd runs as), and that user must
# have filesystem-level permission to access the repository.
#
# On a Windows system, you should name the hook program
# 'pre-commit.bat' or 'pre-commit.exe',
# but the basic idea is the same.
#
# The hook program typically does not inherit the environment of
# its parent process. For example, a common problem is for the
# PATH environment variable to not be set to its usual value, so
# that subprograms fail to launch unless invoked via absolute path.
# If you're having unexpected problems with a hook program, the
# culprit may be unusual (or missing) environment variables.
#
# Here is an example hook script, for a Unix /bin/sh interpreter.
# For more examples and pre-written hooks, see those in
# the Subversion repository at
# http://svn.apache.org/repos/asf/subversion/trunk/tools/hook-scripts/ and
# http://svn.apache.org/repos/asf/subversion/trunk/contrib/hook-scripts/
REPOS="$1"
TXN="$2"
# Make sure that the log message contains some text.
SVNLOOK=/usr/local/bin/svnlook
$SVNLOOK log -t "$TXN" "$REPOS" | \
grep "[a-zA-Z0-9]" > /dev/null || exit 1
# Check that the author of this commit has the rights to perform
# the commit on the files and directories being modified.
commit-access-control.pl "$REPOS" "$TXN" commit-access-control.cfg || exit 1
C:\wamp\bin\php\php5.4.3\scripts\phpcs-svn-pre-commit "$REPOS" -t "$TXN" >&2 || exit 1
# All checks passed, so allow the commit.
exit 0
I am pretty new to both SVN and codesniffer so i am pretty much just following guides and running tests as i go along. Any advice or tips on getting this to work will be appreciated :)
UPDATE
I have managed to get some results out of my svn hook, it now however shows a list of errors based on the script. I am not familiar with the scripting language required for SVN so i have no clue how to solve these.
List of errors:
REPOS is not recognized as internal or external command
TXN is not recognized as internal or external command
unknown command '/usr/local/bin/svnlook'
$SVNLOOK is not recognized as internal or external command
Judging from your executable file path (C:\wamp\bin\php\php5.4.3\php.exe), I assume you are working on a Windows machine.
The pre-commit file in your question looks like a Linux Bash Shell script.
Bash has a different syntax from a batch file you would use under Windows.
I suggest you use a pre-commit.tmpl file made for a Windows machine.
You probably have onde of these in your hooks folder.
I use a Linux machine, so unfortunately I can't help you further on this search...
The pre-commit hook will look like this (excerpt taken from An Introduction to Subversion Hook Scripts on Windows):
#echo off
:: Stops commits that don't include a log message of at least 6 characters.
#echo off
setlocal
rem Subversion sends through the repository path and transaction id
set REPOS=%1
set TXN=%2
svnlook log %REPOS% -t %TXN% | findstr ...... > nul
if %errorlevel% gtr 0 (goto err) else exit 0
:err
echo --------------------------------------------------------------------------- 1>&2
echo Your commit has been blocked because it didn't include a log message. 1>&2
echo Do the commit again, this time with a log message that describes your changes. 1>&2
echo --------------------------------------------------------------------------- 1>&2
exit 1
Related
Am trying ssr using laravel react js. While am using spatie ssr package for laravel. all configuration setup is done. but whenever i trying to run its throwing error
public function mustRun(callable $callback = null, array $env = [])
{
if (0 !== $this->run($callback, $env)) {
throw new ProcessFailedException($this);
}
return $this;
}
"""
The command "node D:\Deepak\react\storage\app/ssr\95698e4a8cd89030841216d9c8ae9b83.js" failed.\n
\n
Exit Code: 1(General error)\n
\n
Working directory: D:\Deepak\react\public\n
\n
Output:\n
================\n
\n
\n
Error Output:\n
================\n
'node' is not recognized as an internal or external command,\r\n
operable program or batch file.\r\n
(View: D:\Deepak\react\resources\views\welcome.blade.php)
Also i checked with node version and system environment path setup. everything is good.
Node Version 8.9.4
public function mustRun(callable $callback = null, array $env = [])
{
if (0 !== $this->run($callback, $env)) {
throw new ProcessFailedException($this);
}
return $this;
}
/**
* Starts the process and returns after writing the input to STDIN.
*
* This method blocks until all STDIN data is sent to the process then it
* returns while the process runs in the background.
*
* The termination of the process can be awaited with wait().
*
* The callback receives the type of output (out or err) and some bytes from
* the output in real-time while writing the standard input to the process.
* It allows to have feedback from the independent process during execution.
*
* #param callable|null $callback A PHP callback to run whenever there is some
* output available on STDOUT or STDERR
* #param array $env An array of additional env vars to set when running the process
Arguments
"""
The command "node D:\Deepak\react\storage\app/ssr\95698e4a8cd89030841216d9c8ae9b83.js" failed.\n
\n
Exit Code: 1(General error)\n
\n
Working directory: D:\Deepak\react\public\n
\n
Output:\n
================\n
\n
\n
Error Output:\n
================\n
'node' is not recognized as an internal or external command,\r\n
operable program or batch file.\r\n
(View: D:\Deepak\react\resources\views\welcome.blade.php)
I'm trying to attempt using a webhook script so that I can just commit locally and have the script triggered server-side and pull in any change.
Now if I login to the server via SSH and run php webhook.php the cript is triggered successfully and the files are updated. So I know the file does work. But if I make edits to the files, commit and push to master, I'm not seeing the files updated.
The log file produced by the script suggests everything is fine, but clearly it's not.
My file structure is like this:
var
www
my-project
- webhook.php
repo-folder
So the file should be pulling the files into repo-folder and the webhook.php is set as the webhook via the bitbucket control panel. If I view the log within bitbucket, it's showing a successful request every time I push a commit.
The script:
<?php
date_default_timezone_set('Europe/London');
class Deploy {
/**
* A callback function to call after the deploy has finished.
*
* #var callback
*/
public $post_deploy;
/**
* The name of the file that will be used for logging deployments. Set to
* FALSE to disable logging.
*
* #var string
*/
private $_log = 'deployments.log';
/**
* The timestamp format used for logging.
*
* #link http://www.php.net/manual/en/function.date.php
* #var string
*/
private $_date_format = 'Y-m-d H:i:sP';
/**
* The name of the branch to pull from.
*
* #var string
*/
private $_branch = 'master';
/**
* The name of the remote to pull from.
*
* #var string
*/
private $_remote = 'origin';
/**
* The directory where your website and git repository are located, can be
* a relative or absolute path
*
* #var string
*/
private $_directory;
/**
* Sets up defaults.
*
* #param string $directory Directory where your website is located
* #param array $data Information about the deployment
*/
public function __construct($directory, $options = array())
{
// Determine the directory path
$this->_directory = realpath($directory).DIRECTORY_SEPARATOR;
$available_options = array('log', 'date_format', 'branch', 'remote');
foreach ($options as $option => $value)
{
if (in_array($option, $available_options))
{
$this->{'_'.$option} = $value;
}
}
$this->log('Attempting deployment...');
}
/**
* Writes a message to the log file.
*
* #param string $message The message to write
* #param string $type The type of log message (e.g. INFO, DEBUG, ERROR, etc.)
*/
public function log($message, $type = 'INFO')
{
if ($this->_log)
{
// Set the name of the log file
$filename = $this->_log;
if ( ! file_exists($filename))
{
// Create the log file
file_put_contents($filename, '');
// Allow anyone to write to log files
chmod($filename, 0666);
}
// Write the message into the log file
// Format: time --- type: message
file_put_contents($filename, date($this->_date_format).' --- '.$type.': '.$message.PHP_EOL, FILE_APPEND);
}
}
/**
* Executes the necessary commands to deploy the website.
*/
public function execute()
{
try
{
// Make sure we're in the right directory
chdir($this->_directory);
$this->log('Changing working directory... ');
// Discard any changes to tracked files since our last deploy
exec('git reset --hard HEAD', $output);
$this->log('Reseting repository... '.implode(' ', $output));
// Update the local repository
exec('git pull '.$this->_remote.' '.$this->_branch, $output);
$this->log('Pulling in changes... '.implode(' ', $output));
// Secure the .git directory
exec('chmod -R og-rx .git');
$this->log('Securing .git directory... ');
if (is_callable($this->post_deploy))
{
call_user_func($this->post_deploy, $this->_data);
}
$this->log('Deployment successful.');
}
catch (Exception $e)
{
$this->log($e, 'ERROR');
}
}
}
// This is just an example
$deploy = new Deploy('/var/www/site-name/repo-name');
$deploy->execute();
?>
i was researching this more and the best way you can do is like i mention find out what is the user being used by apache server by building a php script and run the shell_exec('whoami'); and run on your browser to see that user it is.
Then on your document root for your website mine per example is /var/www you would need to create shh keys for this directory when you do that also add a config file with the host bitbucket and reference to the key you created.
Add the key to bitbucket
then you would need to add permission for apache to run the git command run the command visudo and add:
yourapacheuser ALL=(yourapacheuser) NOPASSWD: /usr/bin/ #the /usr/bin in my case is where i have installed git so you need to see what is the directory path where you install git.
After that you should be able to run your script without problems, in case it complains about a requiretty message then on visudo again add: Defaults:yourapacheuser !requiretty
hope it helps
did you configure SSH keys for the server you are using in bitbucket and add the webhook with the url of your script?
As user1361389 wrote you need to know what users are running the different processes. This is how I did on an Amazon Ubuntu instance.
I have a php file that calls a bash script:
shell_exec("sudo -u ubuntu /home/ubuntu/gitpull.sh");
Create SSH keys for user ubuntu and uploaded the public key to bitbucket.
Also, make sure that the php files on your server are owned by the correct user. In my case ubuntu.
You then need to impersonate ubuntu when calling the php file to deploy code. Add this line in the sudoer file (>sudo visudo )
www-data ALL=(ubuntu) NOPASSWD: /path/to/gitpull.sh
Then in bitbucket add the URL to your hook.
Ideally also opening the screenshot automatically in an image viewer.
Edit: Thanks to bishop for the tip on opening the apps. Still not sure how to do it Windows, though.
/**
* This works for Selenium and other real browsers that support screenshots.
*
* #Then /^show me a screenshot$/
*/
public function show_me_a_screenshot() {
$image_data = $this->getSession()->getDriver()->getScreenshot();
$file_and_path = '/tmp/behat_screenshot.jpg';
file_put_contents($file_and_path, $image_data);
if (PHP_OS === "Darwin" && PHP_SAPI === "cli") {
exec('open -a "Preview.app" ' . $file_and_path);
}
}
/**
* This works for the Goutte driver and I assume other HTML-only ones.
*
* #Then /^show me the HTML page$/
*/
public function show_me_the_html_page_in_the_browser() {
$html_data = $this->getSession()->getDriver()->getContent();
$file_and_path = '/tmp/behat_page.html';
file_put_contents($file_and_path, $html_data);
if (PHP_OS === "Darwin" && PHP_SAPI === "cli") {
exec('open -a "Safari.app" ' . $file_and_path);
};
}
You can use this package here https://github.com/forceedge01/behat-fail-aid. This will give you screenshot on fail and much more. It injects all details to the existing exception message so it will be perfectly placed below a fail like the usual behat fail message. Best of all, you won't have to write and maintain any code, plus it works with javascript and non javascript drivers! Here is what the output looks like:
All you have to do is install the package via composer
$ composer require genesis/behat-fail-aid --dev
And add the context to your behat.yml file
behat.yml
default:
suites:
default:
contexts:
- FailAid\Context\FailureContext
extensions:
FailAid\Extension: ~
There is bunch of other stuff you can do with this package, but this should solve your problems, Happy testing!
Hi i'm trying to use hhvm to run all of the background PHP workers that are currently there in my application. I don't want to run hhvm as a server as Apache is already taking care of it , all i want to do is to run my php codes with hhvm, instead of the regular Zend engine.
Ok here are the codes which i want to run.
This is the entry point of the computationally intensive modules that i want to run
-------------**RunRenderer.php**--------------
#!/usr/bin/php
<?php
require_once 'Config.php';
require_once 'Renderer.php';
Renderer::getInstance()->run();
?>
Here is just a small a portion of the main controller that controls/forks/manages thousands of php tasks/processes.
----------------------------Renderer.php---------------------
<?php
require 'Workers/BumpMapsCalc.php';
/**
* Main Entry class of the Map rendering module
*
* Create workers for all of the different maps calc sub routines
*
*
*
*/
class Renderer extends \Core_Daemon {
/**
* the interval at which the execute method will run
*
* Interval : 10 min
*
*/
protected $loop_interval = 600;
/**
* Set the chunk size
*/
protected $chunkSize = 500;
/**
* Loop counter
*/
protected $loopCounter;
/**
* Low limit and the high limit
*/
protected $lowLimit;
protected $highLimit;
/**
* set the plugins for lock file and settings ini files
*
*/
protected function setup_plugins() {
$this->plugin('Lock_File');
$this->plugin('settings', new \Core_Plugin_Ini());
$this->settings->filename = BASE_PATH . "/Config/settings.ini";
$this->settings->required_sections = array('geometry');
}
protected function setup() {
$this->log("Computing Bumps Maps");
}
/**
* Create multiple separate task that will run in parallel
* Provide the low limit and the high limit which should effectively partition
* the whole table into more manageable chunks , thus making importing and
* storing data much faster and finished within 10 min
*
*/
protected function execute() {
for ($this->loopCounter = 1 ; $this->loopCounter <= $this->settings['geometry']['number'] ; $this->loopCounter += $this->chunkSize) {
$this->lowLimit = $this->loopCounter;
$this->highLimit = $this->loopCounter + $this->chunkSize;
$this->task(new LocalBumpMaps($this->lowLimit, $this->highLimit));
}
}
protected function log_file() {
$dir = BASE_PATH . "/Logs";
if (#file_exists($dir) == false)
#mkdir($dir, 0777, true);
return $dir . '/log_' . date('Y-m-d');
}
}
?>
So normally i would run the program as
php RunRenderer.php -d -p ./pid/pid $1
which would invoke the default zend engine and Renderer.php would fork around thousands of instances of LocalBumpMaps ( along with 100 other map rendering classes ). Now with each of this subtasks taking around 20-30 mb all of the memory in the workstation gets exhausted pretty quickly thus causing the system to screech to a halt.
Of course the main rendering engine is written in C++, but due to some weird requirement the whole front end is in PHP. And the php modules needs to perform around billions of calculations per second. So the only options that was left was to use HHVM in hopes of some significant increase in performance and efficiency.
But the problem is i can't get this code to run with hhvm. This is what i'm trying
hhvm RunRenderer.php -p ./pid $1
This doesn't do anything at all. No processes are forked, no output, nothing happens. So can anyone please tell me how do i run the php scripts with hhvm instead of zend.
I hope my question makes sense, and i would really appreciate any help.
Thanks,
Maxx
Just run the following line first without forking a process:
hhvm RunRenderer.php
If you see console output, and that you can Ctrl+C to terminate the process, then you can demonize the process with an Upstart script. Create a file called /etc/init/renderer.conf:
start on startup
stop on shutdown
respawn
script
hhvm RunRenderer.php
end script
Then you can manually start and stop the process by running:
start renderer
and
stop renderer
If you are running Ubuntu 12.04LTS and above, a log file will be created for you automatically under the name /var/log/upstart/renderer.log. You can fetch live output by tailing the file:
tail -f /var/log/upstart/renderer.log
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 6 years ago.
Improve this question
For a project I am working on, we want to use git as a revision tracker for certain data we modify often. We are using php for the web frontend and we need a goo php git client to use. I have come across a handful on the internet and they all tend to have the same limitation...
There is no support for HTTP. We need to be able to push/pull to remote repositories. We also need to clone.
Ideally I am looking for something that does not use the git command (ie: wrapers to exec()) but I am willing to settle if the class works well. I have seen a C library which appears to do what I want, however the php language binding is incomplete and the http functions are labeled experimental.
Does anyone have any insight into using git and http through php?
https://github.com/kbjr/Git.php
Git.php is a wrapper class around git calls that uses proc_open instead of exec to run the commands. While it does not have push/pull methods, it does have a general run method for running custom git commands, so it could be used something like this:
$repo = Git::open('/path/to/repo');
$repo->run('push origin master');
It also does have methods for cloning (clone_to and clone_from which do local cloning and clone_remote for remote cloning).
One possibility is to use PHP's SSH library to perform those actions by connecting back to the web server?
Or I found this set of classes which allow you to you to clone and read other metadata over HTTP, but not push nor pull. However it could be a starting point if you're brave enough to extend them to do that. I can imagine it would be a lot of work to replicate these processes and keep them compliant with various server versions etc.
[UPDATED 23/03/2014, after receiving an upvote - thanks!]
I did get some way trying to implement the above (I was searching for an implementation, drew a blank so tried to write my own), and it was hard as I thought! I actually abandoned it as I found a simpler way to achieve this in a different architecture, but here's the class I wrote trying. It essentially works, but was brittle to the environmental variations I was working in (i.e. it doesn't cope very well with errors or problems).
It uses:
herzult/php-ssh
an ssh config file - a trick to simplify setting up authentication credentials in code
(Note - I had to quickly strip out a few details from the code to post it. So you'll need to fiddle about a bit to integrate it into your app/namespace etc.)
<?php
/**
* #author: scipilot
* #since: 31/12/2013
*/
/**
* Class GitSSH allows you to perform Git functions over an SSH session.
* i.e. you are using the command-line Git commands after SSHing to a host which has the Git client.
*
* You don't need to know about the SSH to use the class, other than the fact you will need access
* to a server via SSH which has the Git client installed. Its likely this is the local web server.
*
* This was made because PHP has no good native Git client.
*
* Requires herzult/php-ssh
*
* Example php-ssh config file would be
*
* <code>
* Host localhost
* User git
* IdentityFile id_rsa
*
* Host your.host.domain.com
* User whoever
* IdentityFile ~/.ssh/WhoeverGit
*</code>
*/
class GitSSH {
protected $config;
protected $session;
protected $sPath;
/**
* #var string
*/
protected $sConfigPath = '~/.ssh/config';
/**
* Connects to the specified host, ready for further commands.
*
* #param string $sHost Host (entry in the config file) to connect to.
* #param string $sConfigPath Optional; config file path. Defaults to ~/.ssh/config,
* which is probably inaccessible for web apps.
*/
function __construct($sHost, $sConfigPath=null){
\Log::info('New GitSSH '.$sHost.', '.$sConfigPath);
if(isset($sConfigPath)) $this->sConfigPath = $sConfigPath;
$this->config = new \Ssh\SshConfigFileConfiguration($this->sConfigPath, $sHost);
$this->session = new \Ssh\Session($this->config, $this->config->getAuthentication());
}
public function __destruct() {
$this->disconnect();
}
/**
* Thanks to Steve Kamerman, as there isn't a native disconnect.
*/
public function disconnect() {
$this->exec('echo "EXITING" && exit;');
$this->session = null;
}
/**
* Run a command (in the current working directory set by cd)
* #param $sCommand
* #return string
*/
protected function exec($sCommand) {
//echo "\n".$sCommand."\n";
$exec = $this->session->getExec();
$result = $exec->run('cd '.$this->sPath.'; '.$sCommand);
// todo: parse/scrape the result, return a Result object?
return $result;
}
/**
* CD to a folder. (This not an 'incremental' cd!)
* Devnote: we don't really execute the cd now, it's appended to other commands. Each command seems to re-login?
*
* #param string $sPath Absolute filesystem path, or relative from user home
*/
public function cd($sPath){
$this->sPath = $sPath;
// #todo this is useless! each command seems to run in a separate login?
//$result = $this->exec('cd'); // /; ls');
//return $result;
}
/**
* #return string
*/
public function ls(){
$result = $this->exec('ls ');
return $result;
}
public function gitAdd($sOptions=null, array $aFiles=null){
$result = $this->exec('git add '
.(empty($sOptions) ? '' : ' '.$sOptions)
.(empty($aFiles) ? '' : ' '.implode(' ', $aFiles))
);
return $result;
}
public function gitClone($sRepo, $sBranch=null, $sTarget=null){
\Log::info('GitSSH::clone '.$sRepo.', '.$sBranch.', '.$sTarget);
$result = $this->exec('git clone '
.(empty($sBranch) ? '' : ' --branch '.$sBranch)
.' '.$sRepo
.' '.$sTarget);
return $result;
}
public function gitCommit($sMessage, $sOptions=null, array $aFiles=null){
$result = $this->exec('git commit '
.'-m "'.addcslashes($sMessage, '"').'"'
.(empty($sOptions) ? '' : ' '.$sOptions)
.(empty($aFiles) ? '' : ' '.implode(' ', $aFiles))
);
return $result;
}
public function gitPull($sOptions=null, $sRepo=null, $sRefspec=null){
$result = $this->exec('git pull '
.(empty($sOptions) ? '' : ' '.$sOptions)
.(empty($sRepo) ? '' : ' '.$sRepo)
.(empty($sRefspec) ? '' : ' '.$sRefspec)
);
return $result;
}
public function gitPush($sOptions=null, $sRepo=null, $sRefspec=null){
$result = $this->exec('git push '
.(empty($sOptions) ? '' : ' '.$sOptions)
.(empty($sRepo) ? '' : ' '.$sRepo)
.(empty($sRefspec) ? '' : ' '.$sRefspec)
);
return $result;
}
/**
* #return string the raw result from git status
*/
public function gitStatus(){
$result = $this->exec('git status');
return $result;
}
}
This looks promising: http://gitphp.org (broken link; see an archived version)
I think that will do it for you. Here is the description of it:
GitPHP is a web frontend for git repositories. It emulates the look of standard gitweb, but is written in PHP and makes use of Smarty templates for customization. It has a couple extras, including syntax highlighting through the GeSHi PHP class and project category support. It works with standard git as well as msysgit on Windows.
Setup should be fairly simple – just extract the tarball where you want to install it, copy config/gitphp.conf.php.example to config/gitphp.conf.php, and set the projectroot in the conf to point to your directory where your bare git repositories are, and make the templates_c directory writeable by the webserver if it’s not already.
You can look through all the available options and defaults in config/gitphp.conf.defaults.php, and copy an option into your config file if you want to override the default. You can also copy config/projects.conf.php.example to config/projects.conf.php and edit it if you want more advanced control over your projects, such as defining categories for projects or loading projects from a text file. More detailed instructions are in the included README.
Note: if you’re upgrading your existing gitphp.conf.php will not be overwritten, but I recommend checking gitphp.conf.defaults.php for new configuration options that may have been added.
You can view the live copy running on this site.