View source
<?php
define('GIT_DEPLOY_ERROR_DUMP', file_exists('/dev/null') ? '/dev/null' : 'nul');
if (basename($_SERVER['PHP_SELF']) == 'update.php' || function_exists('update_main')) {
$GLOBALS['module_list']['git_deploy']['filename'] = __FILE__;
}
function git_deploy_boot() {
}
function git_deploy_system_info_alter(&$info, $file, $type) {
$projects =& drupal_static(__FUNCTION__ . ':projects', array());
$available =& drupal_static(__FUNCTION__ . ':available');
$update =& drupal_static(__FUNCTION__ . ':update', array());
$is_core = isset($info['package']) && strpos($info['package'], 'Core') === 0;
if (empty($info['hidden']) && (empty($info['version']) || ($is_core ? strstr($info['version'], '-dev') == '-dev' : $info['version'] == VERSION || !preg_match('/^7\\.x-\\d+\\..+/', $info['version'])))) {
$home = getenv('HOME') === FALSE ? 'HOME=' . DRUPAL_ROOT . ' ' : '';
$directory = exec($home . 'git -C ' . escapeshellarg(dirname($file->uri)) . ' 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->uri))) . ' 2> ' . GIT_DEPLOY_ERROR_DUMP)) {
$upstream = _git_deploy_get_upstream($git, $is_core ? array(
'7',
) : array(
'7.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('update') && ($upstream['synced'] || $upstream['branch'] == 'master')) {
if (!isset($available)) {
$available = _update_get_cached_available_releases();
}
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'] > $available[$project_name]['last_fetch']) {
$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_update_projects_alter(&$projects) {
$update = drupal_static('git_deploy_system_info_alter:update', array());
drupal_static_reset('git_deploy_system_info_alter:projects');
drupal_static_reset('git_deploy_system_info_alter:available');
drupal_static_reset('git_deploy_system_info_alter:update');
if (!empty($update)) {
module_load_include('inc', 'update', 'update.fetch');
foreach ($update as $project_name) {
_update_process_fetch_task($projects[$project_name]);
}
$available = _update_get_cached_available_releases();
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_datestamp_sync(array &$project, array $release) {
if ($project['datestamp'] + 43200 + 100 > $release['date']) {
$project['datestamp'] = max($release['date'], $project['datestamp']);
}
}