view admin/application/libraries/hgphp.php @ 9:97bc7635ce3f

HGRC read properties, and prepped for write
author joshjcarrier
date Thu, 13 May 2010 19:40:22 -0700
parents 6215bb22f3d3
children 0e7e4cead7c9
line wrap: on
line source

<?php if (!defined('BASEPATH')) exit('No direct script access allowed');

/**
 * CodeIgniter Mercurial Repository Management class
 * 
 * Scans file system and Mercurial projects directory, allowing
 * web-based manipulation of the hgwebdir.config and hgrc configuration files.
 * 
 * Depends on the HgConf2Ini library.
 * 
 * @package        	CodeIgniter
 * @subpackage    	Libraries
 * @category    	Libraries
 * @author 			Josh Carrier
 * @link			blog.joshjcarrier.com
 * 
 */
class HgPHP
{
	private $_ci;
	
	function __construct($config = array())
	{
		if(!empty($config))
		{
			$this->initialize($config);
		}
		
		$this->_ci =& get_instance();
		$this->_ci->lang->load('hgphp');
		$this->_ci->load->library('hgconf2ini');
        log_message('debug', 'HgPHP class Initialized');
	}
	
	function initialize($config = array())
	{
		foreach($config as $key=>$val)
		{
			$this->{'_'.$key} = $val;
		}
	}
	
	/**
	 * Public accessors - hgweb.config
	 */
	
	/**
	 * Returns a list of available repositories.
	 * Will show up if: detected in repo directory
	 * Will have status "enabled" if: detected in hgweb.config
	 * 
	 * @return an array of 0 or more detected repositories
	 */
	function lsdir()
	{
		$realdir = $this->__realdirscan();
		$hgwebdir_compat = $this->_ci->hgconf2ini->getHgWebDirCollections();
				
		// FIXME test no directory cases
		$allrepo = array_merge($realdir, $hgwebdir_compat);
		
		$hgrepos = array();
		foreach($allrepo as $repo)
		{
			$hgrepos[$repo]['name'] = $repo;

			if(isset($realdir[$repo]) && isset($hgwebdir_compat[$repo]))
			{
				$hgrepos[$repo]['status'] = 1;
			}
			else if(isset($realdir[$repo]) && !isset($hgwebdir_compat[$repo]))
			{
				$hgrepos[$repo]['status'] = 0;
			}
			else if(!isset($realdir[$repo]) && isset($hgwebdir_compat[$repo]))
			{
				$hgrepos[$repo]['status'] = 2;
			}
		}
		
		return $hgrepos;
	}
	
	/**
	 * Create a Hg repository by:
	 * - adding an entry in hgwebdir if not present
	 * - creating a bare repository if not present
	 */
	function create_repository($new_repo_name)
	{
		// FIXME constants required
		$return_code = 0;
		
		if(!$this->can_create($new_repo_name))
		{
			// FIXME constants required
			return -1;
		}
		
		$lsdir = $this->lsdir();
		$existingdir = array_keys($lsdir);
		
		// not registered in hgweb.config
		if(!isset($lsdir[$new_repo_name]))
		{
			// create the repository
			$create_status = $this->create_repository_dir($new_repo_name);
			
			if($create_status)
			{
				// edit the directory
				$existingdir[$new_repo_name] = $new_repo_name;
				$create_status = $this->_ci->hgconf2ini->setHgWebDirCollections($existingdir);
				
				// success message
				//$this->template->inject_partial('user_msg', 'Repository "'. $new_repo_name .'" created successfully.');
				return 0;
			}
			else
			{
				return -2;
				//$this->template->inject_partial('user_err', 'Repository "'. $new_repo_name .'" could not be created; insufficient user or server privileges.');
			}
		}
		// TODO repair missing directory?
		else if($lsdir[$new_repo_name]['status'] == 2)
		{
			return -3;
			//$this->template->inject_partial('user_msg', 'Repository "'. $new_repo_name .'" RESTORE.');
		}
		else
		{
			return -4;
			//$this->template->inject_partial('user_err', 'Repository "'. $new_repo_name .'" could not be created; it already exists.');
		}
		
	}
	
	// TODO
	function update_repository()
	{}
	
	function delete_repository($del_repo_name)
	{
		$return_code = 0;
		
		if(!$this->can_delete($del_repo_name))
		{
			// FIXME constants required
			return -1;
		}
		
		$lsdir = $this->lsdir();
		$existingdir = array_keys($lsdir);
		$tempexistingdir = array();
		foreach($existingdir as $repo_name)
		{
			$tempexistingdir[$repo_name] = $repo_name;
		}
		$existingdir = $tempexistingdir;
		
		if(isset($lsdir[$del_repo_name]))
		{
			$del_status = true;
			
			// existing filesystem is not missing, thus needs to be deleted
			if($lsdir[$del_repo_name]['status'] != 2)
			{
				$del_status = $this->delete_repository_dir($del_repo_name);
			}
			
			// remove from hgweb.config
			if($del_status)
			{
				// edit the directory
				unset($existingdir[$del_repo_name]);

				$this->_ci->hgconf2ini->setHgWebDirCollections($existingdir);

				// success message
				// FIXME constants required
				return 0;
//				$this->template->inject_partial('user_msg', 'Repository "'. $del_repo_name .'" deleted successfully.');
			}
			else
			{
				// FIXME constants required
				return -2;
//				$this->template->inject_partial('user_err', 'Repository "'. $del_repo_name .'" could not be deleted; insufficient user or server privileges.');
			}
		}
		else
		{
			// FIXME constants required
			return -3;
//			$this->template->inject_partial('user_err', 'Repository "'. $del_repo_name .'" could not be deleted; it does not exist or is already deleted.');
		}
	}
	
	function stat_repository($project_name)
	{
		// FIXME permission check 
		
		return $this->_ci->hgconf2ini->getHGRC($project_name);
	}
	 
	 /**
	  * Public accessors - permissions
	  */
	  
	function can_create($repository_name)
	{
		return $this->_hgwebconf_allow_repo_create;
	}
	
	function can_delete($repository_name)
	{
		return $this->_hgwebconf_allow_repo_delete;
	}
	
	/**
	 * Public helpers - filesystem
	 */
	 
	function create_repository_dir($repository_name)
	{
		if(!$this->can_create($repository_name))
		{
			return false;
		}
		
		$cd = $this->_repositories_rel_dir;
		mkdir($cd . $repository_name . '/.hg/store/data/', 0755, TRUE);
		
		// create hgrc
		return $this->_ci->hgconf2ini->touchHGRC($repository_name);
	}
	
	function delete_repository_dir($repository_name)
	{
		if(!$this->can_delete($repository_name))
		{
			return false;
		}
		
		$cd = $this->_repositories_rel_dir . $repository_name;
		
		$this->recursiveDelete($cd . '/.hg/');
		return $this->recursiveDelete($cd);
	}
	 
	  /**
	   * Private helpers - hgweb.config
	   */
	
	/**
	 * Performs a real directory scan where the projects are suppose to reside.
	 * 
	 * @return the array containing 0 or more valid directories
	 */
	function __realdirscan()
	{
		$this->_ci->load->helper('directory');
		
		// FIXME this doesn't check if file or directory...
		$realdir = directory_map($this->_repositories_rel_dir, TRUE);
		
		$verifiedrealdir = array();
		foreach($realdir as $file)
		{
			// checks if we detected a folder
			if(is_dir($this->_repositories_rel_dir . $file))
			{
				$verifiedrealdir[$file] = $file;
			}
		}
		
		return $verifiedrealdir;
	}
	
	
	
	function getProjectParams()
	{
		return array('ui'=>array('config1'=>'value'));
	}
	

	
	
	/**
     * Delete a file or recursively delete a directory
     *
     * @param string $str Path to file or directory
     */
    function recursiveDelete($str){
        if(is_file($str)){
            return @unlink($str);
        }
        elseif(is_dir($str)){
            $scan = glob(rtrim($str,'/').'/*');
            foreach($scan as $index=>$path){
                $this->recursiveDelete($path);
            }
            return @rmdir($str);
        }
    }
}