From b71fd6d276e1b3f58903307ec6d3a0f7cd15538c Mon Sep 17 00:00:00 2001 From: pk910 Date: Sun, 6 Oct 2013 01:12:28 +0200 Subject: [PATCH] added basic functions to GITManagedWebpage.class.php --- GITManagedWebpage.class.php | 232 ++++++++++++++++++++++++++++++++++-- 1 file changed, 220 insertions(+), 12 deletions(-) diff --git a/GITManagedWebpage.class.php b/GITManagedWebpage.class.php index 9093b8a..305530b 100644 --- a/GITManagedWebpage.class.php +++ b/GITManagedWebpage.class.php @@ -25,31 +25,54 @@ class GITManagedWebpage { const ERROR_CRITICAL = 1; - + const SESSION_PREFIX = "GITManagedWebpage_"; private $giturl; - private $workdir; + private $workdir, $localdir; + private $ready = false; + private $loopedcall = false; + private $config = null; + private $config_changed = true; - public function __construct($giturl, $workdir = null) { + public function __construct($giturl, $workdir = null, $localdir = null) { + if(session_status() != PHP_SESSION_ACTIVE) { + session_start(); + } + + if(defined("GITMANAGED_EXECUTED")) { + $this->loopedcall = true; + return; + } + if($workdir === null) { $workdir = dirname(__FILE__); - if(!substr($workdir, -1) == "/") + if(substr($workdir, -1) != "/") $workdir .= "/"; $workdir .= ".gitmanaged/"; } - else if(!substr($workdir, -1) == "/") + else if(substr($workdir, -1) != "/") $workdir .= "/"; + if($localdir === null) { + $localdir = dirname(__FILE__); + if(substr($localdir, -1) != "/") + $localdir .= "/"; + } + else if(substr($localdir, -1) != "/") + $localdir .= "/"; + $this->giturl = $giturl; $this->workdir = $workdir; + $this->localdir = $localdir; - //if(!file_exists($this->workdir) || !is_dir($this->workdir)) { + if(!file_exists($this->workdir) || !is_dir($this->workdir)) { if(file_exists($this->workdir) && !is_dir($this->workdir)) { $this->error(self::ERROR_CRITICAL, "local workdir (".htmlspecialchars($this->workdir).") is not a directory."); return; } $this->setupWorkdir(); - //} + } + $this->ready = true; } /* private function gitcmd(...) @@ -66,11 +89,48 @@ class GITManagedWebpage { } else $argstr .= " ".escapeshellarg($arg); } - $gitcmd = 'git '.escapeshellarg('--git-dir='.$this->workdir.'/repository').$argstr; + $gitcmd = 'git '.escapeshellarg('--git-dir='.$this->workdir.'repository/.git').$argstr; $output = shell_exec($gitcmd); return $output; } + /* private function setConfig($name, $value) + * store a option in the configuration + */ + private function setConfig($name, $value) { + $this->config[strtolower($name)] = $value; + $this->config_changed = true; + } + + /* private function getConfig($name) + * get an option from the configuration + */ + private function getConfig($name) { + if($this->config == null) { + if(!$this->ready) + return null; + if(file_exists($this->workdir."config.txt")) { + $config_txt = @file_get_contents($this->workdir."config.txt"); + $this->config = unserialize($config_txt); + } else { + $this->config = array(); + return null; + } + } + if(array_key_exists(strtolower($name), $this->config)) + return $this->config[strtolower($name)]; + else + return null; + } + + private function saveConfig() { + if($this->config_changed && $this->ready) { + $fp = fopen($this->workdir."config.txt", "w"); + fwrite($fp, serialize($this->config)); + fclose($fp); + } + } + /* private function setupWorkdir() * Setup local GITManagedWebpage Work directory with git repository */ @@ -83,24 +143,172 @@ class GITManagedWebpage { } mkdir($this->workdir); - mkdir($this->workdir.'/repository'); - shell_exec('git clone '.escapeshellarg($this->giturl).' '.escapeshellarg($this->workdir.'/repository')); + mkdir($this->workdir.'repository'); + shell_exec('git clone '.escapeshellarg($this->giturl).' '.escapeshellarg($this->workdir.'repository')); $gitok = $this->gitcmd("status"); if(preg_match("#Not a git repository#", $gitok)) { - rmdir($this->workdir.'/repository'); + rmdir($this->workdir.'repository'); rmdir($this->workdir); $this->error(self::ERROR_CRITICAL, "error cloning git repository."); return; } + $this->ready = true; + + $default_branch = str_replace(array("\r", "\n"), array("", ""), $this->gitcmd("rev-parse", "--abbrev-ref", "HEAD")); + $this->setConfig("defaultbranch", $default_branch); + $this->saveConfig(); + } + + private function getActiveBranch() { + if($this->activeSession) + return $this->activeSession; + else if(isset($_SESSION[self::SESSION_PREFIX.'branch'])) + return $_SESSION[self::SESSION_PREFIX.'branch']; + else + return $this->getConfig("defaultbranch"); + } + + private function setActiveBranch($branch, $remember) { + $this->activeSession = $branch; + if($remember) + $_SESSION[self::SESSION_PREFIX.'branch'] = $branch; + } + + private function getLocalUntrackedFiles() { + $default_branch = $this->getConfig("defaultbranch"); + $tracked_files = $this->gitcmd("ls-tree", $default_branch, "--full-name", "--name-only"); + $local_files = shell_exec("find ".escapeshellarg($this->localdir)); + $untracked_files = array(); + $tracked_files = explode("\n", str_replace(array("\r"), array(""), $tracked_files)); + $local_files = explode("\n", str_replace(array("\r"), array(""), $local_files)); + foreach($local_files as $local_file) { + if(!$local_file) + continue; + if($strip_local || (($strip_local = strlen($this->localdir)) && substr($local_file, 0, $strip_local) == $this->localdir)) { + $local_file = substr($local_file, $strip_local); + } + $tracked = false; + foreach($tracked_files as $tracked_file) { + if($tracked_file == $local_file) { + $tracked = true; + break; + } + } + if(!$tracked) { + $untracked_files[] = $local_file; + } + } + return $untracked_files; + } + + private function branchExists($branch) { + //check if branch exists + $gitret = $this->gitcmd("rev-list", "--max-count=1", $branch); + if(!preg_match("#([a-z0-9]{40})#", $gitret, $match)) + return false; + else + return $match[1]; + } + + private function localBranchPath($branch, $create = false) { + $default_branch = $this->getConfig("defaultbranch"); + if($branch == $default_branch) + $dir = $this->localdir; + else + $dir = $this->workdir.'branch_'.$branch.'/'; + if(file_exists($dir)) + return $dir; + else if($create) { + mkdir($dir); + return $dir; + } else + return false; + } + + private function updateBranch($branch, $path) { + if(substr($path, -1) != '/') + $path .= '/'; + $current_branch = str_replace(array("\r", "\n"), array("", ""), $this->gitcmd("rev-parse", "--abbrev-ref", "HEAD")); + if($current_branch != $branch) + $this->gitcmd("checkout", $branch); + $this->gitcmd("pull"); + $gitret = $this->gitcmd("rev-list", "--max-count=1", $branch); + preg_match("#([a-z0-9]{40})#", $gitret, $match); + $newest_version = $match[1]; + + if(($current_version = $this->getConfig('version_'.$branch))) { + if($current_version == $newest_version) + return; + else { + //applying patch + $difftxt = $this->gitcmd("diff", $current_version, $newest_version); + echo $difftxt; + } + } else + $override_all = true; + if($override_all) { + $rsync_present = preg_match("#rsync#", `which rsync`); + if($rsync_present) + shell_exec('rsync -avz --exclude ".git" '.escapeshellarg($this->workdir."repository/").' '.escapeshellarg($path)); + else + shell_exec('tar -c --exclude ".git" -C '.escapeshellarg($this->workdir."repository").' . | tar -x -C '.escapeshellarg($path)); + } + $this->setConfig('version_'.$branch, $newest_version); + //$this->saveConfig(); } /* public function update() - * Pulls latest commit of active branch and overwrites local files + * Pulls latest commit of active branch and overwrites files in branch folder */ public function update() { + if($this->loopedcall) + return; + + $active_branch = $this->getActiveBranch(); + + if(!$this->branchExists($active_branch)) + return false; + $dir = $this->localBranchPath($active_branch, true); + $this->updateBranch($active_branch, $dir); + } + + public function setBranch($branch, $remember = false) { + if($this->loopedcall) + return; + + if(!$this->branchExists($branch)) + return false; + $this->setActiveBranch($branch, $remember); + + if(!$this->localBranchPath($branch)) { + $dir = $this->localBranchPath($branch, true); + $this->updateBranch($branch, $dir); + } + } + public function execute($file = null) { + if($this->loopedcall) + return; + define("GITMANAGED_EXECUTED", true); + + if(!$file) + $file = $_SERVER['PHP_SELF']; + if($file[0] == '/') + $file = substr($file, 1); + + $default_branch = $this->getConfig("defaultbranch"); + $active_branch = $this->getActiveBranch(); + if($active_branch != $default_branch) { + if(!($dir = $this->localBranchPath($branch))) { + $dir = $this->localBranchPath($active_branch, true); + $this->updateBranch($active_branch, $dir); + } + include_once($dir.$file); + } else { + include_once($this->localdir.$file); + } } } -- 2.20.1