From 07f49931b376b1d9f5be037f5984a06e8485c942 Mon Sep 17 00:00:00 2001 From: Andreas Hennings Date: Fri, 29 Jul 2016 00:24:17 +0200 Subject: Change doc comment on git_deploy_system_info_alter() --- git_deploy.module | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/git_deploy.module b/git_deploy.module index f598ffb..7c6e83b 100644 --- a/git_deploy.module +++ b/git_deploy.module @@ -7,9 +7,10 @@ */ /** - * Implement hook_system_info_alter() to provide metadata to drupal from git. + * Implements hook_system_info_alter(). * - * We support populating $info['version'] and $info['project']. + * Provide metadata to drupal from git. We support populating $info['version'], + * $info['project'] and $info['datestamp']. * * @param array $info * The module/theme info array we're altering. -- 1.9.1 From fc293beeb89e60f34b206051e42bd5e5f10b155a Mon Sep 17 00:00:00 2001 From: Andreas Hennings Date: Fri, 29 Jul 2016 00:27:15 +0200 Subject: Introduce _git_deploy_get_info_from_directory() to replace _git_deploy_get_info_from_git_dir(). Static cache per directory instead of per git dir. --- git_deploy.module | 38 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/git_deploy.module b/git_deploy.module index 7c6e83b..0a4023d 100644 --- a/git_deploy.module +++ b/git_deploy.module @@ -29,35 +29,29 @@ function git_deploy_system_info_alter(&$info, $file, $type = NULL) { return; } - $directory = dirname($file->uri); - - while (TRUE) { - if (!$directory || '.' === $directory) { - return; - } - if (file_exists("$directory/.git")) { - break; - } - $directory = dirname($directory); + if (array() !== $extracted_info = _git_deploy_get_info_from_directory(dirname($file->uri))) { + $info = $extracted_info + $info; } - - $info = _git_deploy_get_info_from_git_dir("$directory/.git") + $info; } /** - * Extracts enhancements to a module info array from a module's git repository. - * - * @param string $git_dir - * E.g. 'sites/all/modules/git/views/.git' + * @param string $directory + * E.g. 'sites/all/modules/contrib/views' * * @return array - * E.g. ['project' => 'views', 'version' => '3.x-dev', 'datestamp' => ..] */ -function _git_deploy_get_info_from_git_dir($git_dir) { - static $cache = array(); - return isset($cache[$git_dir]) - ? $cache[$git_dir] - : $cache[$git_dir] = _git_deploy_read_info_from_git_dir($git_dir); +function _git_deploy_get_info_from_directory($directory) { + static $static = array('.' => array(), '' => array()); + + if (isset($static[$directory])) { + return $static[$directory]; + } + + if (file_exists("$directory/.git/HEAD")) { + return $static[$directory] = _git_deploy_read_info_from_git_dir("$directory/.git"); + } + + return $static[$directory] = _git_deploy_get_info_from_directory(dirname($directory)); } /** -- 1.9.1 From 43b04751e2317035a11fd4319b622d1c125a4c64 Mon Sep 17 00:00:00 2001 From: Andreas Hennings Date: Fri, 29 Jul 2016 00:34:20 +0200 Subject: Introduce persistent cache, as in #1511112-48 --- README.txt | 10 +++ git_deploy.inc | 1 + git_deploy.install | 74 ++++++++++++++++++++- git_deploy.module | 187 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 268 insertions(+), 4 deletions(-) create mode 100644 git_deploy.inc diff --git a/README.txt b/README.txt index 98d181e..c4ca752 100644 --- a/README.txt +++ b/README.txt @@ -6,3 +6,13 @@ An alternative to using git_deploy is to install modules and themes using the --gitinfofile". This performs a git clone and checkout and then inserts the desired version information into the .info file. The "drush make" command will automatically write packaging information without additional options. + +If you use this module for several sites on the same machine, you can make use +of the shared file cache by adding this or something like this to your settings +file: + +$conf['git_deploy_file_cache_directory'] = '/tmp/git_deploy'; + +The git status is also saved in a (site-specific) cache bin called +cache_git_deploy, in case you want to use an alternative backend for your +particular instance. diff --git a/git_deploy.inc b/git_deploy.inc new file mode 100644 index 0000000..b3d9bbc --- /dev/null +++ b/git_deploy.inc @@ -0,0 +1 @@ + t('git binary'), - 'value' => t('The git binary is present and executable'), + $requirements['git_deploy_git_binary'] = array( + 'title' => $t('Git binary'), + 'value' => $t('The Git binary is present and executable'), 'severity' => function_exists('exec') && exec('git') ? REQUIREMENT_OK : REQUIREMENT_ERROR, ); + + if ($directory = variable_get('git_deploy_file_cache_directory')) { + $requirements['git_deploy_file_cache_directory'] = array( + 'title' => $t('Git deploy - Shared cache directory'), + 'value' => $t('The shared Git deploy temporary directory is exists and writable.'), + 'severity' => is_dir($directory) && is_writable($directory) ? REQUIREMENT_OK : REQUIREMENT_ERROR, + ); + } } + return $requirements; } + +/** + * Implements hook_enable(). + */ +function git_deploy_enable() { + $weight = db_select('system', 's') + ->fields('s', array('weight')) + ->condition('s.type', 'module') + ->condition('s.name', 'git_deploy', '<>') + ->orderBy('s.weight') + ->orderBy('s.name') + ->range(0, 1) + ->execute() + ->fetchColumn(); + + db_update('system') + ->fields(array('weight' => $weight - 1)) + ->condition('type', 'module') + ->condition('name', 'git_deploy') + ->execute(); +} + +/** + * Implements hook_uninstall(). + */ +function git_deploy_uninstall() { + variable_del('git_deploy_file_cache_directory'); +} + +/** + * Implements hook_schema(). + */ +function git_deploy_schema() { + $table = drupal_get_schema_unprocessed('system', 'cache'); + $table['description'] = 'Cache table for git deploy to store exec command results.'; + $schema = array('cache_git_deploy' => $table); + + return $schema; +} + +/** + * Add a separate cache table. + */ +function git_deploy_update_7001() { + if (!db_table_exists('cache_git_deploy')) { + $table = drupal_get_schema_unprocessed('system', 'cache'); + $table['description'] = 'Cache table for git deploy to store exec command results.'; + db_create_table('cache_git_deploy', $table); + } +} diff --git a/git_deploy.module b/git_deploy.module index 0a4023d..58cd46a 100644 --- a/git_deploy.module +++ b/git_deploy.module @@ -48,13 +48,38 @@ function _git_deploy_get_info_from_directory($directory) { } if (file_exists("$directory/.git/HEAD")) { - return $static[$directory] = _git_deploy_read_info_from_git_dir("$directory/.git"); + return $static[$directory] = _git_deploy_get_info_from_git_dir("$directory/.git"); } return $static[$directory] = _git_deploy_get_info_from_directory(dirname($directory)); } /** + * Extracts enhancements to a module info array from a module's git repository. + * + * @param string $git_dir + * E.g. 'sites/all/modules/git/views/.git' + * + * @return array + * E.g. ['project' => 'views', 'version' => '3.x-dev', 'datestamp' => ..] + */ +function _git_deploy_get_info_from_git_dir($git_dir) { + + $head_hash = trim(file_get_contents($git_dir . '/HEAD')); + $cache_id = "git_deploy:$git_dir:$head_hash"; + + if ($cache = _git_deploy_cache_get($cache_id)) { + return $cache->data; + } + + $info = _git_deploy_read_info_from_git_dir($git_dir); + + _git_deploy_cache_set($cache_id, $info); + + return $info; +} + +/** * @param string $git_dir * E.g. 'sites/all/modules/git/views/.git' * @@ -171,3 +196,163 @@ function _git_deploy_exec_get_all($git_dir, $cmd) { exec("git --git-dir $git_dir_safe $cmd 2>&1", $output_lines); return $output_lines; } + +/** + * Returns cache object from the cache_git_deploy cache bin. + * + * If the cache data is not exists in the local cache bin, then attempt to read + * from the shared file cache. + * + * @param string $cache_id + * Cache identifier. + * + * @return object|false + * Cache object or FALSE. + */ +function _git_deploy_cache_get($cache_id) { + $cache_bin = 'cache_git_deploy'; + $cache_object = cache_get($cache_id, $cache_bin); + if (empty($cache_object)) { + $cache_data = _git_deploy_file_cache_read($cache_id); + if ($cache_data) { + cache_set($cache_id, $cache_data, $cache_bin); + $cache_object = cache_get($cache_id, $cache_bin); + } + } + + return $cache_object; +} + +/** + * Save $info additions into cache_git_deploy cache bin and file cache. + * + * @param string $cache_id + * Cache identifier. + * @param array $cache_data + * Array of system info additions. + */ +function _git_deploy_cache_set($cache_id, $cache_data) { + cache_set($cache_id, $cache_data, 'cache_git_deploy'); + _git_deploy_file_cache_write($cache_id, $cache_data); +} + +/** + * Convert cache id to file name. + * + * @param string $cache_id + * Cache identifier. + * + * @return string + * File name. + */ +function _git_deploy_file_cache_name($cache_id) { + return str_replace(array(':', '/'), '-', $cache_id); +} + +/** + * Read cache data from the shared file based cache. + * + * WebServer writable files can not be trusted and sending untrusted data + * through unserialize() is dangerous. + * + * @see _git_deploy_file_cache_write() + * @see _git_deploy_file_cache_unserialize() + * + * @param string $cache_id + * Cache identifier. + * + * @return array|null + * Cache data. System info additions. + */ +function _git_deploy_file_cache_read($cache_id) { + if ($directory = variable_get('git_deploy_file_cache_directory', '')) { + $file_name = str_replace(array(':', '/'), '-', $cache_id); + if (is_readable("$directory/$file_name") && ($cache_data = @file_get_contents("$directory/$file_name"))) { + return _git_deploy_file_cache_unserialize($cache_data); + } + } + + return NULL; +} + +/** + * Write cache data into the shared file based cache. + * + * @see _git_deploy_file_cache_read() + * + * @param string $cache_id + * Cache identifier. + * @param array $cache_data + * System info additions. + * + * @return int|bool + * Returns the number of bytes that were written to the file, or FALSE on + * failure. + */ +function _git_deploy_file_cache_write($cache_id, $cache_data) { + if ($directory = variable_get('git_deploy_file_cache_directory', '')) { + $file_path = $directory . '/' . _git_deploy_file_cache_name($cache_id); + if (file_exists($file_path)) { + return TRUE; + } + + $is_directory = (is_dir($directory) || file_prepare_directory($directory, FILE_CREATE_DIRECTORY)); + $is_writable = (!file_exists($file_path) || is_writable($file_path)); + if ($is_directory && $is_writable) { + return @file_put_contents($file_path, _git_deploy_file_cache_serialize($cache_data)); + } + } + + return FALSE; +} + +/** + * Prepare cache data to write into a shared file. + * + * @see _git_deploy_file_cache_unserialize() + * + * @param array $cache_data + * System info additions. + * + * @return string + * Serialized cache data. + */ +function _git_deploy_file_cache_serialize($cache_data) { + $text = ''; + foreach ($cache_data as $key => $value) { + $text .= "$key=$value\n"; + } + + return $text; +} + +/** + * Parse the serialized cache data. + * + * @see _git_deploy_file_cache_serialize() + * + * @param string $text + * Serialized cache data. + * + * @return array + * System info additions. + */ +function _git_deploy_file_cache_unserialize($text) { + $cache_data = array(); + $keys = array('version', 'project', 'datetime'); + foreach (explode("\n", trim($text)) as $line) { + list($key, $value) = explode('=', $line); + if (in_array($key, $keys)) { + $cache_data[$key] = check_plain($value); + } + } + + return $cache_data; +} + +/** + * Implements hook_flush_caches(). + */ +function git_deploy_flush_caches() { + return array('cache_git_deploy'); +} -- 1.9.1