summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGábor Hojtsy <gabor@hojtsy.hu>2008-01-17 12:03:21 +0000
committerGábor Hojtsy <gabor@hojtsy.hu>2008-01-17 12:03:21 +0000
commit8c8d7336ea541edaba66e3093579fde832d9ef0e (patch)
treeaf8a5242c6a6b9b0db604af877f0cc41ff8f3162
parent75653ac7f4e14710798bd4785b2ab3e2dd0c00e5 (diff)
downloadbrdo-8c8d7336ea541edaba66e3093579fde832d9ef0e.tar.gz
brdo-8c8d7336ea541edaba66e3093579fde832d9ef0e.tar.bz2
#209242 by dww: local .info file changes (ie. updated code) was not taken properly into account in update module
-rw-r--r--modules/update/update.compare.inc24
-rw-r--r--modules/update/update.module31
2 files changed, 48 insertions, 7 deletions
diff --git a/modules/update/update.compare.inc b/modules/update/update.compare.inc
index 6b580d4eb..9b4501b64 100644
--- a/modules/update/update.compare.inc
+++ b/modules/update/update.compare.inc
@@ -49,19 +49,33 @@ function _update_process_info_list(&$projects, &$list, $project_type) {
$file->info['project'] = update_get_project_name($file);
}
- if (!isset($projects[$file->info['project']])) {
+ // If we don't already know it, grab the change time on the .info file
+ // itself. Note: we need to use the ctime, not the mtime (modification
+ // time) since many (all?) tar implementations will go out of their way to
+ // set the mtime on the files it creates to the timestamps recorded in the
+ // tarball. We want to see the last time the file was changed on disk,
+ // which is left alone by tar and correctly set to the time the .info file
+ // was unpacked.
+ if (!isset($file->info['_info_file_ctime'])) {
+ $info_filename = dirname($file->filename) .'/'. $file->name .'.info';
+ $file->info['_info_file_ctime'] = filectime($info_filename);
+ }
+
+ $project_name = $file->info['project'];
+ if (!isset($projects[$project_name])) {
// Only process this if we haven't done this project, since a single
// project can have multiple modules or themes.
- $projects[$file->info['project']] = array(
- 'name' => $file->info['project'],
+ $projects[$project_name] = array(
+ 'name' => $project_name,
'info' => $file->info,
'datestamp' => isset($file->info['datestamp']) ? $file->info['datestamp'] : 0,
'includes' => array($file->name => $file->info['name']),
- 'project_type' => $file->info['project'] == 'drupal' ? 'core' : $project_type,
+ 'project_type' => $project_name == 'drupal' ? 'core' : $project_type,
);
}
else {
- $projects[$file->info['project']]['includes'][$file->name] = $file->info['name'];
+ $projects[$project_name]['includes'][$file->name] = $file->info['name'];
+ $projects[$project_name]['info']['_info_file_ctime'] = max($projects[$project_name]['info']['_info_file_ctime'], $file->info['_info_file_ctime']);
}
}
}
diff --git a/modules/update/update.module b/modules/update/update.module
index 66f712bb3..d9f7ae588 100644
--- a/modules/update/update.module
+++ b/modules/update/update.module
@@ -320,17 +320,44 @@ function _update_no_data() {
* Internal helper to try to get the update information from the cache
* if possible, and to refresh the cache when necessary.
*
+ * In addition to checking the cache lifetime, this function also ensures that
+ * there are no .info files for enabled modules or themes that have a newer
+ * modification timestamp than the last time we checked for available update
+ * data. If any .info file was modified, it almost certainly means a new
+ * version of something was installed. Without fresh available update data,
+ * the logic in update_calculate_project_data() will be wrong and produce
+ * confusing, bogus results.
+ *
* @param $refresh
* Boolean to indicate if this method should refresh the cache automatically
* if there's no data.
+ *
+ * @see update_refresh()
+ * @see update_get_projects()
*/
function update_get_available($refresh = FALSE) {
+ include_once './modules/update/update.compare.inc';
$available = array();
- if (($cache = cache_get('update_info', 'cache_update'))
+
+ // First, make sure that none of the .info files have a change time
+ // newer than the last time we checked for available updates.
+ $needs_refresh = FALSE;
+ $last_check = variable_get('update_last_check', 0);
+ $projects = update_get_projects();
+ foreach ($projects as $key => $project) {
+ if ($project['info']['_info_file_ctime'] > $last_check) {
+ $needs_refresh = TRUE;
+ break;
+ }
+ }
+ if (!$needs_refresh && ($cache = cache_get('update_info', 'cache_update'))
&& $cache->expire > time()) {
$available = $cache->data;
}
- elseif ($refresh) {
+ elseif ($needs_refresh || $refresh) {
+ // If we need to refresh due to a newer .info file, ignore the argument
+ // and force the refresh (e.g., even for update_requirements()) to prevent
+ // bogus results.
$available = update_refresh();
}
return $available;