From 0f913413c91805dfd02b24022517e39b0673072e Mon Sep 17 00:00:00 2001 From: Andreas Hennings Date: Thu, 28 Jul 2016 22:53:20 +0200 Subject: Docblock types --- git_deploy.module | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/git_deploy.module b/git_deploy.module index e35ff7c..1a6bfa4 100644 --- a/git_deploy.module +++ b/git_deploy.module @@ -11,11 +11,11 @@ * * We support populating $info['version'] and $info['project']. * - * @param $info + * @param array $info * The module/theme info array we're altering. - * @param $file + * @param object $file * An object describing the filesystem location of the module/theme. - * @param $type + * @param string $type * Can be module or theme. */ function git_deploy_system_info_alter(&$info, $file, $type = NULL) { -- 1.9.1 From 1bc0a5f4a16753f21b7cba5ef8c514e73b0c3c24 Mon Sep 17 00:00:00 2001 From: Andreas Hennings Date: Thu, 28 Jul 2016 22:55:39 +0200 Subject: Refactor and split git_deploy_system_info_alter(). --- git_deploy.module | 212 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 151 insertions(+), 61 deletions(-) diff --git a/git_deploy.module b/git_deploy.module index 1a6bfa4..b02937a 100644 --- a/git_deploy.module +++ b/git_deploy.module @@ -19,69 +19,159 @@ * Can be module or theme. */ function git_deploy_system_info_alter(&$info, $file, $type = NULL) { - if (empty($info['version'])) { - $directory = dirname($file->uri); - // Check whether this belongs to core. Speed optimization. - if (substr($directory, 0, strlen($type)) != $type) { - while ($directory && !file_exists("$directory/.git")) { - $directory = substr($directory, 0, strrpos($directory, '/')); - } - $git_dir = "$directory/.git"; - // Theoretically /.git could exist. - if ($directory && file_exists($git_dir)) { - $git = "git --git-dir $git_dir"; - // Find first the project name based on fetch URL. - // Eat error messages. >& is valid on Windows, too. Also, $output does - // not need initialization because it's taken by reference. - exec("$git remote show -n origin 2>&1", $output); - if ($fetch_url = preg_grep('/^\s*Fetch URL:/', $output)) { - $fetch_url = current($fetch_url); - $project_name = substr($fetch_url, strrpos($fetch_url, '/') + 1); - if (substr($project_name, -4) == '.git') { - $project_name = substr($project_name, 0, -4); - } - $info['project'] = $project_name; - } - // Try to fill in branch and tag. - exec("$git rev-parse --abbrev-ref HEAD 2>&1", $branch); - $tag_found = FALSE; - if ($branch) { - $branch = $branch[0]; - // Any Drupal-formatted branch. - $branch_preg = '\d+\.x-\d+\.'; - if (preg_match('/^' . $branch_preg . 'x$/', $branch)) { - $info['version'] = $branch . '-dev'; - // Nail down the core and the major version now that we know - // what they are. - $branch_preg = preg_quote(substr($branch, 0, -1)); - } - // Now try to find a tag. - exec("$git rev-list --topo-order --max-count=1 HEAD 2>&1", $last_tag_hash); - if ($last_tag_hash) { - exec("$git describe --tags $last_tag_hash[0] 2>&1", $last_tag); - if ($last_tag) { - $last_tag = $last_tag[0]; - // Make sure the tag starts as Drupal formatted (for eg. - // 7.x-1.0-alpha1) and if we are on a proper branch (ie. not - // master) then it's on that branch. - if (preg_match('/^(' . $branch_preg . '\d+(?:-[^-]+)?)(-(\d+-)g[0-9a-f]{7})?$/', $last_tag, $matches)) { - $tag_found = TRUE; - $info['version'] = isset($matches[2]) ? $matches[1] . '.' . $matches[3] . 'dev' : $last_tag; - } - } - } - } - if (!$tag_found) { - $last_tag = ''; - } - // The git log -1 command always succeeds and if we are not on a - // tag this will happen to return the time of the last commit which - // is exactly what we wanted. - exec("$git log -1 --pretty=format:%at $last_tag 2>&1", $datestamp); - if ($datestamp && is_numeric($datestamp[0])) { - $info['datestamp'] = $datestamp[0]; + if (!empty($info['version'])) { + return; + } + + // Check whether this belongs to core. Speed optimization. + if (0 === strpos($file->uri, $type)) { + return; + } + + $directory = dirname($file->uri); + + while (TRUE) { + if (!$directory || '.' === $directory) { + return; + } + if (file_exists("$directory/.git")) { + break; + } + $directory = dirname($directory); + } + + $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' + * + * @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); +} + +/** + * @param string $git_dir + * E.g. 'sites/all/modules/git/views/.git' + * + * @return array + */ +function _git_deploy_read_info_from_git_dir($git_dir) { + + $info = array(); + + // Find first the project name based on fetch URL. + // Eat error messages. >& is valid on Windows, too. Also, $output does + // not need initialization because it's taken by reference. + if (NULL !== $fetch_url = _git_deploy_exec_grep($git_dir, 'remote show -n origin', '/^\s*Fetch URL:/')) { + $project_name = substr($fetch_url, strrpos($fetch_url, '/') + 1); + if (substr($project_name, -4) === '.git') { + $project_name = substr($project_name, 0, -4); + } + $info['project'] = $project_name; + } + + // Try to fill in branch and tag. + $last_tag = ''; + if (NULL !== $branch = _git_deploy_exec_get_line($git_dir, 'rev-parse --abbrev-ref HEAD')) { + + // Any Drupal-formatted branch. + $branch_preg = '\d+\.x-\d+\.'; + if (preg_match('/^' . $branch_preg . 'x$/', $branch)) { + $info['version'] = $branch . '-dev'; + // Nail down the core and the major version now that we know + // what they are. + $branch_preg = preg_quote(substr($branch, 0, -1)); + } + + // Now try to find a tag. + if (NULL !== $last_tag_hash = _git_deploy_exec_get_line($git_dir, 'rev-list --topo-order --max-count=1 HEAD')) { + if (NULL !== $last_tag_candidate = _git_deploy_exec_get_line($git_dir, "describe --tags $last_tag_hash")) { + // Make sure the tag starts as Drupal formatted (for eg. + // 7.x-1.0-alpha1) and if we are on a proper branch (ie. not + // master) then it's on that branch. + if (preg_match('/^(' . $branch_preg . '\d+(?:-[^-]+)?)(-(\d+-)g[0-9a-f]{7})?$/', $last_tag_candidate, $matches)) { + $info['version'] = isset($matches[2]) + ? $matches[1] . '.' . $matches[3] . 'dev' + : $last_tag; } } } } + + // The git log -1 command always succeeds and if we are not on a + // tag this will happen to return the time of the last commit which + // is exactly what we wanted. + if (NULL !== $datestamp = _git_deploy_exec_get_line($git_dir, "log -1 --pretty=format:%at $last_tag")) { + if (is_numeric($datestamp)) { + $info['datestamp'] = $datestamp; + } + } + + return $info; +} + +/** + * Executes a git command, and returns the first line of the output. + * + * @param string $git_dir + * E.g. 'status' for 'git status'. + * @param string $cmd + * The git directory for + * + * @return string|null + * The line of the output, or NULL if output was empty. + */ +function _git_deploy_exec_get_line($git_dir, $cmd) { + $output_lines = _git_deploy_exec_get_all($git_dir, $cmd); + return isset($output_lines[0]) ? $output_lines[0] : NULL; +} + +/** + * Executes a git command, and returns the (first) line of the output that + * matches the regex pattern. + * + * @param string $git_dir + * @param string $cmd + * E.g. 'status' for 'git status'. + * @param string $preg_grep_regex + * + * @return string|null + * Line of the output that matches the pattern, or NULL if no match. + */ +function _git_deploy_exec_grep($git_dir, $cmd, $preg_grep_regex) { + + $output_lines = _git_deploy_exec_get_all($git_dir, $cmd); + + if (array() !== $output_lines) { + if (array() !== $matches = preg_grep('/^\s*Fetch URL:/', $output_lines)) { + return current($matches); + } + } + + return NULL; +} + +/** + * Executes a git command, and returns all lines of the output. + * + * @param string $git_dir + * @param string $cmd + * E.g. 'status' for 'git status'. + * + * @return string[] + * Lines of the output, as provided by exec(). + */ +function _git_deploy_exec_get_all($git_dir, $cmd) { + exec("git --git-dir $git_dir $cmd 2>&1", $output_lines); + return $output_lines; } -- 1.9.1 From 425a91847f86aa4f6aa8bea8ea01c8257f21ec53 Mon Sep 17 00:00:00 2001 From: Andreas Hennings Date: Thu, 28 Jul 2016 22:57:12 +0200 Subject: Use escapeshellarg() --- git_deploy.module | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/git_deploy.module b/git_deploy.module index b02937a..f598ffb 100644 --- a/git_deploy.module +++ b/git_deploy.module @@ -172,6 +172,7 @@ function _git_deploy_exec_grep($git_dir, $cmd, $preg_grep_regex) { * Lines of the output, as provided by exec(). */ function _git_deploy_exec_get_all($git_dir, $cmd) { - exec("git --git-dir $git_dir $cmd 2>&1", $output_lines); + $git_dir_safe = escapeshellarg($git_dir); + exec("git --git-dir $git_dir_safe $cmd 2>&1", $output_lines); return $output_lines; } -- 1.9.1