diff --git a/js/functions.js b/js/functions.js index 088cc457d8..4d63780301 100644 --- a/js/functions.js +++ b/js/functions.js @@ -149,6 +149,21 @@ function PMA_current_version() $('#li_pma_version').append(version_information_message); } +/** + * Loads Git revision data from ajax for main.php + */ +function PMA_display_git_revision() +{ + $.get("main.php?token=" + + $("input[type=hidden][name=token]").val() + + "&git_revision=1&ajax_request=true", function (data) { + if (data.error != "undefined" && data.error) { + return; + } + $(data.message).insertAfter('#li_pma_version'); + }); +} + /** * for libraries/display_change_password.lib.php * libraries/user_password.php @@ -3080,6 +3095,10 @@ $(document).ready(function() { $.getScript('http://www.phpmyadmin.net/home_page/version.js', PMA_current_version); } + if (typeof is_git_revision != "undefined") { + setTimeout(PMA_display_git_revision, 10); + } + /** * Slider effect. */ diff --git a/libraries/Config.class.php b/libraries/Config.class.php index f3f1632e16..6afc1c7909 100644 --- a/libraries/Config.class.php +++ b/libraries/Config.class.php @@ -349,6 +349,189 @@ class PMA_Config $this->set('PMA_PHP_STR_VERSION', phpversion()); } + /** + * detects if Git revision + * + * @return boolean + */ + function isGitRevision() + { + // caching + if (isset($_SESSION['is_git_revision'])) { + if ($_SESSION['is_git_revision']) { + $this->set('PMA_VERSION_GIT', 1); + } + return $_SESSION['is_git_revision']; + } + // find out if there is a .git folder + $git_folder = '.git'; + if (! @file_exists($git_folder) + || ! @file_exists($git_folder . '/config')) { + $_SESSION['is_git_revision'] = false; + return false; + } + $_SESSION['is_git_revision'] = true; + return true; + } + + /** + * detects Git revision, if running inside repo + * + * @return void + */ + function checkGitRevision() + { + // find out if there is a .git folder + $git_folder = '.git'; + if (! @file_exists($git_folder) + || ! @file_exists($git_folder . '/config')) { + return; + } + + if (! $ref_head = @file_get_contents($git_folder . '/HEAD')) { + return; + } + $branch = false; + // are we on any branch? + if (strstr($ref_head, '/')) { + $ref_head = substr(trim($ref_head), 5); + $branch = basename($ref_head); + + if (! $hash = @file_get_contents($git_folder . '/' . $ref_head)) { + return; + } + $hash = trim($hash); + } else { + $hash = trim($ref_head); + } + + if ( !isset($_SESSION['PMA_VERSION_COMMITDATA_' . $hash])) { + if (! $commit = @file_get_contents( + $git_folder . '/objects/' . substr($hash, 0, 2) + . '/' . substr($hash, 2))) { + return; + } + $commit = explode("\0", gzuncompress($commit), 2); + $commit = explode("\n", $commit[1]); + $_SESSION['PMA_VERSION_COMMITDATA_' . $hash] = $commit; + } else { + $commit = $_SESSION['PMA_VERSION_COMMITDATA_' . $hash]; + } + + $author = array('name' => '', 'email' => '', 'date' => ''); + $committer = array('name' => '', 'email' => '', 'date' => ''); + + do { + $dataline = array_shift($commit); + $datalinearr = explode(' ', $dataline, 2); + $linetype = $datalinearr[0]; + if (in_array($linetype, array('author', 'committer'))) + { + $user = $datalinearr[1]; + preg_match('/([^<]+)<([^>]+)> ([0-9]+)( [^ ]+)?/', $user, $user); + $user2 = array( + 'name' => trim($user[1]), + 'email' => trim($user[2]), + 'date' => date('Y-m-d H:i:s', $user[3])); + if (isset($user[4])) + { + $user2['date'] .= $user[4]; + } + $$linetype = $user2; + } + } + while ($dataline != ''); + $message = trim(implode(' ', $commit)); + + // check if commit exists in Github + $is_remote_commit = false; + if (isset($_SESSION['PMA_VERSION_REMOTECOMMIT_' . $hash])) { + $is_remote_commit = $_SESSION['PMA_VERSION_REMOTECOMMIT_' . $hash]; + } else { + $link = 'https://api.github.com/repos/phpmyadmin/phpmyadmin/git/commits/' . $hash; + $is_found = $this->checkHTTP($link); + switch($is_found) { + case true: + $is_remote_commit = true; + $_SESSION['PMA_VERSION_REMOTECOMMIT_' . $hash] = true; + break; + case false: + $is_remote_commit = false; + $_SESSION['PMA_VERSION_REMOTECOMMIT_' . $hash] = false; + break; + case null: + // no remote link for now, but don't cache this as Github is down + $is_remote_commit = false; + break; + } + } + + $is_remote_branch = false; + if ($is_remote_commit && $branch !== false) { + // check if branch exists in Github + if (isset($_SESSION['PMA_VERSION_REMOTEBRANCH_' . $hash])) { + $is_remote_branch = $_SESSION['PMA_VERSION_REMOTEBRANCH_' . $hash]; + } else { + $link = 'https://api.github.com/repos/phpmyadmin/phpmyadmin/git/trees/' . $branch; + $is_found = $this->checkHTTP($link); + switch($is_found) { + case true: + $is_remote_branch = true; + $_SESSION['PMA_VERSION_REMOTEBRANCH_' . $hash] = true; + break; + case false: + $is_remote_branch = false; + $_SESSION['PMA_VERSION_REMOTEBRANCH_' . $hash] = false; + break; + case null: + // no remote link for now, but don't cache this as Github is down + $is_remote_branch = false; + break; + } + } + } + + $this->set('PMA_VERSION_GIT', 1); + $this->set('PMA_VERSION_GIT_COMMITHASH', $hash); + $this->set('PMA_VERSION_GIT_BRANCH', $branch); + $this->set('PMA_VERSION_GIT_MESSAGE', $message); + $this->set('PMA_VERSION_GIT_AUTHOR', $author); + $this->set('PMA_VERSION_GIT_COMMITTER', $committer); + $this->set('PMA_VERSION_GIT_ISREMOTECOMMIT', $is_remote_commit); + $this->set('PMA_VERSION_GIT_ISREMOTEBRANCH', $is_remote_branch); + } + + /** + * Checks if given URL is 200 or 404 + */ + function checkHTTP($link) + { + if (! function_exists('curl_init')) { + return null; + } + $ch = curl_init($link); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0); + curl_setopt($ch, CURLOPT_NOBODY, 1); + curl_setopt($ch, CURLOPT_HEADER, 1); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); + curl_setopt($ch, CURLOPT_TIMEOUT, 5); + $data = @curl_exec($ch); + if ($data === false) { + return null; + } + $ok = 'HTTP/1.1 200 OK'; + $notfound = 'HTTP/1.1 404 Not Found'; + if (substr($data, 0, strlen($ok)) === $ok) { + return true; + } elseif (substr($data, 0, strlen($notfound)) === $notfound) { + return false; + } + return null; + } + /** * loads default values from default source * diff --git a/libraries/display_git_revision.lib.php b/libraries/display_git_revision.lib.php new file mode 100644 index 0000000000..b31ce8a361 --- /dev/null +++ b/libraries/display_git_revision.lib.php @@ -0,0 +1,71 @@ +get('PMA_VERSION_GIT')) { + PMA_ajaxResponse('', false); + } + + // load revision data from repo + $GLOBALS['PMA_Config']->checkGitRevision(); + + // if using a remote commit fast-forwarded, link to Github + $commit_hash = substr($GLOBALS['PMA_Config']->get('PMA_VERSION_GIT_COMMITHASH'), 0, 7); + $commit_hash = '' + . $commit_hash . ''; + if ($GLOBALS['PMA_Config']->get('PMA_VERSION_GIT_ISREMOTECOMMIT')) { + $commit_hash = + '' . $commit_hash . ''; + } + + $branch = $GLOBALS['PMA_Config']->get('PMA_VERSION_GIT_BRANCH'); + if ($GLOBALS['PMA_Config']->get('PMA_VERSION_GIT_ISREMOTEBRANCH')) { + $branch = + '' . $branch . ''; + } + if ($branch !== false) { + $branch = sprintf(__('%s from %s branch'), $commit_hash, $branch); + } else { + $branch = $commit_hash . ' (' . __('no branch') . ')'; + } + + ob_start(); + PMA_printListItem(__('Git revision') . ': ' + . $branch . ',
' + . sprintf( + __('committed on %s by %s'), + PMA_localisedDate(strtotime($GLOBALS['PMA_Config']->get('PMA_VERSION_GIT_COMMITTER')['date'])), + '' + . htmlspecialchars($GLOBALS['PMA_Config']->get('PMA_VERSION_GIT_COMMITTER')['name']) . '') + . ($GLOBALS['PMA_Config']->get('PMA_VERSION_GIT_AUTHOR') != $GLOBALS['PMA_Config']->get('PMA_VERSION_GIT_COMMITTER') + ? ',
' + . sprintf( + __('authored on %s by %s'), + PMA_localisedDate(strtotime($GLOBALS['PMA_Config']->get('PMA_VERSION_GIT_AUTHOR')['date'])), + '' + . htmlspecialchars($GLOBALS['PMA_Config']->get('PMA_VERSION_GIT_AUTHOR')['name']) . '') + : ''), + 'li_pma_version_git', null, null, null); + $item = ob_get_contents(); + ob_end_clean(); + PMA_ajaxResponse($item, true); +} diff --git a/main.php b/main.php index f4babfe139..680829568c 100644 --- a/main.php +++ b/main.php @@ -10,6 +10,18 @@ */ require_once 'libraries/common.inc.php'; +/** + * display Git revision if requested + */ +require_once 'libraries/display_git_revision.lib.php'; + +if ($GLOBALS['PMA_Config']->isGitRevision()) { + if (isset($_REQUEST['git_revision']) && $GLOBALS['is_ajax_request'] == true) { + PMA_printGitRevision(); + } + PMA_AddJSVar('is_git_revision', true); +} + // Handles some variables that may have been sent by the calling script $GLOBALS['db'] = ''; $GLOBALS['table'] = '';