160 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			160 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| 
 | |
| namespace Zotlabs\Storage;
 | |
| 
 | |
| use PHPGit\Git as PHPGit;
 | |
| 
 | |
| require __DIR__ . '/../../library/PHPGit.autoload.php'; // Load PHPGit dependencies
 | |
| 
 | |
| /**
 | |
|  * Wrapper class for PHPGit class for git repositories managed by Hubzilla
 | |
|  *
 | |
|  * @author Andrew Manning <andrewmanning@grid.reticu.li>
 | |
|  */
 | |
| class GitRepo {
 | |
| 
 | |
| 	public $url = null;
 | |
| 	public $name = null;
 | |
| 	private $path = null;
 | |
| 	private $channel = null;
 | |
| 	public $git = null;
 | |
| 	private $repoBasePath = null;
 | |
| 
 | |
| 	function __construct($channel = 'sys', $url = null, $clone = false, $name = null, $path = null) {
 | |
| 
 | |
| 		if ($channel === 'sys' && !is_site_admin()) {
 | |
| 			logger('Only admin can use channel sys');
 | |
| 			return null;
 | |
| 		}
 | |
| 
 | |
| 		$this->repoBasePath = __DIR__ . '/../../store/git';
 | |
| 		$this->channel = $channel;
 | |
| 		$this->git = new PHPGit();
 | |
| 
 | |
| 		// Allow custom path for repo in the case of , for example
 | |
| 		if ($path) {
 | |
| 			$this->path = $path;
 | |
| 		} else {
 | |
| 			$this->path = $this->repoBasePath . "/" . $this->channel . "/" . $this->name;
 | |
| 		}
 | |
| 
 | |
| 		if ($this->isValidGitRepoURL($url)) {
 | |
| 			$this->url = $url;
 | |
| 		}
 | |
| 
 | |
| 		if ($name) {
 | |
| 			$this->name = $name;
 | |
| 		} else {
 | |
| 			$this->name = $this->getRepoNameFromURL($url);
 | |
| 		}
 | |
| 		if (!$this->name) {
 | |
| 			logger('Error creating GitRepo. No repo name found.');
 | |
| 			return null;
 | |
| 		}
 | |
| 
 | |
| 		if (is_dir($this->path)) {
 | |
| 			// ignore the $url input if it exists
 | |
| 			// TODO: Check if the path is either empty or is a valid git repo and error if not
 | |
| 			$this->git->setRepository($this->path);
 | |
| 			// TODO: get repo metadata 
 | |
| 			return;
 | |
| 		}
 | |
| 
 | |
| 		if ($this->url) {
 | |
| 			// create the folder and clone the repo at url to that folder if $clone is true
 | |
| 			if ($clone) {
 | |
| 				if (mkdir($this->path, 0770, true)) {
 | |
| 					$this->git->setRepository($this->path);
 | |
| 					if (!$this->cloneRepo()) {
 | |
| 						// TODO: throw error
 | |
| 						logger('git clone failed: ' . json_encode($this->git));
 | |
| 					}
 | |
| 				} else {
 | |
| 					logger('git repo path could not be created: ' . json_encode($this->git));
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	
 | |
| 	public function initRepo() {
 | |
| 		if(!$this->path) return false;
 | |
| 		try {
 | |
| 			return $this->git->init($this->path);
 | |
| 		} catch (\PHPGit\Exception\GitException $ex) {
 | |
| 			return false;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public function pull() {
 | |
| 		try {
 | |
| 			$success = $this->git->pull();
 | |
| 		} catch (\PHPGit\Exception\GitException $ex) {
 | |
| 			return false;
 | |
| 		}
 | |
| 		return $success;
 | |
| 	}
 | |
| 
 | |
| 	public function getRepoPath() {
 | |
| 		return $this->path;
 | |
| 	}
 | |
| 
 | |
| 	public function setRepoPath($directory) {
 | |
| 		if (is_dir($directory)) {
 | |
| 			$this->path->$directory;
 | |
| 			$this->git->setRepository($directory);
 | |
| 			return true;
 | |
| 		}
 | |
| 		return false;
 | |
| 	}
 | |
| 
 | |
| 	public function setIdentity($user_name, $user_email) {
 | |
| 		// setup user for commit messages
 | |
| 		$this->git->config->set("user.name", $user_name, ['global' => false, 'system' => false]);
 | |
| 		$this->git->config->set("user.email", $user_email, ['global' => false, 'system' => false]);
 | |
| 	}
 | |
| 
 | |
| 	public function cloneRepo() {
 | |
| 		if (validate_url($this->url) && $this->isValidGitRepoURL($this->url) && is_dir($this->path)) {
 | |
| 			return $this->git->clone($this->url, $this->path);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public function probeRepo() {
 | |
| 		$git = $this->git;
 | |
| 		$repo = array();
 | |
| 		$repo['remote'] = $git->remote();
 | |
| 		$repo['branches'] = $git->branch(['all' => true]);
 | |
| 		$repo['logs'] = $git->log(array('limit' => 50));
 | |
| 		return $repo;
 | |
| 	}
 | |
| 	
 | |
| 	// Commit changes to the repo. Default is to stage all changes and commit everything.
 | |
| 	public function commit($msg, $options = array()) {
 | |
| 		try {
 | |
| 			return $this->git->commit($msg, $options);
 | |
| 		} catch (\PHPGit\Exception\GitException $ex) {
 | |
| 			return false;
 | |
| 		}		
 | |
| 	}
 | |
| 
 | |
| 	public static function isValidGitRepoURL($url) {
 | |
| 		if (validate_url($url) && strrpos(parse_url($url, PHP_URL_PATH), '.')) {
 | |
| 			return true;
 | |
| 		} else {
 | |
| 			return false;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public static function getRepoNameFromURL($url) {
 | |
| 		$urlpath = parse_url($url, PHP_URL_PATH);
 | |
| 		$lastslash = strrpos($urlpath, '/') + 1;
 | |
| 		$gitext = strrpos($urlpath, '.');
 | |
| 		if ($gitext) {
 | |
| 			return substr($urlpath, $lastslash, $gitext - $lastslash);
 | |
| 		} else {
 | |
| 			return null;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| }
 |