Escape project directory in shell commands
Escape project directory in shell commands

<?php <?php
/** /**
* Class to load a file's history * Class to load a file's history
* *
* @author Christopher Han <xiphux@gmail.com> * @author Christopher Han <xiphux@gmail.com>
* @copyright Copyright (c) 2012 Christopher Han * @copyright Copyright (c) 2012 Christopher Han
* @package GitPHP * @package GitPHP
* @subpackage Git * @subpackage Git
*/ */
class GitPHP_FileHistory implements Iterator, GitPHP_Pagination_Interface class GitPHP_FileHistory implements Iterator, GitPHP_Pagination_Interface
{ {
/** /**
* The project * The project
* *
* @var GitPHP_Project * @var GitPHP_Project
*/ */
protected $project = null; protected $project = null;
   
/** /**
* History * History
* *
* @var GitPHP_FileDiff[] * @var GitPHP_FileDiff[]
*/ */
protected $history = array(); protected $history = array();
   
/** /**
* The path * The path
* *
* @var string * @var string
*/ */
protected $path; protected $path;
   
/** /**
* The limit of objects to load * The limit of objects to load
* *
* @var int * @var int
*/ */
protected $limit = 50; protected $limit = 50;
   
/** /**
* The number of objects to skip * The number of objects to skip
* *
* @var int * @var int
*/ */
protected $skip = 0; protected $skip = 0;
   
/** /**
* The hash to walk back from * The hash to walk back from
* *
* @var string * @var string
*/ */
protected $hash = false; protected $hash = false;
   
/** /**
* Whether data has been loaded * Whether data has been loaded
* *
* @var boolean * @var boolean
*/ */
protected $dataLoaded = false; protected $dataLoaded = false;
   
/** /**
* Executable * Executable
* *
* @var GitPHP_GitExe * @var GitPHP_GitExe
*/ */
protected $exe; protected $exe;
   
/** /**
* Constructor * Constructor
* *
* @param GitPHP_Project $project project * @param GitPHP_Project $project project
* @param string $path file path to trace history of * @param string $path file path to trace history of
* @param GitPHP_GitExe $exe git exe * @param GitPHP_GitExe $exe git exe
* @param GitPHP_Commit $head commit to start history from * @param GitPHP_Commit $head commit to start history from
* @param int $limit limit of revisions to walk * @param int $limit limit of revisions to walk
* @param int $skip number of revisions to skip * @param int $skip number of revisions to skip
*/ */
public function __construct($project, $path, $exe, $head = null, $limit = 0, $skip = 0) public function __construct($project, $path, $exe, $head = null, $limit = 0, $skip = 0)
{ {
if (!$project) { if (!$project) {
throw new Exception('Project is required'); throw new Exception('Project is required');
} }
   
$this->project = $project; $this->project = $project;
$this->limit = $limit; $this->limit = $limit;
$this->skip = $skip; $this->skip = $skip;
   
if (!$head) if (!$head)
$head = $this->project->GetHeadCommit(); $head = $this->project->GetHeadCommit();
   
if ($head) { if ($head) {
$this->hash = $head->GetHash(); $this->hash = $head->GetHash();
} }
if (empty($path)) if (empty($path))
throw new Exception('Path is required'); throw new Exception('Path is required');
   
if (!$exe) if (!$exe)
throw new Exception('Git exe is required'); throw new Exception('Git exe is required');
   
$this->path = $path; $this->path = $path;
   
$this->exe = $exe; $this->exe = $exe;
} }
   
/** /**
* Gets the path for this file history * Gets the path for this file history
* *
* @return string path * @return string path
*/ */
public function GetPath() public function GetPath()
{ {
return $this->path; return $this->path;
} }
   
/** /**
* Gets the project * Gets the project
* *
* @return GitPHP_Project project * @return GitPHP_Project project
*/ */
public function GetProject() public function GetProject()
{ {
return $this->project; return $this->project;
} }
   
/** /**
* Gets the count * Gets the count
* *
* @return int count * @return int count
*/ */
public function GetCount() public function GetCount()
{ {
if (!$this->dataLoaded) { if (!$this->dataLoaded) {
$this->LoadData(); $this->LoadData();
} }
   
return count($this->history); return count($this->history);
} }
   
/** /**
* Gets the limit * Gets the limit
* *
* @return int limit * @return int limit
*/ */
public function GetLimit() public function GetLimit()
{ {
return $this->limit; return $this->limit;
} }
   
/** /**
* Sets the limit * Sets the limit
* *
* @param int $limit limit * @param int $limit limit
*/ */
public function SetLimit($limit) public function SetLimit($limit)
{ {
if ($this->limit == $limit) if ($this->limit == $limit)
return; return;
   
if ($this->dataLoaded) { if ($this->dataLoaded) {
if (($limit < $this->limit) && ($limit > 0)) { if (($limit < $this->limit) && ($limit > 0)) {
/* want less data, just trim the array */ /* want less data, just trim the array */
$this->history = array_slice($this->history, 0, $limit); $this->history = array_slice($this->history, 0, $limit);
} else if (($limit > $this->limit) || ($limit < 1)) { } else if (($limit > $this->limit) || ($limit < 1)) {
/* want more data, have to reload */ /* want more data, have to reload */
$this->Clear(); $this->Clear();
} }
} }
   
$this->limit = $limit; $this->limit = $limit;
} }
   
/** /**
* Gets the skip number * Gets the skip number
* *
* @return int skip number * @return int skip number
*/ */
public function GetSkip() public function GetSkip()
{ {
return $this->skip; return $this->skip;
} }
   
/** /**
* Sets the skip number * Sets the skip number
* *
* @param int $skip skip number * @param int $skip skip number
*/ */
public function SetSkip($skip) public function SetSkip($skip)
{ {
if ($skip == $this->skip) if ($skip == $this->skip)
return; return;
   
if ($this->dataLoaded) { if ($this->dataLoaded) {
$this->Clear(); $this->Clear();
} }
   
$this->skip = $skip; $this->skip = $skip;
} }
   
/** /**
* Gets the head this log will walk from * Gets the head this log will walk from
* *
* @return GitPHP_Commit head commit * @return GitPHP_Commit head commit
*/ */
public function GetHead() public function GetHead()
{ {
return $this->project->GetCommit($this->hash); return $this->project->GetCommit($this->hash);
} }
   
/** /**
* Sets the head this log will walk from * Sets the head this log will walk from
* *
* @param GitPHP_Commit $head head commit * @param GitPHP_Commit $head head commit
*/ */
public function SetHead($head) public function SetHead($head)
{ {
if ($head) if ($head)
$this->SetHeadHash($head->GetHash()); $this->SetHeadHash($head->GetHash());
else else
$this->SetHeadHash(null); $this->SetHeadHash(null);
} }
   
/** /**
* Gets the head hash this log will walk from * Gets the head hash this log will walk from
* *
* @return string hash * @return string hash
*/ */
public function GetHeadHash() public function GetHeadHash()
{ {
return $this->hash; return $this->hash;
} }
   
/** /**
* Sets the head hash this log will walk from * Sets the head hash this log will walk from
* *
* @param string $hash head commit hash * @param string $hash head commit hash
*/ */
public function SetHeadHash($hash) public function SetHeadHash($hash)
{ {
if (empty($hash)) { if (empty($hash)) {
$head = $this->project->GetHeadCommit(); $head = $this->project->GetHeadCommit();
if ($head) if ($head)
$hash = $head->GetHash(); $hash = $head->GetHash();
} }
   
if ($hash != $this->hash) { if ($hash != $this->hash) {
$this->Clear(); $this->Clear();
$this->hash = $hash; $this->hash = $hash;
} }
} }
   
/** /**
* Loads the history data * Loads the history data
*/ */
protected function LoadData() protected function LoadData()
{ {
$this->dataLoaded = true; $this->dataLoaded = true;
   
$args = array(); $args = array();
$args[] = $this->hash; $args[] = $this->hash;
$args[] = '--no-merges'; $args[] = '--no-merges';
   
$canSkip = true; $canSkip = true;
if ($this->skip > 0) if ($this->skip > 0)
$canSkip = $this->exe->CanSkip(); $canSkip = $this->exe->CanSkip();
   
if ($canSkip) { if ($canSkip) {
if ($this->limit > 0) { if ($this->limit > 0) {
$args[] = '--max-count=' . $this->limit; $args[] = '--max-count=' . $this->limit;
} }
if ($this->skip > 0) { if ($this->skip > 0) {
$args[] = '--skip=' . $this->skip; $args[] = '--skip=' . $this->skip;
} }
} else { } else {
if ($this->limit > 0) { if ($this->limit > 0) {
$args[] = '--max-count=' . ($this->limit + $this->skip); $args[] = '--max-count=' . ($this->limit + $this->skip);
} }
} }
   
$args[] = '--'; $args[] = '--';
$args[] = $this->path; $args[] = $this->path;
$args[] = '|'; $args[] = '|';
$args[] = $this->exe->GetBinary(); $args[] = $this->exe->GetBinary();
$args[] = '--git-dir=' . $this->project->GetPath(); $args[] = '--git-dir=' . escapeshellarg($this->project->GetPath());
$args[] = GIT_DIFF_TREE; $args[] = GIT_DIFF_TREE;
$args[] = '-r'; $args[] = '-r';
$args[] = '--stdin'; $args[] = '--stdin';
$args[] = '--'; $args[] = '--';
$args[] = $this->path; $args[] = $this->path;
$historylines = explode("\n", $this->exe->Execute($this->project->GetPath(), GIT_REV_LIST, $args)); $historylines = explode("\n", $this->exe->Execute($this->project->GetPath(), GIT_REV_LIST, $args));
   
$commitHash = null; $commitHash = null;
foreach ($historylines as $line) { foreach ($historylines as $line) {
if (preg_match('/^([0-9a-fA-F]{40})/', $line, $regs)) { if (preg_match('/^([0-9a-fA-F]{40})/', $line, $regs)) {
$commitHash = $regs[1]; $commitHash = $regs[1];
} else if ($commitHash) { } else if ($commitHash) {
try { try {
$this->history[] = array('diffline' => $line, 'commithash' => $commitHash); $this->history[] = array('diffline' => $line, 'commithash' => $commitHash);
} catch (Exception $e) { } catch (Exception $e) {
} }
$commitHash = null; $commitHash = null;
} }
} }
   
if (($this->skip > 0) && (!$canSkip)) { if (($this->skip > 0) && (!$canSkip)) {
if ($this->limit > 0) { if ($this->limit > 0) {
$this->history = array_slice($this->history, $this->skip, $this->limit); $this->history = array_slice($this->history, $this->skip, $this->limit);
} else { } else {
$this->history = array_slice($this->history, $this->skip); $this->history = array_slice($this->history, $this->skip);
} }
} }
   
} }
   
/** /**
* Rewinds the iterator * Rewinds the iterator
*/ */
function rewind() function rewind()
{ {
if (!$this->dataLoaded) { if (!$this->dataLoaded) {
$this->LoadData(); $this->LoadData();
} }
   
return reset($this->history); return reset($this->history);
} }
   
/** /**
* Returns the current revision * Returns the current revision
* *
* @return GitPHP_Commit * @return GitPHP_Commit
*/ */
function current() function current()
{ {
if (!$this->dataLoaded) { if (!$this->dataLoaded) {
$this->LoadData(); $this->LoadData();
} }
   
$data = current($this->history); $data = current($this->history);
   
if (!(empty($data['diffline']) || empty($data['commithash']))) { if (!(empty($data['diffline']) || empty($data['commithash']))) {
$history = $this->GetProject()->GetObjectManager()->GetFileDiff($data['diffline']); $history = $this->GetProject()->GetObjectManager()->GetFileDiff($data['diffline']);
$history->SetCommitHash($data['commithash']); $history->SetCommitHash($data['commithash']);
return $history; return $history;
} }
   
return null; return null;
} }
   
/** /**
* Returns the current key * Returns the current key
*/ */
function key() function key()
{ {
if (!$this->dataLoaded) { if (!$this->dataLoaded) {
$this->LoadData(); $this->LoadData();
} }
   
return key($this->history); return key($this->history);
} }
   
/** /**
* Advance the pointer * Advance the pointer
*/ */
function next() function next()
{ {
if (!$this->dataLoaded) { if (!$this->dataLoaded) {
$this->LoadData(); $this->LoadData();
} }
   
return next($this->history); return next($this->history);
} }
   
/** /**
* Test for a valid pointer * Test for a valid pointer
* *
* @return boolean * @return boolean
*/ */
function valid() function valid()
{ {
if (!$this->dataLoaded) { if (!$this->dataLoaded) {
$this->LoadData(); $this->LoadData();
} }
   
return key($this->history) !== null; return key($this->history) !== null;
} }
   
/** /**
* Clears the loaded data * Clears the loaded data
*/ */
public function Clear() public function Clear()
{ {
if (!$this->dataLoaded) if (!$this->dataLoaded)
return; return;
   
$this->history = array(); $this->history = array();
reset($this->history); reset($this->history);
   
$this->dataLoaded = false; $this->dataLoaded = false;
} }
} }
   
<?php <?php
   
/** /**
* git cat-file constant * git cat-file constant
*/ */
define('GIT_CAT_FILE','cat-file'); define('GIT_CAT_FILE','cat-file');
   
/** /**
* git diff-tree constant * git diff-tree constant
*/ */
define('GIT_DIFF_TREE','diff-tree'); define('GIT_DIFF_TREE','diff-tree');
   
/** /**
* git ls-tree constant * git ls-tree constant
*/ */
define('GIT_LS_TREE','ls-tree'); define('GIT_LS_TREE','ls-tree');
   
/** /**
* git rev-list constant * git rev-list constant
*/ */
define('GIT_REV_LIST','rev-list'); define('GIT_REV_LIST','rev-list');
   
/** /**
* git rev-parse constant * git rev-parse constant
*/ */
define('GIT_REV_PARSE','rev-parse'); define('GIT_REV_PARSE','rev-parse');
   
/** /**
* git show-ref constant * git show-ref constant
*/ */
define('GIT_SHOW_REF','show-ref'); define('GIT_SHOW_REF','show-ref');
   
/** /**
* git archive constant * git archive constant
*/ */
define('GIT_ARCHIVE','archive'); define('GIT_ARCHIVE','archive');
   
/** /**
* git grep constant * git grep constant
*/ */
define('GIT_GREP','grep'); define('GIT_GREP','grep');
   
/** /**
* git blame constant * git blame constant
*/ */
define('GIT_BLAME','blame'); define('GIT_BLAME','blame');
   
/** /**
* git name-rev constant * git name-rev constant
*/ */
define('GIT_NAME_REV','name-rev'); define('GIT_NAME_REV','name-rev');
   
/** /**
* git for-each-ref constant * git for-each-ref constant
*/ */
define('GIT_FOR_EACH_REF','for-each-ref'); define('GIT_FOR_EACH_REF','for-each-ref');
   
/** /**
* Class to wrap git executable * Class to wrap git executable
* *
* @author Christopher Han <xiphux@gmail.com> * @author Christopher Han <xiphux@gmail.com>
* @copyright Copyright (c) 2010 Christopher Han * @copyright Copyright (c) 2010 Christopher Han
* @package GitPHP * @package GitPHP
* @subpackage Git * @subpackage Git
*/ */
class GitPHP_GitExe implements GitPHP_Observable_Interface class GitPHP_GitExe implements GitPHP_Observable_Interface
{ {
   
/** /**
* The binary path * The binary path
* *
* @var string * @var string
*/ */
protected $binary; protected $binary;
/** /**
* The binary version * The binary version
* *
* @var string * @var string
*/ */
protected $version; protected $version;
   
/** /**
* Whether the version has been read * Whether the version has been read
* *
* @var boolean * @var boolean
*/ */
protected $versionRead = false; protected $versionRead = false;
   
/** /**
* Observers * Observers
* *
* @var GitPHP_Observer_Interface[] * @var GitPHP_Observer_Interface[]
*/ */
protected $observers = array(); protected $observers = array();
   
/** /**
* Whether the exec function is allowed by the install * Whether the exec function is allowed by the install
* *
* @var null|boolean * @var null|boolean
*/ */
protected $execAllowed = null; protected $execAllowed = null;
   
/** /**
* Whether the shell_exec function is allowed by the install * Whether the shell_exec function is allowed by the install
* *
* @var null|boolean * @var null|boolean
*/ */
protected $shellExecAllowed = null; protected $shellExecAllowed = null;
   
/** /**
* Whether the popen function is allowed by the install * Whether the popen function is allowed by the install
* *
* @var null|boolean * @var null|boolean
*/ */
protected $popenAllowed = null; protected $popenAllowed = null;
   
/** /**
* Constructor * Constructor
* *
* @param string $binary path to git binary * @param string $binary path to git binary
*/ */
public function __construct($binary = '') public function __construct($binary = '')
{ {
if (empty($binary)) { if (empty($binary)) {
$binary = GitPHP_GitExe::DefaultBinary(); $binary = GitPHP_GitExe::DefaultBinary();
} }
$this->binary = $binary; $this->binary = $binary;
} }
   
/** /**
* Executes a command * Executes a command
* *
* @param string $projectPath path to project * @param string $projectPath path to project
* @param string $command the command to execute * @param string $command the command to execute
* @param string[] $args arguments * @param string[] $args arguments
* @return string result of command * @return string result of command
*/ */
public function Execute($projectPath, $command, $args) public function Execute($projectPath, $command, $args)
{ {
if ($this->shellExecAllowed === null) { if ($this->shellExecAllowed === null) {
$this->shellExecAllowed = GitPHP_Util::FunctionAllowed('shell_exec'); $this->shellExecAllowed = GitPHP_Util::FunctionAllowed('shell_exec');
if (!$this->shellExecAllowed) { if (!$this->shellExecAllowed) {
throw new GitPHP_DisabledFunctionException('shell_exec'); throw new GitPHP_DisabledFunctionException('shell_exec');
} }
} }
   
$fullCommand = $this->CreateCommand($projectPath, $command, $args); $fullCommand = $this->CreateCommand($projectPath, $command, $args);
   
$this->Log('Begin executing "' . $fullCommand . '"'); $this->Log('Begin executing "' . $fullCommand . '"');
   
$ret = shell_exec($fullCommand); $ret = shell_exec($fullCommand);
   
$this->Log('Finish executing "' . $fullCommand . '"' . $this->Log('Finish executing "' . $fullCommand . '"' .
"\nwith result: " . $ret); "\nwith result: " . $ret);
   
return $ret; return $ret;
} }
   
/** /**
* Opens a resource to a command * Opens a resource to a command
* *
* @param string $projectPath path to project * @param string $projectPath path to project
* @param string $command the command to execute * @param string $command the command to execute
* @param string[] $args arguments * @param string[] $args arguments
* @param string $mode process open mode * @param string $mode process open mode
* @return resource process handle * @return resource process handle
*/ */
public function Open($projectPath, $command, $args, $mode = 'r') public function Open($projectPath, $command, $args, $mode = 'r')
{ {
if ($this->popenAllowed === null) { if ($this->popenAllowed === null) {
$this->popenAllowed = GitPHP_Util::FunctionAllowed('popen'); $this->popenAllowed = GitPHP_Util::FunctionAllowed('popen');
if (!$this->popenAllowed) { if (!$this->popenAllowed) {
throw new GitPHP_DisabledFunctionException('popen'); throw new GitPHP_DisabledFunctionException('popen');
} }
} }
   
$fullCommand = $this->CreateCommand($projectPath, $command, $args); $fullCommand = $this->CreateCommand($projectPath, $command, $args);
   
return popen($fullCommand, $mode); return popen($fullCommand, $mode);
} }
   
/** /**
* Creates a command * Creates a command
* *
* @param string $projectPath path to project * @param string $projectPath path to project
* @param string $command the command to execute * @param string $command the command to execute
* @param string[] $args arguments * @param string[] $args arguments
* @return string full executable string * @return string full executable string
*/ */
protected function CreateCommand($projectPath, $command, $args) protected function CreateCommand($projectPath, $command, $args)
{ {
$gitDir = ''; $gitDir = '';
if (!empty($projectPath)) { if (!empty($projectPath)) {
$gitDir = '--git-dir=' . $projectPath; $gitDir = '--git-dir=' . escapeshellarg($projectPath);
} }
return $this->binary . ' ' . $gitDir . ' ' . $command . ' ' . implode(' ', $args); return $this->binary . ' ' . $gitDir . ' ' . $command . ' ' . implode(' ', $args);
} }
   
/** /**
* Gets the binary for this executable * Gets the binary for this executable
* *
* @return string binary * @return string binary
*/ */
public function GetBinary() public function GetBinary()
{ {
return $this->binary; return $this->binary;
} }
   
/** /**
* Gets the version of the git binary * Gets the version of the git binary
* *
* @return string version * @return string version
*/ */
public function GetVersion() public function GetVersion()
{ {
if (!$this->versionRead) if (!$this->versionRead)
$this->ReadVersion(); $this->ReadVersion();
   
return $this->version; return $this->version;
} }
   
/** /**
* Reads the git version * Reads the git version
*/ */
protected function ReadVersion() protected function ReadVersion()
{ {
if ($this->shellExecAllowed === null) { if ($this->shellExecAllowed === null) {
$this->shellExecAllowed = GitPHP_Util::FunctionAllowed('shell_exec'); $this->shellExecAllowed = GitPHP_Util::FunctionAllowed('shell_exec');
if (!$this->shellExecAllowed) { if (!$this->shellExecAllowed) {
throw new GitPHP_DisabledFunctionException('shell_exec'); throw new GitPHP_DisabledFunctionException('shell_exec');
} }
} }
   
$this->versionRead = true; $this->versionRead = true;
   
$this->version = ''; $this->version = '';
   
$versionCommand = $this->binary . ' --version'; $versionCommand = $this->binary . ' --version';
$ret = trim(shell_exec($versionCommand)); $ret = trim(shell_exec($versionCommand));
if (preg_match('/^git version ([0-9\.]+)$/i', $ret, $regs)) { if (preg_match('/^git version ([0-9\.]+)$/i', $ret, $regs)) {
$this->version = $regs[1]; $this->version = $regs[1];
} }
} }
   
/** /**
* Tests if this version of git can skip through the revision list * Tests if this version of git can skip through the revision list
* *
* @return boolean true if we can skip * @return boolean true if we can skip
*/ */
public function CanSkip() public function CanSkip()
{ {
$version = $this->GetVersion(); $version = $this->GetVersion();
if (!empty($version)) { if (!empty($version)) {
$splitver = explode('.', $version); $splitver = explode('.', $version);
   
/* Skip only appears in git >= 1.5.0 */ /* Skip only appears in git >= 1.5.0 */
if (($splitver[0] < 1) || (($splitver[0] == 1) && ($splitver[1] < 5))) { if (($splitver[0] < 1) || (($splitver[0] == 1) && ($splitver[1] < 5))) {
return false; return false;
} }
} }
   
return true; return true;
} }
   
/** /**
* Tests if this version of git can show the size of a blob when listing a tree * Tests if this version of git can show the size of a blob when listing a tree
* *
* @return true if we can show sizes * @return true if we can show sizes
*/ */
public function CanShowSizeInTree() public function CanShowSizeInTree()
{ {
$version = $this->GetVersion(); $version = $this->GetVersion();
if (!empty($version)) { if (!empty($version)) {
$splitver = explode('.', $version); $splitver = explode('.', $version);
   
/* /*
* ls-tree -l only appears in git 1.5.3 * ls-tree -l only appears in git 1.5.3
* (technically 1.5.3-rc0 but i'm not getting that fancy) * (technically 1.5.3-rc0 but i'm not getting that fancy)
*/ */
if (($splitver[0] < 1) || (($splitver[0] == 1) && ($splitver[1] < 5)) || (($splitver[0] == 1) && ($splitver[1] == 5) && ($splitver[2] < 3))) { if (($splitver[0] < 1) || (($splitver[0] == 1) && ($splitver[1] < 5)) || (($splitver[0] == 1) && ($splitver[1] == 5) && ($splitver[2] < 3))) {
return false; return false;
} }
} }
   
return true; return true;
   
} }
   
/** /**
* Tests if this version of git has the regexp tuning option to ignore regexp case * Tests if this version of git has the regexp tuning option to ignore regexp case
* *
* @return true if we can ignore regexp case * @return true if we can ignore regexp case
*/ */
public function CanIgnoreRegexpCase() public function CanIgnoreRegexpCase()
{ {
$version = $this->GetVersion(); $version = $this->GetVersion();
if (!empty($version)) { if (!empty($version)) {
$splitver = explode('.', $version); $splitver = explode('.', $version);
   
/* /*
* regexp-ignore-case only appears in git 1.5.3 * regexp-ignore-case only appears in git 1.5.3
*/ */
if (($splitver[0] < 1) || (($splitver[0] == 1) && ($splitver[1] < 5)) || (($splitver[0] == 1) && ($splitver[1] == 5) && ($splitver[2] < 3))) { if (($splitver[0] < 1) || (($splitver[0] == 1) && ($splitver[1] < 5)) || (($splitver[0] == 1) && ($splitver[1] == 5) && ($splitver[2] < 3))) {
return false; return false;
} }
} }
   
return true; return true;
} }
   
/** /**
* Tests if this executable is valid * Tests if this executable is valid
* *
* @return boolean true if valid * @return boolean true if valid
*/ */
public function Valid() public function Valid()
{ {
if ($this->execAllowed === null) { if ($this->execAllowed === null) {
$this->execAllowed = GitPHP_Util::FunctionAllowed('exec'); $this->execAllowed = GitPHP_Util::FunctionAllowed('exec');
if (!$this->execAllowed) { if (!$this->execAllowed) {
throw new GitPHP_DisabledFunctionException('exec'); throw new GitPHP_DisabledFunctionException('exec');
} }
} }
   
if (empty($this->binary)) if (empty($this->binary))
return false; return false;
   
$code = 0; $code = 0;
$out = exec($this->binary . ' --version', $tmp, $code); $out = exec($this->binary . ' --version', $tmp, $code);
   
return $code == 0; return $code == 0;
} }
   
/** /**
* Add a new observer * Add a new observer
* *
* @param GitPHP_Observer_Interface $observer observer * @param GitPHP_Observer_Interface $observer observer
*/ */
public function AddObserver($observer) public function AddObserver($observer)
{ {
if (!$observer) if (!$observer)
return; return;
   
if (array_search($observer, $this->observers) !== false) if (array_search($observer, $this->observers) !== false)
return; return;
   
$this->observers[] = $observer; $this->observers[] = $observer;
} }
   
/** /**
* Remove an observer * Remove an observer
* *
* @param GitPHP_Observer_Interface $observer observer * @param GitPHP_Observer_Interface $observer observer
*/ */
public function RemoveObserver($observer) public function RemoveObserver($observer)
{ {
if (!$observer) if (!$observer)
return; return;
   
$key = array_search($observer, $this->observers); $key = array_search($observer, $this->observers);
   
if ($key === false) if ($key === false)
return; return;
   
unset($this->observers[$key]); unset($this->observers[$key]);
} }
   
/** /**
* Log an execution * Log an execution
* *
* @param string $message message * @param string $message message
*/ */
private function Log($message) private function Log($message)
{ {
if (empty($message)) if (empty($message))
return; return;
   
foreach ($this->observers as $observer) { foreach ($this->observers as $observer) {
$observer->ObjectChanged($this, GitPHP_Observer_Interface::LoggableChange, array($message)); $observer->ObjectChanged($this, GitPHP_Observer_Interface::LoggableChange, array($message));
} }
} }
   
/** /**
* Gets the default binary for the platform * Gets the default binary for the platform
* *
* @return string binary * @return string binary
*/ */
public static function DefaultBinary() public static function DefaultBinary()
{ {
if (GitPHP_Util::IsWindows()) { if (GitPHP_Util::IsWindows()) {
// windows // windows
   
if (GitPHP_Util::Is64Bit()) { if (GitPHP_Util::Is64Bit()) {
// match x86_64 and x64 (64 bit) // match x86_64 and x64 (64 bit)
// C:\Program Files (x86)\Git\bin\git.exe // C:\Program Files (x86)\Git\bin\git.exe
return 'C:\\Progra~2\\Git\\bin\\git.exe'; return 'C:\\Progra~2\\Git\\bin\\git.exe';
} else { } else {
// 32 bit // 32 bit
// C:\Program Files\Git\bin\git.exe // C:\Program Files\Git\bin\git.exe
return 'C:\\Progra~1\\Git\\bin\\git.exe'; return 'C:\\Progra~1\\Git\\bin\\git.exe';
} }
} else { } else {
// *nix, just use PATH // *nix, just use PATH
return 'git'; return 'git';
} }
} }
   
} }
   
comments