View source
<?php
define('GIT_DEPLOY_ERROR_DUMP', file_exists('/dev/null') ? '/dev/null' : 'nul');
function git_deploy_help($path, $arg) {
if ($path == 'admin/reports/updates' && !module_exists('mydropwizard')) {
return '<p><strong>' . t('Drupal 6 has reached its community End-of-Life (EOL) date and is now in a Long-Term Support (LTS) phase, where support is provided by a <a href="http://drupal.org/project/d6lts">small group of vendors</a>. To get accurate update status information, enable the <a href="https://www.drupal.org/project/mydropwizard">myDropWizard</a> module.') . '</strong></p>';
}
}
function &_git_deploy_static($name, $default_value = NULL, $reset = FALSE) {
static $data = array(), $default = array();
if (isset($name)) {
if (array_key_exists($name, $data)) {
if ($reset) {
$data[$name] = $default[$name];
}
}
else {
$data[$name] = $default[$name] = $default_value;
}
return $data[$name];
}
elseif ($reset) {
foreach ($default as $name => $value) {
$data[$name] = $default[$name];
}
}
return $data;
}
function _git_deploy_static_reset($name = NULL) {
_git_deploy_static($name, NULL, TRUE);
}
function git_deploy_system_info_alter(&$info, $file) {
$projects =& _git_deploy_static('projects', array());
$available =& _git_deploy_static('available');
$update =& _git_deploy_static('update', array());
$last_check =& _git_deploy_static('last_check');
$is_core = isset($info['package']) && strpos($info['package'], 'Core -') !== FALSE;
if (empty($info['version']) || ($is_core ? strstr($info['version'], '-dev') == '-dev' : $info['version'] == VERSION || !preg_match('/^6\\.x-\\d+\\..+/', $info['version']))) {
$home = getenv('HOME') === FALSE ? 'HOME=' . DRUPAL_ROOT . ' ' : '';
$directory = exec($home . 'git -C ' . escapeshellarg(dirname($file->filename)) . ' rev-parse --show-toplevel 2> ' . GIT_DEPLOY_ERROR_DUMP);
if (!empty($directory) && (!$is_core || $directory == DRUPAL_ROOT)) {
if (!isset($projects[$directory])) {
$projects[$directory] = array();
$git = $home . 'git -C ' . escapeshellarg($directory);
if (exec("{$git} ls-files " . escapeshellarg(str_replace("{$directory}/", '', realpath($file->filename))) . ' 2> ' . GIT_DEPLOY_ERROR_DUMP)) {
$upstream = _git_deploy_get_upstream($git, $is_core ? array(
'6',
) : array(
'6.x-*',
));
if ($is_core) {
$project_name = 'drupal';
}
elseif (isset($upstream['remote'])) {
$fetch_url = exec("{$git} config --get " . escapeshellarg("remote.{$upstream['remote']}.url") . ' 2> ' . GIT_DEPLOY_ERROR_DUMP);
if (!empty($fetch_url)) {
$project_name = basename($fetch_url, '.git');
$projects[$directory]['project'] = $project_name;
}
}
if (isset($upstream['datestamp'])) {
$projects[$directory]['datestamp'] = $upstream['datestamp'];
if (empty($info['_info_file_ctime'])) {
$projects[$directory]['_info_file_ctime'] = $upstream['datestamp'];
}
else {
$projects[$directory]['_info_file_ctime'] = max($info['_info_file_ctime'], $upstream['datestamp']);
}
}
if (isset($upstream['tag'])) {
$projects[$directory]['version'] = $upstream['tag'];
}
elseif (isset($upstream['branch'])) {
if ($upstream['branch'] != 'master') {
$projects[$directory]['version'] = "{$upstream['branch']}-dev";
}
if (module_exists('mydropwizard') && ($upstream['synced'] || $upstream['branch'] == 'master')) {
if (!isset($available)) {
if (($cache = _mydropwizard_cache_get('mydropwizard_available_releases')) && $cache->expire > time()) {
$available = $cache->data;
$last_check = variable_get('mydropwizard_last_check', 0);
}
}
if (!empty($available[$project_name]['releases'])) {
if ($upstream['branch'] == 'master') {
foreach ($available[$project_name]['releases'] as $release) {
if (isset($release['tag']) && $release['tag'] == 'HEAD') {
$projects[$directory]['version'] = $release['version'];
break;
}
}
}
if ($upstream['synced']) {
$version = $projects[$directory]['version'];
if (!isset($available[$project_name]['releases'][$version]) || $projects[$directory]['_info_file_ctime'] > $last_check) {
$update[] = $project_name;
}
else {
_git_deploy_datestamp_sync($projects[$directory], $available[$project_name]['releases'][$version]);
}
}
}
}
}
}
}
$info = $projects[$directory] + $info;
}
}
}
function _git_deploy_get_upstream($git, array $patterns = array(
'*',
)) {
$upstream = array(
'synced' => FALSE,
);
exec("{$git} remote 2> " . GIT_DEPLOY_ERROR_DUMP, $remotes);
if (!empty($remotes)) {
$tag = exec("{$git} describe --tags --abbrev=0 --match " . implode(' --match ', substr_replace($patterns, '.*', array_map('strlen', $patterns))) . ' 2> ' . GIT_DEPLOY_ERROR_DUMP);
$last_base = $head = exec("{$git} log -1 --pretty=format:%H 2> " . GIT_DEPLOY_ERROR_DUMP);
$remote = exec("{$git} rev-parse --abbrev-ref @{upstream} 2> " . GIT_DEPLOY_ERROR_DUMP);
if ($remote !== '' && preg_match('/^.+\\/(?:' . implode('|', str_replace(array(
'.',
'*',
), array(
'\\.',
'\\d+',
), $patterns)) . ')\\.x$/', $remote)) {
list($upstream['branch'], $upstream['remote']) = array_reverse(explode('/', $remote));
$last_base = exec("{$git} merge-base HEAD " . escapeshellarg($remote) . ' 2> ' . GIT_DEPLOY_ERROR_DUMP);
if (!empty($tag)) {
exec("{$git} describe --tags --contains " . escapeshellarg($last_base) . ' --match ' . escapeshellarg($tag) . ' 2> ' . GIT_DEPLOY_ERROR_DUMP, $output, $status);
}
if (empty($tag) || $status !== 0) {
$upstream['synced'] = $last_base == exec("{$git} log -1 --pretty=format:%H " . escapeshellarg($remote) . ' 2> ' . GIT_DEPLOY_ERROR_DUMP);
}
else {
$upstream['tag'] = $tag;
}
}
else {
if (in_array('origin', $remotes)) {
$upstream['remote'] = 'origin';
}
elseif ($remote !== '') {
list(, $upstream['remote']) = array_reverse(explode('/', $remote));
}
if (isset($upstream['remote'])) {
$branch_patterns = substr_replace($patterns, "{$upstream['remote']}/", 0, 0);
}
else {
$upstream['remote'] = current($remotes);
$branch_patterns = substr_replace($patterns, '*/', 0, 0);
}
if (!empty($tag)) {
exec("{$git} describe --tags --exact-match --match " . escapeshellarg($tag) . ' 2> ' . GIT_DEPLOY_ERROR_DUMP, $output, $status);
}
if (empty($tag) || $status !== 0) {
$branch_patterns = substr_replace($branch_patterns, '.x', array_map('strlen', $branch_patterns));
$branch_pattern = implode(' ', array_map('escapeshellarg', $branch_patterns));
exec("{$git} branch -r --list {$branch_pattern} master 2> " . GIT_DEPLOY_ERROR_DUMP, $branches);
if (!empty($branches)) {
usort($branches, 'version_compare');
foreach (array_reverse(array_map('trim', $branches)) as $branch) {
$tip = exec("{$git} log -1 --pretty=format:%H " . escapeshellarg($branch) . ' 2> ' . GIT_DEPLOY_ERROR_DUMP);
if ($tip == $head) {
list($upstream['branch'], $upstream['remote']) = array_reverse(explode('/', $branch));
$last_base = $tip;
$upstream['synced'] = TRUE;
break;
}
if (isset($upstream['branch'])) {
$tip = exec("{$git} merge-base HEAD " . escapeshellarg($tip) . ' 2> ' . GIT_DEPLOY_ERROR_DUMP);
if ($tip != $last_base) {
exec("{$git} merge-base --is-ancestor " . escapeshellarg($tip) . ' ' . escapeshellarg($last_base) . ' 2> ' . GIT_DEPLOY_ERROR_DUMP, $output, $status);
}
if ($tip == $last_base || $status === 0) {
break;
}
list($upstream['branch'], $upstream['remote']) = array_reverse(explode('/', $branch));
$last_base = $tip;
}
else {
list($upstream['branch'], $upstream['remote']) = array_reverse(explode('/', $branch));
$last_base = exec("{$git} merge-base HEAD " . escapeshellarg($tip) . ' 2> ' . GIT_DEPLOY_ERROR_DUMP);
$upstream['synced'] = $last_base == $tip;
}
}
if (!empty($tag)) {
exec("{$git} describe --tags --contains " . escapeshellarg($last_base) . ' --match ' . escapeshellarg($tag) . ' 2> ' . GIT_DEPLOY_ERROR_DUMP, $output, $status);
if ($status === 0) {
$upstream['tag'] = $tag;
}
}
}
}
else {
$upstream['tag'] = $tag;
}
}
$upstream['datestamp'] = exec("{$git} log -1 --pretty=format:%at " . escapeshellarg($last_base) . " 2> " . GIT_DEPLOY_ERROR_DUMP);
}
return $upstream;
}
function git_deploy_mydropwizard_projects_alter(&$projects) {
$update = _git_deploy_static('update', array());
_git_deploy_static_reset();
if (!empty($update)) {
$available = _git_deploy_update_refresh($projects);
foreach ($update as $project_name) {
$project =& $projects[$project_name];
$version = $project['info']['version'];
if (isset($available[$project_name]['releases'][$version])) {
_git_deploy_datestamp_sync($project, $available[$project_name]['releases'][$version]);
}
}
}
}
function _git_deploy_update_refresh($projects) {
static $fail = array();
global $base_url;
module_load_include('inc', 'mydropwizard', 'mydropwizard.compare');
_mydropwizard_cache_clear('mydropwizard_project_projects');
_mydropwizard_cache_clear('mydropwizard_project_data');
$available = array();
$data = array();
$site_key = md5($base_url . drupal_get_private_key());
_mydropwizard_cache_clear('mydropwizard_available_releases');
$max_fetch_attempts = variable_get('mydropwizard_max_fetch_attempts', UPDATE_MAX_FETCH_ATTEMPTS);
$project_versions = array();
foreach ($projects as $key => $project) {
if (strpos($project['project_type'], 'disabled') === FALSE) {
if (!empty($project['info']['version'])) {
$version = $project['info']['version'];
}
else {
$version = DRUPAL_CORE_COMPATIBILITY;
}
$project_versions[$key] = $version;
}
}
$statistics_url = variable_get('mydropwizard_statistics_url', MYDROPWIZARD_STATISTICS_URL);
$statistics_data = drupal_to_js(array(
'site_key' => $site_key,
'projects' => $project_versions,
'mydropwizard_key' => variable_get('mydropwizard_customer_key', ''),
));
if (variable_get('mydropwizard_http_post_disabled', FALSE)) {
$response = drupal_http_request($statistics_url . '?data=' . base64_encode($statistics_data));
}
else {
$response = drupal_http_request($statistics_url, array(
'Content-type' => 'application/json',
), 'POST', $statistics_data);
}
$update_status = $response->data;
variable_set('mydropwizard_update_status', $update_status);
if ($update_status == 'OK' || variable_get('mydropwizard_ignore_statistics_errors', FALSE)) {
module_load_include('inc', 'mydropwizard', 'mydropwizard.fetch');
foreach ($projects as $key => $project) {
$url = _mydropwizard_build_fetch_url($project, $site_key);
$fetch_url_base = _mydropwizard_get_fetch_url_base($project);
if (empty($fail[$fetch_url_base]) || count($fail[$fetch_url_base]) < $max_fetch_attempts) {
$xml = drupal_http_request($url);
if (isset($xml->data)) {
$data[] = $xml->data;
}
else {
$fail[$fetch_url_base][$key] = 1;
}
}
else {
$fail[$fetch_url_base][$key] = 1;
}
}
}
if ($data) {
$parser = new mydropwizard_xml_parser();
$available = $parser
->parse($data);
}
if (!empty($available) && is_array($available)) {
foreach ($fail as $fetch_url_base => $failures) {
foreach ($failures as $key => $value) {
$available[$key]['project_status'] = 'not-fetched';
}
}
$frequency = variable_get('mydropwizard_check_frequency', 1);
_mydropwizard_cache_set('mydropwizard_available_releases', $available, time() + 60 * 60 * 24 * $frequency);
watchdog('mydropwizard', 'Attempted to fetch information about all available new releases and updates.', array(), WATCHDOG_NOTICE, l(t('view'), 'admin/reports/updates'));
}
else {
watchdog('mydropwizard', 'Unable to fetch any information about available new releases and updates.', array(), WATCHDOG_ERROR, l(t('view'), 'admin/reports/updates'));
}
variable_set('mydropwizard_last_check', time());
return $available;
}
function _git_deploy_datestamp_sync(array &$project, array $release) {
if ($project['datestamp'] + 43200 + 100 > $release['date']) {
$project['datestamp'] = max($release['date'], $project['datestamp']);
}
}
function git_deploy_mydropwizard_status_alter(&$projects) {
if ($projects['git_deploy']['status'] == UPDATE_NOT_SUPPORTED && $projects['git_deploy']['project_status'] == 'unsupported') {
array_shift($projects['git_deploy']['extra']);
switch ($projects['git_deploy']['install_type']) {
case 'official':
if ($projects['git_deploy']['existing_version'] === $projects['git_deploy']['recommended'] || $projects['git_deploy']['existing_version'] === $projects['git_deploy']['latest_version']) {
$projects['git_deploy']['status'] = UPDATE_CURRENT;
}
else {
$projects['git_deploy']['status'] = UPDATE_NOT_CURRENT;
}
break;
case 'dev':
if (isset($projects['git_deploy']['dev_version']) && $projects['git_deploy']['releases'][$projects['git_deploy']['dev_version']]['date'] > $projects['git_deploy']['releases'][$projects['git_deploy']['latest_version']]['date']) {
$latest = $projects['git_deploy']['releases'][$projects['git_deploy']['dev_version']];
}
else {
$latest = $projects['git_deploy']['releases'][$projects['git_deploy']['latest_version']];
}
if (empty($projects['git_deploy']['datestamp'])) {
$projects['git_deploy']['status'] = UPDATE_NOT_CHECKED;
$projects['git_deploy']['reason'] = t('Unknown release date');
}
elseif ($projects['git_deploy']['datestamp'] + 100 > $latest['date']) {
$projects['git_deploy']['status'] = UPDATE_CURRENT;
}
else {
$projects['git_deploy']['status'] = UPDATE_NOT_CURRENT;
}
break;
default:
$projects['git_deploy']['status'] = UPDATE_UNKNOWN;
$projects['git_deploy']['reason'] = t('Invalid info');
}
}
}