Changeset 392

Show
Ignore:
Timestamp:
10/08/07 21:56:27 (1 year ago)
Author:
bermiferrer
Message:

- Adding new command line script for managing plugins.
- Improved the AkPluginManager? to use subversion when available.
- Fixed bug in Ak::directory_delete which prevented removing directories that contained files which started with a dot.
- Fixing bug #57. Setup directories should be removed now on unix and windows
- Adding timeout options to Ak::url_get_contents, and setting CURLOPT_RETURNTRANSFER for following redirects. FIxed a referrer bug.
- Updating doc packages for other scripts.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/app/models/framework_setup.php

    r366 r392  
    738738        AK_APP_DIR.DS.'installers'.DS.'framework_version.txt', 
    739739        AK_APP_DIR.DS.'models'.DS.'framework_setup.php', 
    740         AK_APP_DIR.DS.'controllers'.DS.'framework_setup_controller.php', 
     740        AK_APP_DIR.DS.'controllers'.DS.'framework_setup_controller.php' 
     741        )); 
     742        @array_map(array('Ak','directory_delete'),  array( 
    741743        AK_APP_DIR.DS.'views'.DS.'framework_setup', 
    742744        AK_APP_DIR.DS.'locales'.DS.'framework_setup' 
  • trunk/lib/Ak.php

    r383 r392  
    448448            return AkFtp::delete($dir_name); 
    449449        }else{ 
    450             if($fs_items = glob($options['base_path'].DS.$dir_name."/*")){ 
     450            $items = glob($options['base_path'].DS.$dir_name."/*"); 
     451            $hidden_items = glob($options['base_path'].DS.$dir_name."/.*"); 
     452            $fs_items = $items || $hidden_items ? array_merge((array)$items, (array)$hidden_items) : false; 
     453            if($fs_items){ 
    451454                $items_to_delete = array('directories'=>array(), 'files'=>array()); 
    452455                foreach($fs_items as $fs_item) { 
    453                     $items_to_delete[ (is_dir($fs_item) ? 'directories' : 'files') ][] = $fs_item; 
     456                    if($fs_item[strlen($fs_item)-1] != '.'){ 
     457                        $items_to_delete[ (is_dir($fs_item) ? 'directories' : 'files') ][] = $fs_item; 
     458                    } 
    454459                } 
    455460                foreach ($items_to_delete['files'] as $file){ 
     
    579584        'referer' => $url, 
    580585        'method' => 'post', 
     586        'timeout' => 100, 
    581587        'params' => '', 
    582588        'browser_name' => 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)', 
     
    590596        $ch = curl_init(); 
    591597 
    592         curl_setopt ($ch, CURLOPT_URL, $options['referer']); 
    593         curl_setopt ($ch, CURLOPT_USERAGENT, $options['browser_name']); 
    594         curl_setopt ($ch, CURLOPT_HEADER, 0); 
     598        curl_setopt($ch, CURLOPT_URL, $url); 
     599        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); 
     600        curl_setopt($ch, CURLOPT_USERAGENT, $options['browser_name']); 
     601        curl_setopt($ch, CURLOPT_HEADER, 0); 
    595602 
    596603        if(!empty($options['params']) && $options['method'] == 'post'){ 
     
    601608        } 
    602609 
    603         curl_setopt ($ch, CURLOPT_REFERER, $url); 
    604  
    605         curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1); 
    606         curl_setopt($ch, CURLOPT_TIMEOUT, 100); 
     610        curl_setopt ($ch, CURLOPT_REFERER, $options['referer']); 
     611 
     612        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
     613        curl_setopt($ch, CURLOPT_TIMEOUT, $options['timeout']); 
    607614 
    608615        $result = curl_exec ($ch); 
  • trunk/lib/AkPlugin/AkPluginManager.php

    r389 r392  
    7070    function getAvailableRepositories($force_reload = false) 
    7171    { 
     72        if(!empty($this->tmp_repositories)){ 
     73            return $this->tmp_repositories; 
     74        } 
     75 
    7276        if($force_reload || empty($this->repositories)){ 
    7377            $this->repositories = array($this->main_repository); 
     
    97101    function addRepository($repository_path) 
    98102    { 
    99         Ak::file_add_contents($this->_getRepositoriesConfigPath(), $repository_path."\n"); 
     103        if(!in_array(trim($repository_path), $this->getAvailableRepositories(true))){ 
     104            Ak::file_add_contents($this->_getRepositoriesConfigPath(), $repository_path."\n"); 
     105        } 
    100106    } 
    101107 
     
    135141    function getPlugins($force_update = false) 
    136142    { 
    137         if(!$force_update || !is_file($this->_getRepositoriesCahePath()) || filemtime($this->_getRepositoriesCahePath()) > 3600){ 
     143        if($force_update || !is_file($this->_getRepositoriesCahePath()) || filemtime($this->_getRepositoriesCahePath()) > 3600){ 
    138144            if(!$this->_updateRemotePluginsList()){ 
    139145                return array(); 
     
    141147        } 
    142148 
    143         return Ak::convert('yaml', 'array', Ak::file_get_contents($this->_getRepositoriesCahePath())); 
     149        return array_map('trim', Ak::convert('yaml', 'array', Ak::file_get_contents($this->_getRepositoriesCahePath()))); 
    144150    } 
    145151 
     
    171177     * @param  string  $plugin_name Plugin name 
    172178     * @param  unknown $repository   An Apache mod_svn interface to subversion. If not provided it will use a trusted repository. 
     179     * @param  array $options   
     180     * - externals: Use svn:externals to grab the plugin. Enables plugin updates and plugin versioning. 
     181     * - checkout:  Use svn checkout to grab the plugin. Enables updating but does not add a svn:externals entry. 
     182     * - revision:  Checks out the given revision from subversion. Ignored if subversion is not used. 
     183     * - force:     Overwrite existing files. 
    173184     * @return mixed Returns false if the plugin can't be found. 
    174185     * @access public  
    175186     */ 
    176     function installPlugin($plugin_name, $repository = null) 
    177     { 
     187    function installPlugin($plugin_name, $repository = null, $options = array()) 
     188    { 
     189        $default_options = array( 
     190        'externals' => false, 
     191        'checkout' => false, 
     192        'force' => false, 
     193        'revision' => null, 
     194        ); 
     195 
     196        $options = array_merge($default_options, $options); 
     197 
    178198        $plugin_name = Ak::sanitize_include($plugin_name, 'high'); 
    179         $repository = $this->_getRepositoryForPlugin($plugin_name, $repository); 
    180         $this->_copyRemoteDir(rtrim($repository, '/').'/'.$plugin_name.'/', AK_PLUGINS_DIR); 
    181         $this->_runInstaller($plugin_name, 'install'); 
    182     } 
    183  
    184  
    185     /** 
    186      * Updates a plugin if there changes. 
    187      *  
    188      * This method is the same as install, but can you can avoid an updates if  
    189      * you keep a CHANGELOG file for your plugin it will only perform the update 
    190      * if the CHANGELOG has hanged from last version 
     199        $repository = $this->getRepositoryForPlugin($plugin_name, $repository); 
     200 
     201        if(!$options['force'] && is_dir(AK_PLUGINS_DIR.DS.$plugin_name)){ 
     202            trigger_error(Ak::t('Destination directory is not empty. Use force option to overwrite exiting files.'), E_USER_NOTICE); 
     203        }else{ 
     204            $method = '_installUsing'.ucfirst($this->guessBestInstallMethod($options)); 
     205            $this->$method($plugin_name, rtrim($repository, '/'), $options['revision'], $options['force']); 
     206            $this->_runInstaller($plugin_name, 'install'); 
     207        } 
     208    } 
     209 
     210 
     211    function guessBestInstallMethod($options = array()) 
     212    { 
     213        if($this->canUseSvn()){ 
     214            if($options['externals'] && $this->_shouldUseSvnExternals()){ 
     215                return 'externals'; 
     216            }elseif($options['checkout'] && $this->_shouldUseSvnCheckout()){ 
     217                return 'checkout'; 
     218            } 
     219            return 'export'; 
     220        }else{ 
     221            return 'http'; 
     222        } 
     223    } 
     224 
     225    function canUseSvn() 
     226    { 
     227        return strstr(`svn --version`, 'CollabNet'); 
     228    } 
     229 
     230 
     231    /** 
     232     * Updates a plugin if there are changes. 
     233     *  
     234     * Uses subversion update if available. If http update is used, it will  
     235     * download the whole plugin unless there is a CHANGELOG file, in which case 
     236     * it will only perform the update if there are changes. 
    191237     *  
    192238     * @param  string  $plugin_name Plugin name 
    193239     * @param  string $repository   An Apache mod_svn interface to subversion. If not provided it will use a trusted repository. 
    194      * @return mixed Returns false if the plugin can't be found, true if is already updated and null when there is an update 
     240     * @return null 
    195241     * @access public  
    196242     */ 
    197243    function updatePlugin($plugin_name, $repository = null) 
    198244    { 
     245        $options = array( 
     246        'externals' => true, 
     247        'checkout' => true 
     248        ); 
     249 
    199250        $plugin_name = Ak::sanitize_include($plugin_name, 'high'); 
    200         $repository = $this->_getRepositoryForPlugin($plugin_name, $repository); 
    201  
    202         if(is_file(AK_PLUGINS_DIR.DS.$plugin_name.DS.'CHANGELOG') && 
    203         md5(Ak::url_get_contents(rtrim($repository, '/').'/'.$plugin_name.'/CHANGELOG')) == md5_file(AK_PLUGINS_DIR.DS.$plugin_name.DS.'CHANGELOG')){ 
    204             return false; 
    205         } 
    206  
    207         return $this->installPlugin($plugin_name, $repository); 
     251 
     252        $method = '_updateUsing'.ucfirst($this->guessBestInstallMethod($options)); 
     253        $this->$method($plugin_name, rtrim($this->getRepositoryForPlugin($plugin_name, $repository), '/')); 
     254 
     255        $this->_runInstaller($plugin_name, 'install'); 
    208256    } 
    209257 
     
    225273        $this->_runInstaller($plugin_name, 'uninstall'); 
    226274        Ak::directory_delete(AK_PLUGINS_DIR.DS.$plugin_name); 
     275 
     276        if($this->_shouldUseSvnExternals()){ 
     277            $this->_uninstallExternals($plugin_name); 
     278        } 
    227279    } 
    228280 
     
    246298     * @param  string  $repository  If a repository name is provided it will check for the plugin name existance. 
    247299     * @return mixed Repository URL or false if plugin can't be found    
    248      * @access private 
    249      */ 
    250     function _getRepositoryForPlugin($plugin_name, $repository = null) 
     300     * @access public 
     301     */ 
     302    function getRepositoryForPlugin($plugin_name, $repository = null) 
    251303    { 
    252304        if(empty($repository)){ 
     
    282334        $plugin_dir = AK_PLUGINS_DIR.DS.$plugin_name; 
    283335        if(file_exists($plugin_dir.DS.'installer'.DS.$plugin_name.'_installer.php')){ 
     336            require_once(AK_LIB_DIR.DS.'AkInstaller.php'); 
    284337            require_once($plugin_dir.DS.'installer'.DS.$plugin_name.'_installer.php'); 
    285338            $class_name = AkInflector::camelize($plugin_name.'_installer'); 
    286339            if(class_exists($class_name)){ 
    287340                $Installer =& new $class_name(); 
     341                $Installer->db->debug = false; 
    288342                $Installer->warn_if_same_version = false; 
    289343                $Installer->$install_or_uninstall(); 
     
    437491    function _getRepositoriesConfigPath() 
    438492    { 
    439         return AK_CONFIG_DIR.DS.'plugin_repositories.txt'; 
     493        if(empty($this->tmp_repositories)){ 
     494            return AK_CONFIG_DIR.DS.'plugin_repositories.txt'; 
     495        }else{ 
     496            return AK_TMP_DIR.DS.'plugin_repositories.'.md5(serialize($this->tmp_repositories)); 
     497        } 
    440498    } 
    441499 
     
    452510        return AK_TMP_DIR.DS.'plugin_repositories.yaml'; 
    453511    } 
     512 
     513 
     514     
     515    function _shouldUseSvnExternals() 
     516    { 
     517        return is_dir(AK_PLUGINS_DIR.DS.'.svn'); 
     518    } 
     519 
     520    function _shouldUseSvnCheckout() 
     521    { 
     522        return is_dir(AK_PLUGINS_DIR.DS.'.svn'); 
     523    } 
     524 
     525    function _installUsingCheckout($name, $uri, $rev = null, $force = false) 
     526    { 
     527        $rev = empty($rev) ? '' : " -r $rev "; 
     528        $force = $force ? ' --force ' : ''; 
     529        $plugin_dir = AK_PLUGINS_DIR.DS.$name; 
     530        `svn co $force $rev $uri/$name $plugin_dir`; 
     531    } 
     532 
     533    function _updateUsingCheckout($name) 
     534    { 
     535        $plugin_dir = AK_PLUGINS_DIR.DS.$name; 
     536        `svn update $plugin_dir`; 
     537    } 
     538 
     539    function _installUsingExport($name, $uri, $rev = null, $force = false) 
     540    { 
     541        $rev = empty($rev) ? '' : " -r $rev "; 
     542        $force = $force ? ' --force ' : ''; 
     543        $plugin_dir = AK_PLUGINS_DIR.DS.$name; 
     544        `svn export $force $rev $uri/$name $plugin_dir`; 
     545    } 
     546     
     547    function _updateUsingExport($name, $uri) 
     548    { 
     549        $plugin_dir = AK_PLUGINS_DIR.DS.$name; 
     550        `svn export --force $uri/$name $plugin_dir`; 
     551    } 
     552 
     553    function _installUsingExternals($name, $uri, $rev = null, $force = false) 
     554    { 
     555        $extras = empty($rev) ? '' : " -r $rev "; 
     556        $extras .= ($force ? ' --force ' : ''); 
     557        $externals = $this->_getExternals(); 
     558        $externals[$name] = $uri; 
     559        $this->_setExternals($externals, $extras); 
     560        $this->_installUsingCheckout($name, $uri, $rev, $force); 
     561    } 
     562     
     563    function _updateUsingExternals($name) 
     564    { 
     565        $this->_updateUsingCheckout($name); 
     566    } 
     567     
     568    function _updateUsingHttp($name, $uri) 
     569    { 
     570        if(is_file(AK_PLUGINS_DIR.DS.$name.DS.'CHANGELOG') && 
     571        md5(Ak::url_get_contents(rtrim($uri, '/').'/'.$name.'/CHANGELOG')) == md5_file(AK_PLUGINS_DIR.DS.$name.DS.'CHANGELOG')){ 
     572            return false; 
     573        } 
     574        $this->_copyRemoteDir(rtrim($uri, '/').'/'.$name.'/', AK_PLUGINS_DIR); 
     575    } 
     576     
     577     
     578    function _setExternals($items, $extras = '') 
     579    { 
     580        $externals = array(); 
     581        foreach ($items as $name => $uri){ 
     582            $externals[] = "$name ".rtrim($uri, '/'); 
     583        } 
     584        $tmp_file = AK_TMP_DIR.DS.Ak::uuid(); 
     585        $plugins_dir = AK_PLUGINS_DIR; 
     586        Ak::file_put_contents($tmp_file, join("\n", $externals)); 
     587        `svn propset $extras -q svn:externals -F "$tmp_file" "$plugins_dir"`; 
     588        Ak::file_delete($tmp_file); 
     589    } 
     590 
     591    function _uninstallExternals($name) 
     592    { 
     593        $externals = $this->_getExternals(); 
     594        unset($externals[$name]); 
     595        $this->_setExternals($externals); 
     596    } 
     597 
     598    function _getExternals() 
     599    { 
     600        if($this->_shouldUseSvnExternals()){ 
     601            $plugins_dir = AK_PLUGINS_DIR; 
     602            $svn_externals = array_diff(array_map('trim',(array)explode("\n", `svn propget svn:externals "$plugins_dir"`)), array('')); 
     603            $externals = array(); 
     604            foreach ($svn_externals as $svn_external){ 
     605                list($name, $uri) = explode(' ', trim($svn_external)); 
     606                $externals[$name] = $uri; 
     607            } 
     608            return $externals; 
     609        }else{ 
     610            return array(); 
     611        } 
     612    } 
     613 
     614    function _installUsingHttp($name, $uri) 
     615    { 
     616        $this->_copyRemoteDir(rtrim($uri, '/').'/'.$name.'/', AK_PLUGINS_DIR); 
     617    } 
     618     
    454619} 
    455620 
  • trunk/script/console

    r341 r392  
    1111 
    1212/** 
    13  * @package AkelosFramework 
    14  * @subpackage Generator
     13 * @package ActiveSupport 
     14 * @subpackage Script
    1515 * @author Bermi Ferrer <bermi a.t akelos c.om> 
    1616 * @copyright Copyright (c) 2002-2006, Akelos Media, S.L. http://www.akelos.org 
  • trunk/script/migrate

    r341 r392  
    1111 
    1212/** 
    13  * @package AkelosFramework 
    14  * @subpackage Installer 
     13 * @package ActiveSupport 
     14 * @subpackage Scripts 
    1515 * @author Bermi Ferrer <bermi a.t akelos c.om> 
    1616 * @copyright Copyright (c) 2002-2006, Akelos Media, S.L. http://www.akelos.org 
  • trunk/script/test

    r328 r392  
    1111 
    1212/** 
    13  * @package AkelosFramework 
    14  * @subpackage Testing 
     13 * @package ActiveSupport 
     14 * @subpackage Scripts 
    1515 * @author Bermi Ferrer <bermi a.t akelos c.om> 
    1616 * @copyright Copyright (c) 2002-2006, Akelos Media, S.L. http://www.akelos.org 
  • trunk/test/unit/lib/utils/_Ak_file_functions.php

    r371 r392  
    126126        } 
    127127    } 
     128     
     129    function test_should_delete_nested_directories_when_include_hidden_files() 
     130    { 
     131        $dir_name = AK_TMP_DIR.Ak::randomString(); 
     132        Ak::make_dir($dir_name); 
     133        Ak::make_dir($dir_name.DS.'.hidden'); 
     134        $this->assertTrue(is_dir($dir_name), 'Could not create test directory '.$dir_name); 
     135        $this->assertTrue(Ak::directory_delete($dir_name)); 
     136        clearstatcache(); 
     137        $this->assertFalse(is_dir($dir_name)); 
     138    } 
    128139} 
    129140