From f9b9a5ad101b15e95094560b8c48064a4147b7b7 Mon Sep 17 00:00:00 2001 From: rylon Date: Tue, 16 Jun 2015 13:16:30 +0200 Subject: [PATCH] git lib init --- autoload.inc | 3 + lib/Git.php | 113 ++++++++++ lib/GitRepo.php | 572 +++++++++++++++++++++++++++++++++++++++++++++++ lib/autoload.inc | 2 + lib_git.php | 11 + 5 files changed, 701 insertions(+) create mode 100644 autoload.inc create mode 100644 lib/Git.php create mode 100644 lib/GitRepo.php create mode 100644 lib/autoload.inc create mode 100644 lib_git.php diff --git a/autoload.inc b/autoload.inc new file mode 100644 index 0000000..e35c137 --- /dev/null +++ b/autoload.inc @@ -0,0 +1,3 @@ +clone_remote($source, $reference); + } else { + $repo->clone_from($source); + } + } else { + $repo->run('init'); + } + return $repo; + } + } + + /** + * Constructor + * + * Accepts a repository path + * + * @access public + * @param string repository path + * @param bool create if not exists? + * @return void + */ + public function __construct($repo_path = null, $create_new = false, $_init = true) { + if (is_string($repo_path)) { + $this->set_repo_path($repo_path, $create_new, $_init); + } + } + + /** + * Set the repository's path + * + * Accepts the repository path + * + * @access public + * @param string repository path + * @param bool create if not exists? + * @param bool initialize new Git repo if not exists? + * @return void + */ + public function set_repo_path($repo_path, $create_new = false, $_init = true) { + if (is_string($repo_path)) { + if ($new_path = realpath($repo_path)) { + $repo_path = $new_path; + if (is_dir($repo_path)) { + // Is this a work tree? + if (file_exists($repo_path."/.git") || is_dir($repo_path."/.git")) { + $this->repo_path = $repo_path; + $this->bare = false; + // Is this a bare repo? + } else if (is_file($repo_path."/config")) { + $parse_ini = parse_ini_file($repo_path."/config"); + if ($parse_ini['bare']) { + $this->repo_path = $repo_path; + $this->bare = true; + } + } else { + if ($create_new) { + $this->repo_path = $repo_path; + if ($_init) { + $this->run('init'); + } + } else { + throw new \Exception('"'.$repo_path.'" is not a git repository'); + } + } + } else { + throw new \Exception('"'.$repo_path.'" is not a directory'); + } + } else { + if ($create_new) { + if ($parent = realpath(dirname($repo_path))) { + mkdir($repo_path); + $this->repo_path = $repo_path; + if ($_init) $this->run('init'); + } else { + throw new \Exception('cannot create repository in non-existent directory'); + } + } else { + throw new \Exception('"'.$repo_path.'" does not exist'); + } + } + } + } + + /** + * Get the path to the git repo directory (eg. the ".git" directory) + * + * @access public + * @return string + */ + public function git_directory_path() { + return ($this->bare) ? $this->repo_path : $this->repo_path."/.git"; + } + + /** + * Tests if git is installed + * + * @access public + * @return bool + */ + public function test_git() { + $descriptorspec = array( + 1 => array('pipe', 'w'), + 2 => array('pipe', 'w'), + ); + $pipes = array(); + $resource = proc_open(Git::get_bin(), $descriptorspec, $pipes); + + $stdout = stream_get_contents($pipes[1]); + $stderr = stream_get_contents($pipes[2]); + foreach ($pipes as $pipe) { + fclose($pipe); + } + + $status = trim(proc_close($resource)); + return ($status != 127); + } + + /** + * Run a command in the git repository + * + * Accepts a shell command to run + * + * @access protected + * @param string command to run + * @return string + */ + protected function run_command($command) { + $descriptorspec = array( + 1 => array('pipe', 'w'), + 2 => array('pipe', 'w'), + ); + $pipes = array(); + /* Depending on the value of variables_order, $_ENV may be empty. + * In that case, we have to explicitly set the new variables with + * putenv, and call proc_open with env=null to inherit the reset + * of the system. + * + * This is kind of crappy because we cannot easily restore just those + * variables afterwards. + * + * If $_ENV is not empty, then we can just copy it and be done with it. + */ + if(count($_ENV) === 0) { + $env = NULL; + foreach($this->envopts as $k => $v) { + putenv(sprintf("%s=%s",$k,$v)); + } + } else { + $env = array_merge($_ENV, $this->envopts); + } + $cwd = $this->repo_path; + $resource = proc_open($command, $descriptorspec, $pipes, $cwd, $env); + + $stdout = stream_get_contents($pipes[1]); + $stderr = stream_get_contents($pipes[2]); + foreach ($pipes as $pipe) { + fclose($pipe); + } + + $status = trim(proc_close($resource)); + if ($status) throw new \Exception($stderr); + + return $stdout; + } + + /** + * Run a git command in the git repository + * + * Accepts a git command to run + * + * @access public + * @param string command to run + * @return string + */ + public function run($command) { + return $this->run_command(Git::get_bin()." ".$command); + } + + /** + * Runs a 'git status' call + * + * Accept a convert to HTML bool + * + * @access public + * @param bool return string with
+ * @return string + */ + public function status($html = false) { + $msg = $this->run("status"); + if ($html == true) { + $msg = str_replace("\n", "
", $msg); + } + return $msg; + } + + /** + * Runs a `git add` call + * + * Accepts a list of files to add + * + * @access public + * @param mixed files to add + * @return string + */ + public function add($files = "*") { + if (is_array($files)) { + $files = '"'.implode('" "', $files).'"'; + } + return $this->run("add $files -v"); + } + + /** + * Runs a `git rm` call + * + * Accepts a list of files to remove + * + * @access public + * @param mixed files to remove + * @param Boolean use the --cached flag? + * @return string + */ + public function rm($files = "*", $cached = false) { + if (is_array($files)) { + $files = '"'.implode('" "', $files).'"'; + } + return $this->run("rm ".($cached ? '--cached ' : '').$files); + } + + + /** + * Runs a `git commit` call + * + * Accepts a commit message string + * + * @access public + * @param string commit message + * @param boolean should all files be committed automatically (-a flag) + * @return string + */ + public function commit($message = "", $commit_all = true) { + $flags = $commit_all ? '-av' : '-v'; + return $this->run("commit ".$flags." -m ".escapeshellarg($message)); + } + + /** + * Runs a `git clone` call to clone the current repository + * into a different directory + * + * Accepts a target directory + * + * @access public + * @param string target directory + * @return string + */ + public function clone_to($target) { + return $this->run("clone --local ".$this->repo_path." $target"); + } + + /** + * Runs a `git clone` call to clone a different repository + * into the current repository + * + * Accepts a source directory + * + * @access public + * @param string source directory + * @return string + */ + public function clone_from($source) { + return $this->run("clone --local $source ".$this->repo_path); + } + + /** + * Runs a `git clone` call to clone a remote repository + * into the current repository + * + * Accepts a source url + * + * @access public + * @param string source url + * @param string reference path + * @return string + */ + public function clone_remote($source, $reference) { + return $this->run("clone $reference $source ".$this->repo_path); + } + + /** + * Runs a `git clean` call + * + * Accepts a remove directories flag + * + * @access public + * @param bool delete directories? + * @param bool force clean? + * @return string + */ + public function clean($dirs = false, $force = false) { + return $this->run("clean".(($force) ? " -f" : "").(($dirs) ? " -d" : "")); + } + + /** + * Runs a `git branch` call + * + * Accepts a name for the branch + * + * @access public + * @param string branch name + * @return string + */ + public function create_branch($branch) { + return $this->run("branch $branch"); + } + + /** + * Runs a `git branch -[d|D]` call + * + * Accepts a name for the branch + * + * @access public + * @param string branch name + * @return string + */ + public function delete_branch($branch, $force = false) { + return $this->run("branch ".(($force) ? '-D' : '-d')." $branch"); + } + + /** + * Runs a `git branch` call + * + * @access public + * @param bool keep asterisk mark on active branch + * @return array + */ + public function list_branches($keep_asterisk = false) { + $branchArray = explode("\n", $this->run("branch")); + foreach($branchArray as $i => &$branch) { + $branch = trim($branch); + if (! $keep_asterisk) { + $branch = str_replace("* ", "", $branch); + } + if ($branch == "") { + unset($branchArray[$i]); + } + } + return $branchArray; + } + + /** + * Lists remote branches (using `git branch -r`). + * + * Also strips out the HEAD reference (e.g. "origin/HEAD -> origin/master"). + * + * @access public + * @return array + */ + public function list_remote_branches() { + $branchArray = explode("\n", $this->run("branch -r")); + foreach($branchArray as $i => &$branch) { + $branch = trim($branch); + if ($branch == "" || strpos($branch, 'HEAD -> ') !== false) { + unset($branchArray[$i]); + } + } + return $branchArray; + } + + /** + * Returns name of active branch + * + * @access public + * @param bool keep asterisk mark on branch name + * @return string + */ + public function active_branch($keep_asterisk = false) { + $branchArray = $this->list_branches(true); + $active_branch = preg_grep("/^\*/", $branchArray); + reset($active_branch); + if ($keep_asterisk) { + return current($active_branch); + } else { + return str_replace("* ", "", current($active_branch)); + } + } + + /** + * Runs a `git checkout` call + * + * Accepts a name for the branch + * + * @access public + * @param string branch name + * @return string + */ + public function checkout($branch) { + return $this->run("checkout $branch"); + } + + + /** + * Runs a `git merge` call + * + * Accepts a name for the branch to be merged + * + * @access public + * @param string $branch + * @return string + */ + public function merge($branch) { + return $this->run("merge $branch --no-ff"); + } + + + /** + * Runs a git fetch on the current branch + * + * @access public + * @return string + */ + public function fetch() { + return $this->run("fetch"); + } + + /** + * Add a new tag on the current position + * + * Accepts the name for the tag and the message + * + * @param string $tag + * @param string $message + * @return string + */ + public function add_tag($tag, $message = null) { + if ($message === null) { + $message = $tag; + } + return $this->run("tag -a $tag -m " . escapeshellarg($message)); + } + + /** + * List all the available repository tags. + * + * Optionally, accept a shell wildcard pattern and return only tags matching it. + * + * @access public + * @param string $pattern Shell wildcard pattern to match tags against. + * @return array Available repository tags. + */ + public function list_tags($pattern = null) { + $tagArray = explode("\n", $this->run("tag -l $pattern")); + foreach ($tagArray as $i => &$tag) { + $tag = trim($tag); + if ($tag == '') { + unset($tagArray[$i]); + } + } + + return $tagArray; + } + + /** + * Push specific branch to a remote + * + * Accepts the name of the remote and local branch + * + * @param string $remote + * @param string $branch + * @return string + */ + public function push($remote, $branch) { + return $this->run("push --tags $remote $branch"); + } + + /** + * Pull specific branch from remote + * + * Accepts the name of the remote and local branch + * + * @param string $remote + * @param string $branch + * @return string + */ + public function pull($remote, $branch) { + return $this->run("pull $remote $branch"); + } + + /** + * List log entries. + * + * @param strgin $format + * @return string + */ + public function log($format = null) { + if ($format === null) + return $this->run('log'); + else + return $this->run('log --pretty=format:"' . $format . '"'); + } + + /** + * Sets the project description. + * + * @param string $new + */ + public function set_description($new) { + $path = $this->git_directory_path(); + file_put_contents($path."/description", $new); + } + + /** + * Gets the project description. + * + * @return string + */ + public function get_description() { + $path = $this->git_directory_path(); + return file_get_contents($path."/description"); + } + + /** + * Sets custom environment options for calling Git + * + * @param string key + * @param string value + */ + public function setenv($key, $value) { + $this->envopts[$key] = $value; + } + +} + +/* End of file */ \ No newline at end of file diff --git a/lib/autoload.inc b/lib/autoload.inc new file mode 100644 index 0000000..b4c85ca --- /dev/null +++ b/lib/autoload.inc @@ -0,0 +1,2 @@ +0.1.4';} +}