PHP Classes

File: src/GitProvider.php

Recommend this page to a friend!
  Classes of Maik Greubel   PHP Git Library Provider   src/GitProvider.php   Download  
File: src/GitProvider.php
Role: Class source
Content type: text/plain
Description: The main class
Class: PHP Git Library Provider
Manipulate Git repositories using the git command
Author: By
Last change: Update of src/GitProvider.php
Date: 11 months ago
Size: 13,998 bytes
 

Contents

Class file image Download
<?php namespace Nkey\GitProvider; use Generics\Util\Directory; use Generics\Logger\LoggerTrait; /** * Git provider * * @author Maik Greubel <greubel@nkey.de> */ class GitProvider { use LoggerTrait; /** * The path to repository * * @var string */ private $path; /** * The name (description) of the repository * * @var string */ private $projectName; /** * Whether the repository is bare (non-workspace) * * @var bool */ private $bare; /** * Create a new GitProvider object * * @param string $path * @param string $projectName * @param bool $bare * @throws GitProviderException */ public function __construct($path) { $this->path = $path; } /** * Check repository * * @throws GitProviderException */ private function check() { if (! file_exists($this->path) || ! is_dir($this->path)) { throw new GitProviderException("Invalid repository path, {path} does not exist", array( 'path' => $this->path )); } if ((! file_exists("$this->path/.git") || ! is_dir("$this->path/.git"))) { if (! file_exists("$this->path/HEAD")) { throw new GitProviderException("Invalid repository path, {path} does not seems to be a git repo", array( 'path' => $this->path )); } $this->bare = true; } else { $this->bare = false; } } /** * Intialize a brand new repository * * @param string $path * The path where it will be created * @param bool $bare * Whether it will be a bare repository * @param bool $shared * Whether it should be a shared (or private = false) repository * * @throws GitProviderException */ private function init($path, $bare = false, $shared = false) { $parameters = array(); if ($bare) { $parameters[] = '--bare'; } if ($shared) { $parameters[] = '--shared=0775'; } else { $parameters[] = '--shared=0700'; } $parameters[] = sprintf("'%s'", $path); $this->execute("init", $parameters); $dir = new Directory($this->path); $this->path = $dir->getPath(); } /** * Generates the execution command by parsing the context * * @param string $command * @param array $context * @return string */ private function generateExecutionCommand($command, $context) { $toExecute = "git $command"; foreach ($context as $argument => $parameter) { if (! is_int($argument)) { $toExecute .= sprintf(" %s %s", $argument, $parameter); } else { $toExecute .= " $parameter"; } } $toExecute .= " 2>&1"; return $toExecute; } /** * Parse the output of command * * @param string $command * The command which has been executed * @param string $toExecute * The full command line for logging purposes * @param array $output * The output which the command has been done * @param int $returnvalue * The return value of the command * * @throws GitProviderException * * @return string|array The parsed command */ private function evaluateOutput($command, $toExecute, $output, $returnvalue, $outputAsString) { $this->getLog()->debug("{executed}\ncode: {result}\noutput:{output}", array( 'excuted' => $toExecute, 'result' => $returnvalue, 'output' => implode("\n", $output) )); if ($returnvalue != 0) { throw new GitProviderException("Could not execute command {command}: errorcode = {code}; {reason}", array( 'command' => $command, 'code' => $returnvalue, 'reason' => implode('', $output) )); } $tmpout = array(); foreach ($output as $line) { $line = trim($line); if (strlen($line) > 0) { $tmpout[] = $line; } } if (count($tmpout) == 0) { return $outputAsString ? "" : array(); } return $outputAsString ? implode("\n", $tmpout) : $tmpout; } /** * Executes an abritary git command * * @param string $command * The command to execute * @param array $context * Contextual parameters * @return string|array The output of command * * @throws GitProviderException */ private function execute($command, $context, $outputAsString = true) { $currentDir = null; if ($command != 'init') { $currentDir = getcwd(); chdir($this->path); } $output = array(); $returnvalue = 0; $toExecute = $this->generateExecutionCommand($command, $context); exec("$toExecute", $output, $returnvalue); if ($currentDir != null) { chdir($currentDir); } return $this->evaluateOutput($command, $toExecute, $output, $returnvalue, $outputAsString); } /** * Create a new repository * * @param string $path * The path to repository * @param string $projectName * The name of the project (will be written to description in case of bare) * @param bool $bare * Whether the repository should be a bare (non-workspace) one * @param bool $shared * Whether other users than the owner of the project have access to this */ public function create($bare = false, $shared = false) { $this->init($this->path, $bare, $shared); $this->setProjectName($this->projectName); $this->bare = $bare; } /** * Set the project name; In case of bare repository it will be written to description file. * * @param string $projectName * * @throws GitProviderException */ public function setProjectName($projectName) { $this->check(); $this->projectName = $projectName; if ($projectName === null) { return; } if (! $this->bare) { throw new GitProviderException("Could not write description file on non-bare repository!"); } $fd = null; $fd = fopen("$this->path/description", "w"); if (! $fd) { throw new GitProviderException("Setting the name not possible, could not open description file!"); } fputs($fd, $projectName, strlen($projectName)); fflush($fd); fclose($fd); } /** * Set the user and email address for the repository * * @param string $authorName * The name of author (you) * @param string $authorEmail * The email address of author (your email) */ public function setAuthor($authorName, $authorEmail) { $parameters = array(); $parameters[] = '--local'; $parameters["user.name"] = sprintf("'%s'", $authorName); $this->execute("config", $parameters); $parameters = array(); $parameters[] = '--local'; $parameters["user.email"] = sprintf("'%s'", $authorEmail); $this->execute("config", $parameters); } /** * Retrieve the absolute path to repository * * @return string */ public function getPath() { return $this->path; } /** * Retrieve the directory of repository * * @return \Generics\Util\Directory */ public function getDirectory() { return new Directory($this->path); } /** * Add a subset of entries to index * * @param string $pattern * @throws GitProviderException */ public function addToIndex($pattern = ".") { $parameters = array(); if (! strlen($pattern) > 0) { throw new GitProviderException("Invalid pattern"); } $parameters[] = $pattern; $this->execute("add", $parameters); } /** * Check whether a subset of files is staged * * @param string $pattern * @return boolean */ public function isStaged($pattern) { $parameters = array(); $parameters[] = "--cached"; $parameters[] = "--name-only"; $files = $this->execute("diff", $parameters, false); foreach ($files as $file) { if (preg_match("/$pattern/", $file)) { return true; } } return false; } /** * Commits the staged area * * @param string $message * * @throws GitProviderException */ public function commit($message) { if (strlen($message) == 0) { throw new GitProviderException("Invalid commit message (must not be empty)"); } $parameters = array(); $parameters["-m"] = sprintf("'%s'", $message); $this->execute("commit", $parameters); } /** * Remove a file from repository (or staging area) * * @param string $pattern * The file to be removed * @param boolean $force * Whether to force the removal */ public function remove($pattern, $force = false) { $parameters = array(); if ($this->isStaged($pattern)) { $parameters[] = '--cached'; } if ($force) { $parameters[] = '-f'; } $parameters[] = $pattern; $this->execute('rm', $parameters); } /** * Clones an existing repository * * @param string $uri */ public function cloneFrom($uri) { $parameters = array(); $uri = str_replace('\\', '/', $uri); if (substr($uri, 0, 4) == 'http' || substr($uri, 0, 3) == 'git' || substr($uri, 0, 3) == 'ssh') { $parameters[] = $uri; } elseif (strstr($uri, "://")) { throw new GitProviderException("Invalid uri {uri} given", array( 'uri' => $uri )); } else { $dir = new Directory($uri); if (! $dir->exists()) { $dir->create(true); $this->path = $dir->getPath(); } $uri = sprintf("file://%s%s", (substr($uri, 0, 1) == '/' ? '' : '/'), $uri); $parameters[] = sprintf("'%s'", $uri); } $parameters[] = "."; $this->execute("clone", $parameters); } /** * Checks whether working repository is empty * * @param string $filter * The filter to skip from check * * @throws GitProviderException * * @return boolean */ public function isEmpty($filter = null) { if ($this->bare) { throw new GitProviderException("Could not check emptyness of bare repository"); } $dir = new Directory($this->path); return $dir->isEmpty($filter); } /** * Destroy the repository */ public function destroy() { $dir = new Directory($this->path); $dir->remove(true); } /** * Check whether a branch exists * * @param string $branchName * @return boolean */ public function hasBranch($branchName) { $branches = $this->execute("branch", array(), false); if (count($branches) == 0) { return false; } foreach ($branches as $branch) { if ($branch[0] === '*') { $branch[0] = ' '; } $branch = trim($branch); if ($branch == $branchName) { return true; } } return false; } /** * Push the commited changes to origin repository * * @param string $branch * The branch to push * @param string $remote * The remote identifier */ public function push($branch = "master", $remote = "origin") { if (! $this->hasBranch("master")) { throw new GitProviderException("Nothing commited yet on empty repository!"); } $parameters = array(); $parameters[] = $remote; if ($this->hasBranch($branch)) { $parameters[] = $branch; } $this->execute("push", $parameters); } /** * Pull all changes from origin repository * * @param string $remote * The remote identifier */ public function pull($remote = "origin") { $parameters = array(); $parameters[] = $remote; $this->execute("pull", $parameters); } /** * Create a new branch * * @param string $branch * The name of the new created branch * * @throws GitProviderException */ public function createBranch($branch) { if ($this->hasBranch($branch)) { throw new GitProviderException("Branch {branch} already exists", array( 'branch' => $branch )); } $parameters = array(); $parameters[] = $branch; $this->execute("branch", $parameters); } /** * Checkout a branch * * @param string $branch * The name of branch to checkout (empty branch name will checkout current branch) * * @throws GitProviderException */ public function checkout($branch = "") { $parameters = array(); if (strlen($branch) > 0) { $parameters[] = $branch; } $this->execute("checkout", $parameters); } }