Index: modules/filter/filter.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/filter/filter.admin.inc,v
retrieving revision 1.19
diff -u -r1.19 filter.admin.inc
--- modules/filter/filter.admin.inc	3 Dec 2008 19:43:21 -0000	1.19
+++ modules/filter/filter.admin.inc	8 Dec 2008 09:02:51 -0000
@@ -288,7 +288,10 @@
 
   $default = variable_get('filter_default_format', 1);
   // Replace existing instances of the deleted format with the default format.
-  db_query("UPDATE {node_revision} SET format = %d WHERE format = %d", $default, $form_state['values']['format']);
+  db_query("UPDATE {node} SET format = %d WHERE format = %d", $default, $form_state['values']['format']);
+  if (db_table_exists('node_revision')) {
+    db_query("UPDATE {node_revision} SET format = %d WHERE format = %d", $default, $form_state['values']['format']);
+  }
   db_query("UPDATE {comment} SET format = %d WHERE format = %d", $default, $form_state['values']['format']);
   db_query("UPDATE {box} SET format = %d WHERE format = %d", $default, $form_state['values']['format']);
 
Index: modules/node/node.css
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.css,v
retrieving revision 1.5
diff -u -r1.5 node.css
--- modules/node/node.css	25 Jan 2008 21:21:44 -0000	1.5
+++ modules/node/node.css	8 Dec 2008 09:02:51 -0000
@@ -17,9 +17,6 @@
   margin-left: 0.5em; /* LTR */
   clear: right; /* LTR */
 }
-td.revision-current {
-  background: #ffc;
-}
 .node-form .form-text {
   display: block;
   width: 95%;
Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.1001
diff -u -r1.1001 node.module
--- modules/node/node.module	5 Dec 2008 22:18:45 -0000	1.1001
+++ modules/node/node.module	8 Dec 2008 09:02:52 -0000
@@ -65,7 +65,7 @@
 
   switch ($path) {
     case 'admin/help#node':
-      $output = '<p>' . t('The node module manages content on your site, and stores all posts (regardless of type) as a "node" . In addition to basic publishing settings, including whether the post has been published, promoted to the site front page, or should remain present (or sticky) at the top of lists, the node module also records basic information about the author of a post. Optional revision control over edits is available. For additional functionality, the node module is often extended by other modules.') . '</p>';
+      $output = '<p>' . t('The node module manages content on your site, and stores all posts (regardless of type) as a "node" . In addition to basic publishing settings, including whether the post has been published, promoted to the site front page, or should remain present (or sticky) at the top of lists, the node module also records basic information about the author of a post. Optional revision control over edits is available via the node_revision module. For additional functionality, the node module is often extended by other modules.') . '</p>';
       $output .= '<p>' . t('Though each post on your site is a node, each post is also of a particular <a href="@content-type">content type</a>. <a href="@content-type">Content types</a> are used to define the characteristics of a post, including the title and description of the fields displayed on its add and edit pages. Each content type may have different default settings for <em>Publishing options</em> and other workflow controls. By default, the two content types in a standard Drupal installation are <em>Page</em> and <em>Story</em>. Use the <a href="@content-type">content types page</a> to add new or edit existing content types. Additional content types also become available as you enable additional core, contributed and custom modules.', array('@content-type' => url('admin/build/types'))) . '</p>';
       $output .= '<p>' . t('The administrative <a href="@content">content page</a> allows you to review and manage your site content. The <a href="@post-settings">post settings page</a> sets certain options for the display of posts. The node module makes a number of permissions available for each content type, which may be set by role on the <a href="@permissions">permissions page</a>.', array('@content' => url('admin/content/node'), '@post-settings' => url('admin/content/node-settings'), '@permissions' => url('admin/user/permissions'))) . '</p>';
       $output .= '<p>' . t('For more information, see the online handbook entry for <a href="@node">Node module</a>.', array('@node' => 'http://drupal.org/handbook/modules/node/')) . '</p>';
@@ -76,8 +76,6 @@
       return '<p>' . t('Below is a list of all the content types on your site. All posts that exist on your site are instances of one of these content types.') . '</p>';
     case 'admin/build/types/add':
       return '<p>' . t('To create a new content type, enter the human-readable name, the machine-readable name, and all other relevant fields that are on this page. Once created, users of your site will be able to create posts that are instances of this content type.') . '</p>';
-    case 'node/%/revisions':
-      return '<p>' . t('The revisions let you track differences between multiple versions of a post.') . '</p>';
     case 'node/%/edit':
       $node = node_load($arg[1]);
       $type = node_get_types('type', $node->type);
@@ -129,9 +127,6 @@
       'arguments' => array('node' => NULL),
       'file' => 'node.pages.inc',
     ),
-    'node_log_message' => array(
-      'arguments' => array('log' => NULL),
-    ),
     'node_submitted' => array(
       'arguments' => array('node' => NULL),
     ),
@@ -760,13 +755,8 @@
   // when all requested nodes are loaded from cache.
   $passed_nids = !empty($nids) ? array_flip($nids) : FALSE;
 
-  // Revisions are not statically cached, and require a different query to
-  // other conditions, so separate vid into its own variable.
-  $vid = isset($conditions['vid']) ? $conditions['vid'] : FALSE;
-  unset($conditions['vid']);
-
   // Load any available nodes from the internal cache.
-  if ($node_cache && !$vid) {
+  if ($node_cache) {
     if ($nids) {
       $nodes += array_intersect_key($node_cache, $passed_nids);
       // If any nodes were loaded, remove them from the $nids still to load.
@@ -793,36 +783,16 @@
   // Load any remaining nodes from the database. This is the case if there are
   // any $nids left to load, if loading a revision, or if $conditions was
   // passed without $nids.
-  if ($nids || $vid || ($conditions && !$passed_nids)) {
+  if ($nids || ($conditions && !$passed_nids)) {
     $query = db_select('node', 'n');
 
-    if ($vid) {
-      $query->join('node_revision', 'r', 'r.nid = n.nid AND r.vid = :vid', array(':vid' => $vid));
-    }
-    else {
-      $query->join('node_revision', 'r', 'r.vid = n.vid');
-    }
     $query->join('users', 'u', 'u.uid = n.uid');
 
     // Add fields from the {node} table.
     $node_fields = drupal_schema_fields_sql('node');
 
-    // vid and title are provided by node_revision, so remove them.
-    unset($node_fields['vid']);
-    unset($node_fields['title']);
     $query->fields('n', $node_fields);
 
-    // Add all fields from the {node_revision} table.
-    $node_revision_fields = drupal_schema_fields_sql('node_revision');
-
-    // nid is provided by node, so remove it.
-    unset($node_revision_fields['nid']);
-
-    // Change timestamp to revision_timestamp before adding it to the query.
-    unset($node_revision_fields['timestamp']);
-    $query->addField('r', 'timestamp', 'revision_timestamp');
-    $query->fields('r', $node_revision_fields);
-
     // Add fields from the {users} table.
     $user_fields = array('name', 'picture', 'data');
     $query->fields('u', $user_fields);
@@ -863,10 +833,8 @@
       $function($queried_nodes, array_keys($typed_nodes));
     }
     $nodes += $queried_nodes;
-    // Add nodes to the cache if we're not loading a revision.
-    if (!$vid) {
-      $node_cache += $queried_nodes;
-    }
+    // Add nodes to the cache.
+    $node_cache += $queried_nodes;
   }
 
   // Ensure that the returned array is ordered the same as the original $nids
@@ -888,17 +856,14 @@
  *
  * @param $nid
  *   The node ID.
- * @param $vid
- *   The revision ID.
  * @param $reset
  *   Whether to reset the internal node_load cache.
  *
  * @return
  *   A fully-populated node object.
  */
-function node_load($nid, $vid = array(), $reset = FALSE) {
-  $vid = isset($vid) ? array('vid' => $vid) : NULL;
-  $node = node_load_multiple(array($nid), $vid, $reset);
+function node_load($nid, $reset = FALSE) {
+  $node = node_load_multiple(array($nid), NULL, $reset);
 
   return $node ? $node[$nid] : FALSE;
 }
@@ -998,17 +963,9 @@
     // Insert a new node.
     $node->is_new = TRUE;
 
-    // When inserting a node, $node->log must be set because
-    // {node_revision}.log does not (and cannot) have a default
-    // value.  If the user does not have permission to create
-    // revisions, however, the form will not contain an element for
-    // log so $node->log will be unset at this point.
-    if (!isset($node->log)) {
-      $node->log = '';
-    }
-
-    // For the same reasons, make sure we have $node->teaser and
-    // $node->body.  We should consider making these fields nullable
+    // When inserting a node, $node->teaser and $node->body must be set
+    // because {node}.teaser and {node}.body do not (and cannot) have a
+    // default value. We should consider making these fields nullable
     // in a future version since node types are not required to use them.
     if (!isset($node->teaser)) {
       $node->teaser = '';
@@ -1017,15 +974,6 @@
       $node->body = '';
     }
   }
-  elseif (!empty($node->revision)) {
-    $node->old_vid = $node->vid;
-  }
-  else {
-    // When updating a node, avoid clobberring an existing log entry with an empty one.
-    if (empty($node->log)) {
-      unset($node->log);
-    }
-  }
 
   // Set some required fields:
   if (empty($node->created)) {
@@ -1035,28 +983,16 @@
   $node->changed = REQUEST_TIME;
 
   $node->timestamp = REQUEST_TIME;
-  $update_node = TRUE;
 
-  // Generate the node table query and the node_revisions table query.
+  // Generate the node table query.
   if ($node->is_new) {
     drupal_write_record('node', $node);
-    _node_save_revision($node, $user->uid);
     $op = 'insert';
   }
   else {
     drupal_write_record('node', $node, 'nid');
-    if (!empty($node->revision)) {
-      _node_save_revision($node, $user->uid);
-    }
-    else {
-      _node_save_revision($node, $user->uid, 'vid');
-      $update_node = FALSE;
-    }
     $op = 'update';
   }
-  if ($update_node) {
-    db_query('UPDATE {node} SET vid = %d WHERE nid = %d', $node->vid, $node->nid);
-  }
 
   // Call the node specific callback (if any). This can be
   // node_invoke($node, 'insert') or
@@ -1072,24 +1008,6 @@
 }
 
 /**
- * Helper function to save a revision with the uid of the current user.
- *
- * Node is taken by reference, becuse drupal_write_record() updates the
- * $node with the revision id, and we need to pass that back to the caller.
- */
-function _node_save_revision(&$node, $uid, $update = NULL) {
-  $temp_uid = $node->uid;
-  $node->uid = $uid;
-  if (isset($update)) {
-    drupal_write_record('node_revision', $node, $update);
-  }
-  else {
-    drupal_write_record('node_revision', $node);
-  }
-  $node->uid = $temp_uid;
-}
-
-/**
  * Delete a node.
  */
 function node_delete($nid) {
@@ -1098,7 +1016,6 @@
 
   if (node_access('delete', $node)) {
     db_query('DELETE FROM {node} WHERE nid = %d', $node->nid);
-    db_query('DELETE FROM {node_revision} WHERE nid = %d', $node->nid);
 
     // Call the node-specific callback (if any):
     node_invoke($node, 'delete');
@@ -1228,10 +1145,7 @@
 /**
  * Generate a page displaying a single node, along with its comments.
  */
-function node_show($node, $cid, $message = FALSE) {
-  if ($message) {
-    drupal_set_title(t('Revision of %title from %date', array('%title' => $node->title, '%date' => format_date($node->revision_timestamp))), PASS_THROUGH);
-  }
+function node_show($node, $cid) {
   $output = node_view($node, FALSE, TRUE);
 
   if (function_exists('comment_render') && $node->comment) {
@@ -1245,15 +1159,6 @@
 }
 
 /**
- * Theme a log message.
- *
- * @ingroup themeable
- */
-function theme_node_log_message($log) {
-  return '<div class="log"><div class="title">' . t('Log') . ':</div>' . $log . '</div>';
-}
-
-/**
  * Implementation of hook_perm().
  */
 function node_perm() {
@@ -1264,7 +1169,7 @@
     ),
     'administer nodes' => array(
       'title' => t('Administer nodes'),
-      'description' => t('Manage all information associated with site content, such as author, publication date and current revision. %warning', array('%warning' => t('Warning: Give to trusted roles only; this permission has security implications.'))),
+      'description' => t('Manage all information associated with site content, such as author and publication date and current revision. %warning', array('%warning' => t('Warning: Give to trusted roles only; this permission has security implications.'))),
     ),
     'access content' => array(
       'title' => t('Access content'),
@@ -1274,18 +1179,6 @@
       'title' => t('Bypass node access'),
       'description' => t('View, edit and delete all site content. Users with this permission will bypass any content-related access control. %warning', array('%warning' => t('Warning: Give to trusted roles only; this permission has security implications.'))),
     ),
-    'view revisions' => array(
-      'title' => t('View revisions'),
-      'description' => t('View content revisions.'),
-    ),
-    'revert revisions' => array(
-      'title' => t('Revert revisions'),
-      'description' => t('Replace content with an older revision.'),
-    ),
-    'delete revisions' => array(
-      'title' => t('Delete revisions'),
-      'description' => t('Delete content revisions.'),
-    ),
   );
 
   foreach (node_get_types() as $type) {
@@ -1501,7 +1394,6 @@
  */
 function node_user_delete(&$edit, &$user) {
   db_query('UPDATE {node} SET uid = 0 WHERE uid = %d', $user->uid);
-  db_query('UPDATE {node_revision} SET uid = 0 WHERE uid = %d', $user->uid);
 }
 
 /**
@@ -1555,33 +1447,6 @@
   return $links;
 }
 
-function _node_revision_access($node, $op = 'view') {
-  static $access = array();
-  if (!isset($access[$node->vid])) {
-    $node_current_revision = node_load($node->nid);
-    $is_current_revision = $node_current_revision->vid == $node->vid;
-    // There should be at least two revisions. If the vid of the given node
-    // and the vid of the current revision differs, then we already have two
-    // different revisions so there is no need for a separate database check.
-    // Also, if you try to revert to or delete the current revision, that's
-    // not good.
-    if ($is_current_revision && (db_result(db_query('SELECT COUNT(vid) FROM {node_revision} WHERE nid = %d', $node->nid)) == 1 || $op == 'update' || $op == 'delete')) {
-      $access[$node->vid] = FALSE;
-    }
-    elseif (user_access('administer nodes')) {
-      $access[$node->vid] = TRUE;
-    }
-    else {
-      $map = array('view' => 'view revisions', 'update' => 'revert revisions', 'delete' => 'delete revisions');
-      // First check the user permission, second check the access to the
-      // current revision and finally, if the node passed in is not the current
-      // revision then access to that, too.
-      $access[$node->vid] = isset($map[$op]) && user_access($map[$op]) && node_access($op, $node_current_revision) && ($is_current_revision || node_access($op, $node));
-    }
-  }
-  return $access[$node->vid];
-}
-
 function _node_add_access() {
   $types = node_get_types();
   foreach ($types as $type) {
@@ -1719,41 +1584,6 @@
     'access callback' => 'node_access',
     'access arguments' => array('delete', 1),
     'weight' => 1,
-    'type' => MENU_CALLBACK);
-  $items['node/%node/revisions'] = array(
-    'title' => 'Revisions',
-    'page callback' => 'node_revision_overview',
-    'page arguments' => array(1),
-    'access callback' => '_node_revision_access',
-    'access arguments' => array(1),
-    'weight' => 2,
-    'type' => MENU_LOCAL_TASK,
-  );
-  $items['node/%node/revisions/%/view'] = array(
-    'title' => 'Revisions',
-    'load arguments' => array(3),
-    'page callback' => 'node_show',
-    'page arguments' => array(1, NULL, TRUE),
-    'access callback' => '_node_revision_access',
-    'access arguments' => array(1),
-    'type' => MENU_CALLBACK,
-  );
-  $items['node/%node/revisions/%/revert'] = array(
-    'title' => 'Revert to earlier revision',
-    'load arguments' => array(3),
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('node_revision_revert_confirm', 1),
-    'access callback' => '_node_revision_access',
-    'access arguments' => array(1, 'update'),
-    'type' => MENU_CALLBACK,
-  );
-  $items['node/%node/revisions/%/delete'] = array(
-    'title' => 'Delete earlier revision',
-    'load arguments' => array(3),
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('node_revision_delete_confirm', 1),
-    'access callback' => '_node_revision_access',
-    'access arguments' => array(1, 'delete'),
     'type' => MENU_CALLBACK,
   );
   return $items;
@@ -1779,19 +1609,6 @@
 }
 
 /**
- * Return a list of all the existing revision numbers.
- */
-function node_revision_list($node) {
-  $revisions = array();
-  $result = db_query('SELECT r.vid, r.title, r.log, r.uid, n.vid AS current_vid, r.timestamp, u.name FROM {node_revision} r LEFT JOIN {node} n ON n.vid = r.vid INNER JOIN {users} u ON u.uid = r.uid WHERE r.nid = %d ORDER BY r.timestamp DESC', $node->nid);
-  while ($revision = db_fetch_object($result)) {
-    $revisions[$revision->vid] = $revision;
-  }
-
-  return $revisions;
-}
-
-/**
  * Implementation of hook_block().
  */
 function node_block($op = 'list', $delta = '') {
Index: modules/node/content_types.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/content_types.inc,v
retrieving revision 1.60
diff -u -r1.60 content_types.inc
--- modules/node/content_types.inc	16 Nov 2008 18:19:46 -0000	1.60
+++ modules/node/content_types.inc	8 Dec 2008 09:02:51 -0000
@@ -155,7 +155,6 @@
       'status' => t('Published'),
       'promote' => t('Promoted to front page'),
       'sticky' => t('Sticky at top of lists'),
-      'revision' => t('Create new revision'),
     ),
     '#description' => t('Users with the <em>administer nodes</em> permission will be able to override these options.'),
   );
Index: modules/node/node.pages.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.pages.inc,v
retrieving revision 1.46
diff -u -r1.46 node.pages.inc
--- modules/node/node.pages.inc	3 Dec 2008 16:32:22 -0000	1.46
+++ modules/node/node.pages.inc	8 Dec 2008 09:02:52 -0000
@@ -3,7 +3,7 @@
 
 /**
  * @file
- * Page callbacks for adding, editing, deleting, and revisions management for content.
+ * Page callbacks for adding, editing and deleting content.
  */
 
 
@@ -85,8 +85,6 @@
   else {
     $node->date = format_date($node->created, 'custom', 'Y-m-d H:i:s O');
   }
-  // Always use the default revision setting.
-  $node->revision = in_array('revision', $node_options);
 
   node_invoke($node, 'prepare');
   node_invoke_nodeapi($node, 'prepare');
@@ -145,31 +143,6 @@
 
   $form['#node'] = $node;
 
-  // Add a log field if the "Create new revision" option is checked, or if the
-  // current user has the ability to check that option.
-  if (!empty($node->revision) || user_access('administer nodes')) {
-    $form['revision_information'] = array(
-      '#type' => 'fieldset',
-      '#title' => t('Revision information'),
-      '#collapsible' => TRUE,
-      // Collapsed by default when "Create new revision" is unchecked
-      '#collapsed' => !$node->revision,
-      '#weight' => 20,
-    );
-    $form['revision_information']['revision'] = array(
-      '#access' => user_access('administer nodes'),
-      '#type' => 'checkbox',
-      '#title' => t('Create new revision'),
-      '#default_value' => $node->revision,
-    );
-    $form['revision_information']['log'] = array(
-      '#type' => 'textarea',
-      '#title' => t('Log message'),
-      '#rows' => 2,
-      '#description' => t('An explanation of the additions or updates being made to help other authors understand your motivations.'),
-    );
-  }
-
   // Node author information for administrators
   $form['author'] = array(
     '#type' => 'fieldset',
@@ -500,87 +473,3 @@
   $form_state['redirect'] = '<front>';
 }
 
-/**
- * Generate an overview table of older revisions of a node.
- */
-function node_revision_overview($node) {
-  drupal_set_title(t('Revisions for %title', array('%title' => $node->title)), PASS_THROUGH);
-
-  $header = array(t('Revision'), array('data' => t('Operations'), 'colspan' => 2));
-
-  $revisions = node_revision_list($node);
-
-  $rows = array();
-  $revert_permission = FALSE;
-  if ((user_access('revert revisions') || user_access('administer nodes')) && node_access('update', $node)) {
-    $revert_permission = TRUE;
-  }
-  $delete_permission = FALSE;
-  if ((user_access('delete revisions') || user_access('administer nodes')) && node_access('delete', $node)) {
-    $delete_permission = TRUE;
-  }
-  foreach ($revisions as $revision) {
-    $row = array();
-    $operations = array();
-
-    if ($revision->current_vid > 0) {
-      $row[] = array('data' => t('!date by !username', array('!date' => l(format_date($revision->timestamp, 'small'), "node/$node->nid"), '!username' => theme('username', $revision)))
-                               . (($revision->log != '') ? '<p class="revision-log">' . filter_xss($revision->log) . '</p>' : ''),
-                     'class' => 'revision-current');
-      $operations[] = array('data' => theme('placeholder', t('current revision')), 'class' => 'revision-current', 'colspan' => 2);
-    }
-    else {
-      $row[] = t('!date by !username', array('!date' => l(format_date($revision->timestamp, 'small'), "node/$node->nid/revisions/$revision->vid/view"), '!username' => theme('username', $revision)))
-               . (($revision->log != '') ? '<p class="revision-log">' . filter_xss($revision->log) . '</p>' : '');
-      if ($revert_permission) {
-        $operations[] = l(t('revert'), "node/$node->nid/revisions/$revision->vid/revert");
-      }
-      if ($delete_permission) {
-        $operations[] = l(t('delete'), "node/$node->nid/revisions/$revision->vid/delete");
-      }
-    }
-    $rows[] = array_merge($row, $operations);
-  }
-
-  return theme('table', $header, $rows);
-}
-
-/**
- * Ask for confirmation of the reversion to prevent against CSRF attacks.
- */
-function node_revision_revert_confirm($form_state, $node_revision) {
-  $form['#node_revision'] = $node_revision;
-  return confirm_form($form, t('Are you sure you want to revert to the revision from %revision-date?', array('%revision-date' => format_date($node_revision->revision_timestamp))), 'node/' . $node_revision->nid . '/revisions', '', t('Revert'), t('Cancel'));
-}
-
-function node_revision_revert_confirm_submit($form, &$form_state) {
-  $node_revision = $form['#node_revision'];
-  $node_revision->revision = 1;
-  $node_revision->log = t('Copy of the revision from %date.', array('%date' => format_date($node_revision->revision_timestamp)));
-  if (module_exists('taxonomy')) {
-    $node_revision->taxonomy = array_keys($node_revision->taxonomy);
-  }
-
-  node_save($node_revision);
-
-  watchdog('content', '@type: reverted %title revision %revision.', array('@type' => $node_revision->type, '%title' => $node_revision->title, '%revision' => $node_revision->vid));
-  drupal_set_message(t('@type %title has been reverted back to the revision from %revision-date.', array('@type' => node_get_types('name', $node_revision), '%title' => $node_revision->title, '%revision-date' => format_date($node_revision->revision_timestamp))));
-  $form_state['redirect'] = 'node/' . $node_revision->nid . '/revisions';
-}
-
-function node_revision_delete_confirm($form_state, $node_revision) {
-  $form['#node_revision'] = $node_revision;
-  return confirm_form($form, t('Are you sure you want to delete the revision from %revision-date?', array('%revision-date' => format_date($node_revision->revision_timestamp))), 'node/' . $node_revision->nid . '/revisions', t('This action cannot be undone.'), t('Delete'), t('Cancel'));
-}
-
-function node_revision_delete_confirm_submit($form, &$form_state) {
-  $node_revision = $form['#node_revision'];
-  db_query("DELETE FROM {node_revision} WHERE nid = %d AND vid = %d", $node_revision->nid, $node_revision->vid);
-  node_invoke_nodeapi($node_revision, 'delete_revision');
-  watchdog('content', '@type: deleted %title revision %revision.', array('@type' => $node_revision->type, '%title' => $node_revision->title, '%revision' => $node_revision->vid));
-  drupal_set_message(t('Revision from %revision-date of @type %title has been deleted.', array('%revision-date' => format_date($node_revision->revision_timestamp), '@type' => node_get_types('name', $node_revision), '%title' => $node_revision->title)));
-  $form_state['redirect'] = 'node/' . $node_revision->nid;
-  if (db_result(db_query('SELECT COUNT(vid) FROM {node_revision} WHERE nid = %d', $node_revision->nid)) > 1) {
-    $form_state['redirect'] .= '/revisions';
-  }
-}
Index: modules/node/node.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.test,v
retrieving revision 1.10
diff -u -r1.10 node.test
--- modules/node/node.test	5 Dec 2008 22:18:45 -0000	1.10
+++ modules/node/node.test	8 Dec 2008 09:02:52 -0000
@@ -81,91 +81,6 @@
   }
 }
 
-class NodeRevisionsTestCase extends DrupalWebTestCase {
-  protected $nodes;
-  protected $logs;
-
-  function getInfo() {
-    return array(
-      'name' => t('Node revisions'),
-      'description' => t('Create a node with revisions and test viewing, reverting, and deleting revisions.'),
-      'group' => t('Node'),
-    );
-  }
-
-  function setUp() {
-    parent::setUp();
-
-    // Create and login user.
-    $web_user = $this->drupalCreateUser(array('view revisions', 'revert revisions', 'edit any page content',
-                                               'delete revisions', 'delete any page content'));
-    $this->drupalLogin($web_user);
-
-    // Create initial node.
-    $node = $this->drupalCreateNode();
-    $settings = get_object_vars($node);
-    $settings['revision'] = 1;
-
-    $nodes = array();
-    $logs = array();
-
-    // Get original node.
-    $nodes[] = $node;
-
-    // Create three revisions.
-    $revision_count = 3;
-    for ($i = 0; $i < $revision_count; $i++) {
-      $logs[] = $settings['log'] = $this->randomName(32);
-
-      // Create revision with random title and body and update variables.
-      $this->drupalCreateNode($settings);
-      $node = node_load($node->nid); // Make sure we get revision information.
-      $settings = get_object_vars($node);
-
-      $nodes[] = $node;
-    }
-
-    $this->nodes = $nodes;
-    $this->logs = $logs;
-  }
-
-  /**
-   * Check node revision related opperations.
-   */
-  function testRevisions() {
-    $nodes = $this->nodes;
-    $logs = $this->logs;
-
-    // Get last node for simple checks.
-    $node = $nodes[3];
-
-    // Confirm the correct revision text appears on "view revisions" page.
-    $this->drupalGet("node/$node->nid/revisions/$node->vid/view");
-    $this->assertText($node->body, t('Correct text displays for version.'));
-
-    // Confirm the correct log message appears on "revisions overview" page.
-    $this->drupalGet("node/$node->nid/revisions");
-    foreach ($logs as $log) {
-      $this->assertText($log, t('Log message found.'));
-    }
-
-    // Confirm that revisions revert properly.
-    $this->drupalPost("node/$node->nid/revisions/{$nodes[1]->vid}/revert", array(), t('Revert'));
-    $this->assertRaw(t('@type %title has been reverted back to the revision from %revision-date.',
-                        array('@type' => 'Page', '%title' => $nodes[1]->title,
-                              '%revision-date' => format_date($nodes[1]->revision_timestamp))), t('Revision reverted.'));
-    $reverted_node = node_load($node->nid);
-    $this->assertTrue(($nodes[1]->body == $reverted_node->body), t('Node reverted correctly.'));
-
-    // Confirm revisions delete properly.
-    $this->drupalPost("node/$node->nid/revisions/{$nodes[1]->vid}/delete", array(), t('Delete'));
-    $this->assertRaw(t('Revision from %revision-date of @type %title has been deleted.',
-                        array('%revision-date' => format_date($nodes[1]->revision_timestamp),
-                              '@type' => 'Page', '%title' => $nodes[1]->title)), t('Revision deleted.'));
-    $this->assertTrue(db_result(db_query('SELECT COUNT(vid) FROM {node_revision} WHERE nid = %d and vid = %d', $node->nid, $nodes[1]->vid)) == 0, t('Revision not found.'));
-  }
-}
-
 class NodeTeaserTestCase extends DrupalWebTestCase {
   function getInfo() {
     return array(
Index: modules/node/node.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.install,v
retrieving revision 1.9
diff -u -r1.9 node.install
--- modules/node/node.install	3 Dec 2008 16:32:21 -0000	1.9
+++ modules/node/node.install	8 Dec 2008 09:02:51 -0000
@@ -42,6 +42,24 @@
         'not null' => TRUE,
         'default' => '',
       ),
+      'body' => array(
+        'description' => 'The body of this version.',
+        'type' => 'text',
+        'not null' => TRUE,
+        'size' => 'big',
+      ),
+      'teaser' => array(
+        'description' => 'The teaser of this version.',
+        'type' => 'text',
+        'not null' => TRUE,
+        'size' => 'big',
+      ),
+      'format' => array(
+        'description' => "The input format used by this version's body.",
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
       'uid' => array(
         'description' => 'The {users}.uid that owns this node; initially, this is the user that created it.',
         'type' => 'int',
@@ -210,73 +228,6 @@
     'primary key' => array('nid'),
   );
 
-  $schema['node_revision'] = array(
-    'description' => 'Stores information about each saved version of a {node}.',
-    'fields' => array(
-      'nid' => array(
-        'description' => 'The {node} this version belongs to.',
-        'type' => 'int',
-        'unsigned' => TRUE,
-        'not null' => TRUE,
-        'default' => 0,
-      ),
-      'vid' => array(
-        'description' => 'The primary identifier for this version.',
-        'type' => 'serial',
-        'unsigned' => TRUE,
-        'not null' => TRUE,
-      ),
-      'uid' => array(
-        'description' => 'The {users}.uid that created this version.',
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 0,
-      ),
-      'title' => array(
-        'description' => 'The title of this version.',
-        'type' => 'varchar',
-        'length' => 255,
-        'not null' => TRUE,
-        'default' => '',
-      ),
-      'body' => array(
-        'description' => 'The body of this version.',
-        'type' => 'text',
-        'not null' => TRUE,
-        'size' => 'big',
-      ),
-      'teaser' => array(
-        'description' => 'The teaser of this version.',
-        'type' => 'text',
-        'not null' => TRUE,
-        'size' => 'big',
-      ),
-      'log' => array(
-        'description' => 'The log entry explaining the changes in this version.',
-        'type' => 'text',
-        'not null' => TRUE,
-        'size' => 'big',
-      ),
-      'timestamp' => array(
-        'description' => 'A Unix timestamp indicating when this version was created.',
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 0,
-      ),
-      'format' => array(
-        'description' => "The input format used by this version's body.",
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 0,
-      ),
-    ),
-    'indexes' => array(
-      'nid' => array('nid'),
-      'uid' => array('uid'),
-    ),
-    'primary key' => array('vid'),
-  );
-
   $schema['node_type'] = array(
     'description' => 'Stores information about all defined {node} types.',
     'fields' => array(
@@ -326,7 +277,7 @@
         'default' => '',
       ),
       'has_body' => array(
-        'description' => 'Boolean indicating whether this type uses the {node_revision}.body field.',
+        'description' => 'Boolean indicating whether this type uses the {node}.body field.',
         'type' => 'int',
         'unsigned' => TRUE,
         'not null' => TRUE,
@@ -407,5 +358,54 @@
 }
 
 /**
+ * Split off Node Revisions module from Node module.
+ */
+function node_update_7002() {
+  $ret = array();
+
+  // Add columns to the {node} table.
+  $columns = array(
+	  'body' => array(
+	    'description' => 'The body of this version.',
+	    'type' => 'text',
+	    'not null' => TRUE,
+	    'size' => 'big',
+	  ),
+	  'teaser' => array(
+      'description' => 'The teaser of this version.',
+      'type' => 'text',
+      'not null' => TRUE,
+      'size' => 'big',
+    ),
+    'format' => array(
+      'description' => "The input format used by this version's body.",
+      'type' => 'int',
+      'not null' => TRUE,
+      'default' => 0,
+    ),
+  );
+  foreach ($columns as $name => $definition) {
+    db_add_field($ret, 'node', $name, $definition);
+  }
+  
+  // Migrate over information.
+  $ret[] = update_sql('UPDATE {node} n, {node_revision} r
+	  SET n.body = r.body, n.teaser = r.teaser, n.format = r.format
+    WHERE n.vid = r.vid;');
+  
+    /**
+    if (db_table_exists('node_revision')) {
+	    // node table is self-sufficient now, so we can safely remove
+	    // single revisions from the node_revision table.
+       $ret[] = update_sql('CREATE TABLE {node_revision_temp} AS SELECT * FROM {node_revision} GROUP BY nid HAVING COUNT(nid) > 1');
+	    db_rename_table($ret, 'node_revision', 'node_revision_old');
+	    db_rename_table($ret, 'node_revision_temp', 'node_revision');
+	    db_drop_table($ret, 'node_revision_old');
+    }
+    */
+  return $ret;
+}
+
+/**
  * End of 6.x to 7.x updates
  */
Index: modules/search/search.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/search/search.module,v
retrieving revision 1.277
diff -u -r1.277 search.module
--- modules/search/search.module	3 Dec 2008 16:32:22 -0000	1.277
+++ modules/search/search.module	8 Dec 2008 09:02:55 -0000
@@ -508,7 +508,7 @@
               $linknid = $match[1];
               if ($linknid > 0) {
                 // Note: ignore links to uncachable nodes to avoid redirect bugs.
-                $node = db_fetch_object(db_query('SELECT n.title, n.nid, n.vid, r.format FROM {node} n INNER JOIN {node_revision} r ON n.vid = r.vid WHERE n.nid = %d', $linknid));
+                $node = db_fetch_object(db_query('SELECT title, nid, vid, format FROM {node} WHERE nid = %d', $linknid));
                 if (filter_format_allowcache($node->format)) {
                   $link = TRUE;
                   $linktitle = $node->title;
Index: modules/blogapi/blogapi.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/blogapi/blogapi.module,v
retrieving revision 1.135
diff -u -r1.135 blogapi.module
--- modules/blogapi/blogapi.module	5 Dec 2008 12:50:27 -0000	1.135
+++ modules/blogapi/blogapi.module	8 Dec 2008 09:02:51 -0000
@@ -201,7 +201,6 @@
   $edit['name'] = $user->name;
   $edit['promote'] = in_array('promote', $node_type_default);
   $edit['comment'] = variable_get('comment_' . $edit['type'], 2);
-  $edit['revision'] = in_array('revision', $node_type_default);
   $edit['format'] = FILTER_FORMAT_DEFAULT;
   $edit['status'] = $publish;
 
@@ -379,7 +378,7 @@
   }
 
   if ($bodies) {
-    $result = db_query_range("SELECT n.nid, n.title, r.body, r.format, n.comment, n.created, u.name FROM {node} n, {node_revision} r, {users} u WHERE n.uid = u.uid AND n.vid = r.vid AND n.type = :type AND n.uid = :uid ORDER BY n.created DESC",  array(
+    $result = db_query_range("SELECT n.nid, n.title, n.body, n.format, n.comment, n.created, u.name FROM {node} n, {users} u WHERE n.uid = u.uid AND n.type = :type AND n.uid = :uid ORDER BY n.created DESC",  array(
       ':type' => $blogid,
       ':uid' => $user->uid
     ), 0, $number_of_posts);
Index: modules/node_revision/node_revision.install
===================================================================
RCS file: modules/node_revision/node_revision.install
diff -N modules/node_revision/node_revision.install
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/node_revision/node_revision.install	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,93 @@
+<?php
+// $Id$
+
+/**
+ * Implementation of hook_install().
+ */
+function node_revision_install() {
+  // Create tables.
+  drupal_install_schema('node_revision');
+}
+
+/**
+ * Implementation of hook_uninstall().
+ */
+function node_revision_uninstall() {
+  // Remove tables.
+  drupal_uninstall_schema('node_revision');
+}
+
+/**
+ * Implementation of hook_schema().
+ */
+function node_revision_schema() {
+  $schema['node_revision'] = array(
+    'description' => 'Stores information about each saved version of a {node}.',
+    'fields' => array(
+      'nid' => array(
+        'description' => 'The {node} this version belongs to.',
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'vid' => array(
+        'description' => 'The primary identifier for this version.',
+        'type' => 'serial',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+      ),
+      'uid' => array(
+        'description' => 'The {users}.uid that created this version.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'title' => array(
+        'description' => 'The title of this version.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'body' => array(
+        'description' => 'The body of this version.',
+        'type' => 'text',
+        'not null' => TRUE,
+        'size' => 'big',
+      ),
+      'teaser' => array(
+        'description' => 'The teaser of this version.',
+        'type' => 'text',
+        'not null' => TRUE,
+        'size' => 'big',
+      ),
+      'format' => array(
+        'description' => "The input format used by this version's body.",
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'log' => array(
+        'description' => 'The log entry explaining the changes in this version.',
+        'type' => 'text',
+        'not null' => TRUE,
+        'size' => 'big',
+      ),
+      'timestamp' => array(
+        'description' => 'A Unix timestamp indicating when this version was created.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+    ),
+    'indexes' => array(
+      'nid' => array('nid'),
+      'uid' => array('uid'),
+    ),
+    'primary key' => array('vid'),
+  );
+
+  return $schema;
+}
+
Index: modules/node_revision/node_revision.pages.inc
===================================================================
RCS file: modules/node_revision/node_revision.pages.inc
diff -N modules/node_revision/node_revision.pages.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/node_revision/node_revision.pages.inc	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,95 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Page callbacks for node revisions management.
+ */
+
+/**
+ * Generate an overview table of older revisions of a node.
+ */
+function node_revision_overview($node) {
+  drupal_set_title(t('Revisions for %title', array('%title' => $node->title)), PASS_THROUGH);
+
+  $header = array(t('Revision'), array('data' => t('Operations'), 'colspan' => 2));
+
+  $revisions = node_revision_list($node);
+
+  $rows = array();
+  $revert_permission = FALSE;
+  if ((user_access('revert revisions') || user_access('administer nodes')) && node_access('update', $node)) {
+    $revert_permission = TRUE;
+  }
+  $delete_permission = FALSE;
+  if ((user_access('delete revisions') || user_access('administer nodes')) && node_access('delete', $node)) {
+    $delete_permission = TRUE;
+  }
+  foreach ($revisions as $revision) {
+    $row = array();
+    $operations = array();
+
+    if ($revision->current_vid > 0) {
+      $row[] = array('data' => t('!date by !username', array('!date' => l(format_date($revision->timestamp, 'small'), "node/$node->nid"), '!username' => theme('username', $revision)))
+                               . (($revision->log != '') ? '<p class="revision-log">' . filter_xss($revision->log) . '</p>' : ''),
+                     'class' => 'revision-current');
+      $operations[] = array('data' => theme('placeholder', t('current revision')), 'class' => 'revision-current', 'colspan' => 2);
+    }
+    else {
+      $row[] = t('!date by !username', array('!date' => l(format_date($revision->timestamp, 'small'), "node/$node->nid/revisions/$revision->vid/view"), '!username' => theme('username', $revision)))
+               . (($revision->log != '') ? '<p class="revision-log">' . filter_xss($revision->log) . '</p>' : '');
+      if ($revert_permission) {
+        $operations[] = l(t('revert'), "node/$node->nid/revisions/$revision->vid/revert");
+      }
+      if ($delete_permission) {
+        $operations[] = l(t('delete'), "node/$node->nid/revisions/$revision->vid/delete");
+      }
+    }
+    $rows[] = array_merge($row, $operations);
+  }
+
+  return theme('table', $header, $rows);
+}
+
+/**
+ * Ask for confirmation of the reversion to prevent against CSRF attacks.
+ */
+function node_revision_revert_confirm($form_state, $node_revision) {
+  $form['#node_revision'] = $node_revision;
+  return confirm_form($form, t('Are you sure you want to revert to the revision from %revision-date?', array('%revision-date' => format_date($node_revision->revision_timestamp))), 'node/' . $node_revision->nid . '/revisions', '', t('Revert'), t('Cancel'));
+}
+
+function node_revision_revert_confirm_submit($form, &$form_state) {
+  $node_revision = $form['#node_revision'];
+  $node_revision->revision = 1;
+  $node_revision->log = t('Copy of the revision from %date.', array('%date' => format_date($node_revision->revision_timestamp)));
+  if (module_exists('taxonomy')) {
+    $node_revision->taxonomy = array_keys($node_revision->taxonomy);
+  }
+
+  node_save($node_revision);
+
+  watchdog('content', '@type: reverted %title revision %revision.', array('@type' => $node_revision->type, '%title' => $node_revision->title, '%revision' => $node_revision->vid));
+  drupal_set_message(t('@type %title has been reverted back to the revision from %revision-date.', array('@type' => node_get_types('name', $node_revision), '%title' => $node_revision->title, '%revision-date' => format_date($node_revision->revision_timestamp))));
+  $form_state['redirect'] = 'node/' . $node_revision->nid . '/revisions';
+}
+
+/**
+ * Ask for confirmation of the deletion to prevent against CSRF attacks.
+ */
+function node_revision_delete_confirm($form_state, $node_revision) {
+  $form['#node_revision'] = $node_revision;
+  return confirm_form($form, t('Are you sure you want to delete the revision from %revision-date?', array('%revision-date' => format_date($node_revision->revision_timestamp))), 'node/' . $node_revision->nid . '/revisions', t('This action cannot be undone.'), t('Delete'), t('Cancel'));
+}
+
+function node_revision_delete_confirm_submit($form, &$form_state) {
+  $node_revision = $form['#node_revision'];
+  db_query("DELETE FROM {node_revision} WHERE nid = %d AND vid = %d", $node_revision->nid, $node_revision->vid);
+  node_invoke_nodeapi($node_revision, 'revision_delete');
+  watchdog('content', '@type: deleted %title revision %revision.', array('@type' => $node_revision->type, '%title' => $node_revision->title, '%revision' => $node_revision->vid));
+  drupal_set_message(t('Revision from %revision-date of @type %title has been deleted.', array('%revision-date' => format_date($node_revision->revision_timestamp), '@type' => node_get_types('name', $node_revision), '%title' => $node_revision->title)));
+  $form_state['redirect'] = 'node/' . $node_revision->nid;
+  if (db_result(db_query('SELECT COUNT(vid) FROM {node_revision} WHERE nid = %d', $node_revision->nid)) > 1) {
+    $form_state['redirect'] .= '/revisions';
+  }
+}
Index: modules/node_revision/node_revision.css
===================================================================
RCS file: modules/node_revision/node_revision.css
diff -N modules/node_revision/node_revision.css
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/node_revision/node_revision.css	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,5 @@
+/* $Id$ */
+
+td.revision-current {
+  background: #ffc;
+}
Index: modules/node_revision/node_revision.test
===================================================================
RCS file: modules/node_revision/node_revision.test
diff -N modules/node_revision/node_revision.test
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/node_revision/node_revision.test	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,87 @@
+<?php
+// $Id: node.test,v 1.8 2008/11/25 13:14:27 dries Exp $
+
+class NodeRevisionsTestCase extends DrupalWebTestCase {
+  protected $nodes;
+  protected $logs;
+
+  function getInfo() {
+    return array(
+      'name' => t('Node revisions'),
+      'description' => t('Create a node with revisions and test viewing, reverting, and deleting revisions.'),
+      'group' => t('Node'),
+    );
+  }
+
+  function setUp() {
+    parent::setUp();
+
+    // Create and login user.
+    $web_user = $this->drupalCreateUser(array('view revisions', 'revert revisions', 'edit any page content',
+                                               'delete revisions', 'delete any page content'));
+    $this->drupalLogin($web_user);
+
+    // Create initial node.
+    $node = $this->drupalCreateNode();
+    $settings = get_object_vars($node);
+    $settings['revision'] = 1;
+
+    $nodes = array();
+    $logs = array();
+
+    // Get original node.
+    $nodes[] = $node;
+
+    // Create three revisions.
+    $revision_count = 3;
+    for ($i = 0; $i < $revision_count; $i++) {
+      $logs[] = $settings['log'] = $this->randomName(32);
+
+      // Create revision with random title and body and update variables.
+      $this->drupalCreateNode($settings);
+      $node = node_load($node->nid); // Make sure we get revision information.
+      $settings = get_object_vars($node);
+
+      $nodes[] = $node;
+    }
+
+    $this->nodes = $nodes;
+    $this->logs = $logs;
+  }
+
+  /**
+   * Check node revision related opperations.
+   */
+  function testRevisions() {
+    $nodes = $this->nodes;
+    $logs = $this->logs;
+
+    // Get last node for simple checks.
+    $node = $nodes[3];
+
+    // Confirm the correct revision text appears on "view revisions" page.
+    $this->drupalGet("node/$node->nid/revisions/$node->vid/view");
+    $this->assertText($node->body, t('Correct text displays for version.'));
+
+    // Confirm the correct log message appears on "revisions overview" page.
+    $this->drupalGet("node/$node->nid/revisions");
+    foreach ($logs as $log) {
+      $this->assertText($log, t('Log message found.'));
+    }
+
+    // Confirm that revisions revert properly.
+    $this->drupalPost("node/$node->nid/revisions/{$nodes[1]->vid}/revert", array(), t('Revert'));
+    $this->assertRaw(t('@type %title has been reverted back to the revision from %revision-date.',
+                        array('@type' => 'Page', '%title' => $nodes[1]->title,
+                              '%revision-date' => format_date($nodes[1]->revision_timestamp))), t('Revision reverted.'));
+    $reverted_node = node_load($node->nid);
+    $this->assertTrue(($nodes[1]->body == $reverted_node->body), t('Node reverted correctly.'));
+
+    // Confirm revisions delete properly.
+    $this->drupalPost("node/$node->nid/revisions/{$nodes[1]->vid}/delete", array(), t('Delete'));
+    $this->assertRaw(t('Revision from %revision-date of @type %title has been deleted.',
+                        array('%revision-date' => format_date($nodes[1]->revision_timestamp),
+                              '@type' => 'Page', '%title' => $nodes[1]->title)), t('Revision deleted.'));
+    $this->assertTrue(db_result(db_query('SELECT COUNT(vid) FROM {node_revision} WHERE nid = %d and vid = %d', $node->nid, $nodes[1]->vid)) == 0, t('Revision not found.'));
+  }
+}
Index: modules/node_revision/node_revision.info
===================================================================
RCS file: modules/node_revision/node_revision.info
diff -N modules/node_revision/node_revision.info
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/node_revision/node_revision.info	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,9 @@
+; $Id$
+name = Node Revisions
+description = Allows revisioning of nodes and related properties.
+package = Core
+version = VERSION
+core = 7.x
+files[] = node_revision.module
+files[] = node_revision.pages.inc
+files[] = node_revision.install
Index: modules/node_revision/node_revision.module
===================================================================
RCS file: modules/node_revision/node_revision.module
diff -N modules/node_revision/node_revision.module
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/node_revision/node_revision.module	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,446 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Implements a version management that allows content to be revisioned.
+ */
+
+/**
+ * Implementation of hook_help().
+ */
+function node_revision_help($path, $arg) {
+  switch ($path) {
+    case 'admin/help#node_revision':
+      $output = '<p>' . t('The node_revision module allows content on your site to be revisioned.') . '</p>';
+      $output .= '<p>' . t('For more information, see the online handbook entry for <a href="@node">Node_revisions module</a>.', array('@node' => 'http://drupal.org/handbook/modules/node_revision/')) . '</p>';
+      return $output;
+  	case 'node/%/revisions':
+      return '<p>' . t('The revisions let you track differences between multiple versions of a post.') . '</p>';
+  }
+}
+
+/**
+ * Implementation of hook_init().
+ */
+function node_revision_init() {
+  drupal_add_css(drupal_get_path('module', 'node_revision') . '/node_revision.css');
+}
+
+/**
+ * Implementation of hook_theme().
+ */
+function node_revision_theme() {
+  return array(
+    'node_revision_log_message' => array(
+      'arguments' => array('log' => NULL),
+    ),
+  );
+}
+  
+/**
+ * Implementation of hook_perm().
+ */
+function node_revision_perm() {
+  $perms = array(
+    'view revisions' => array(
+      'title' => t('View revisions'),
+      'description' => t('View content revisions.'),
+    ),
+    'revert revisions' => array(
+      'title' => t('Revert revisions'),
+      'description' => t('Replace content with an older revision.'),
+    ),
+    'delete revisions' => array(
+      'title' => t('Delete revisions'),
+      'description' => t('Delete content revisions.'),
+    ),
+  );
+
+  foreach (node_get_types() as $type) {
+    if ($type->base == 'node_content') {
+      $perms += node_list_permissions($type);
+    }
+  }
+
+  return $perms;
+}
+
+/**
+ * Implementation of hook_hook_info().
+ */
+function node_revision_hook_info() {
+  return array(
+    'node_revision' => array(
+      'nodeapi' => array(
+        'revision_delete' => array(
+          'runs when' => t('After deleting a revision of a post'),
+        ),
+        'revision_load' => array(
+          'runs when' => t('After a node revision has been loaded.'),
+        ),
+      ),
+    ),
+  );
+}
+
+/**
+ * Implementation of hook_menu().
+ */
+function node_revision_menu() {
+  $items['node/%node/revisions'] = array(
+    'title' => 'Revisions',
+    'page callback' => 'node_revision_overview',
+    'page arguments' => array(1),
+    'access callback' => '_node_revision_access',
+    'access arguments' => array(3),
+    'weight' => 2,
+    'type' => MENU_LOCAL_TASK,
+  );
+  $items['node/%/revisions/%node_revision/view'] = array(
+    'title' => 'Revisions',
+    'page callback' => 'node_revision_show',
+    'page arguments' => array(3, TRUE),
+    'access callback' => '_node_revision_access',
+    'access arguments' => array(3),
+    'type' => MENU_CALLBACK,
+  );
+  $items['node/%/revisions/%node_revision/revert'] = array(
+    'title' => 'Revert to earlier revision',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('node_revision_revert_confirm', 3),
+    'access callback' => '_node_revision_access',
+    'access arguments' => array(3, 'update'),
+    'type' => MENU_CALLBACK,
+  );
+  $items['node/%/revisions/%node_revision/delete'] = array(
+    'title' => 'Delete earlier revision',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('node_revision_delete_confirm', 3),
+    'access callback' => '_node_revision_access',
+    'access arguments' => array(3, 'delete'),
+    'type' => MENU_CALLBACK,
+  );
+  return $items;
+}
+
+/**
+ * Menu item access callback - determine if revisioning is accessible.
+ */
+function _node_revision_access($node_revision, $op = 'view') {
+  static $access = array();
+  if (!isset($access[$node_revision->vid])) {
+    $node_current_revision = node_load($node_revision->nid);
+    $is_current_revision = $node_current_revision->vid == $node_revision->vid;
+    // There should be at least two revisions. If the vid of the given node
+    // and the vid of the current revision differs, then we already have two
+    // different revisions so there is no need for a separate database check.
+    // Also, if you try to revert to or delete the current revision, that's
+    // not good.
+    if ($is_current_revision && (db_result(db_query('SELECT COUNT(vid) FROM {node_revision} WHERE nid = %d', $node_revision->nid)) == 1 || $op == 'update' || $op == 'delete')) {
+      $access[$node->vid] = FALSE;
+    }
+    elseif (user_access('administer nodes')) {
+      $access[$node->vid] = TRUE;
+    }
+    else {
+      $map = array('view' => 'view revisions', 'update' => 'revert revisions', 'delete' => 'delete revisions');
+      // First check the user permission, second check the access to the
+      // current revision and finally, if the node passed in is not the current
+      // revision then access to that, too.
+      $access[$node->vid] = isset($map[$op]) && user_access($map[$op]) && node_access($op, $node_current_revision) && ($is_current_revision || node_access($op, $node_revision));
+    }
+  }
+  return $access[$node->vid];
+}
+
+/**
+ * Implementation of hook_form_alter().
+ */
+function node_revision_form_alter(&$form, $form_state, $form_id) {
+  if (!empty($form['#node_edit_form'])) {
+    // Add a log field if the "Create new revision" option is checked,
+    // or if the current user has the ability to check that option.
+    if (!empty($node->revision) || user_access('administer nodes')) {
+      $form['revision_information'] = array(
+        '#type' => 'fieldset',
+        '#title' => t('Revision information'),
+        '#collapsible' => TRUE,
+        // Collapsed by default when "Create new revision" is unchecked
+        '#collapsed' => !$node->revision,
+        '#weight' => 20,
+      );
+      $form['revision_information']['revision'] = array(
+        '#access' => user_access('administer nodes'),
+        '#type' => 'checkbox',
+        '#title' => t('Create new revision'),
+        '#default_value' => $node->revision,
+      );
+      $form['revision_information']['log'] = array(
+        '#type' => 'textarea',
+        '#title' => t('Log message'),
+        '#rows' => 2,
+        '#description' => t('An explanation of the additions or updates being made to help other authors understand your motivations.'),
+      );
+    }
+  }
+  
+  // Also add an option to the workflow section of the node settings form.
+  if ($form_id == 'node_type_form' && isset($form['identity']['type'])) {
+    $form['workflow']['node_options']['#options']['revision'] = t('Create new revision');
+  } 
+}
+
+/**
+ * Implementation of hook_user_delete().
+ */
+function node_revision_user_delete(&$edit, &$user) {
+  db_query('UPDATE {node_revision} SET uid = 0 WHERE uid = %d', $user->uid);
+}
+
+/**
+ * @defgroup nodeapi hook_nodeapi implementations.
+ * @{
+ */
+
+/**
+ * Implementation of hook_nodeapi_prepare().
+ */
+function node_revision_nodeapi_prepare(&$node, $teaser, $page) {
+  // Always use the default revision setting.
+  $node->revision = in_array('revision', $node_options);
+}
+
+/**
+ * Implementation of hook_nodeapi_load().
+ */
+function node_revision_nodeapi_load(&$node, $teaser, $page) {
+  // Nodes should always be preset with the default revision setting.
+  $node->revision = in_array('revision', variable_get('node_options_'. $node->type, array('status', 'promote')));
+}
+
+/**
+ * Implementation of hook_nodeapi_presave().
+ */
+function node_revision_nodeapi_presave(&$node, $teaser, $page) {
+	// Apply filters to some default node fields:
+	if (empty($node->nid)) {
+    // When inserting a node, $node->log must be set because
+	  // {node_revision}.log does not (and cannot) have a default
+	  // value.  If the user does not have permission to create
+	  // revisions, however, the form will not contain an element for
+	  // log so $node->log will be unset at this point.
+	  if (!isset($node->log)) {
+	    $node->log = '';
+	  }
+  }
+  elseif (!empty($node->revision)) {
+    $node->old_vid = $node->vid;
+  }
+  elseif (empty($node->log)) {
+	  // When updating a node, avoid clobbering an existing log entry with an empty one.
+    unset($node->log);
+	}
+}
+
+/**
+ * Implementation of hook_nodeapi_insert().
+ */
+function node_revision_nodeapi_insert(&$node, $teaser, $page) {
+  // Generate the node_revision table query.
+	node_revision_save($node, $user->uid);
+  db_query('UPDATE {node} SET vid = %d WHERE nid = %d', $node->vid, $node->nid);
+}
+
+/**
+ * Implementation of hook_nodeapi_update().
+ */
+function node_revision_nodeapi_update(&$node, $teaser, $page) {
+  // Generate the node_revision table query.
+	if (!empty($node->revision)) {
+    node_revision_save($node, $user->uid);
+  }
+  else {
+    node_revision_save($node, $user->uid, 'vid');
+    db_query('UPDATE {node} SET vid = %d WHERE nid = %d', $node->vid, $node->nid);
+  }
+}
+
+/**
+ * Implementation of hook_nodeapi_delete().
+ */
+function node_revision_nodeapi_delete(&$node, $teaser, $page) {
+  db_query('DELETE FROM {node_revision} WHERE nid = %d', $node->nid);
+}
+
+/**
+ * Implementation of hook_nodeapi_blogapi_new().
+ */
+function node_revision_nodeapi_blogapi_new(&$node, $teaser, $page) {
+  $node['revision'] = in_array('revision', variable_get('node_options_' . $node['type'], array('status', 'promote')));
+}
+
+/**
+ * @} End of "defgroup nodeapi".
+ */
+
+/**
+ * Load node_revision objects from the database.
+ *
+ * This function should be used whenever you need to load more than one
+ * node revision from the database.
+ * Note that node revisions are not cached.
+ *
+ * @param $vids
+ *   An array of node_revision IDs.
+ * @param $conditions
+ *   An array of conditions on the {node} table in the form 'field' => $value.
+ * @param $reset
+ *   Whether to reset the internal node_load cache.
+ *
+ * @return
+ *   An array of node objects indexed by nid.
+ */
+function node_revision_load_multiple($vids = array(), $conditions = array(), $reset = FALSE) {
+  $node_revisions = array();
+
+  // Create a new variable which is either a prepared version of the $nids
+  // array for later comparison with the node cache, or FALSE if no $nids were
+  // passed. The $nids array is reduced as items are loaded from cache, and we
+  // need to know if it's empty for this reason to avoid querying the database
+  // when all requested nodes are loaded from cache.
+  $passed_vids = !empty($vids) ? array_flip($vids) : FALSE;
+
+  // Load any node_revisions from the database.
+  $query = db_select('node_revision', 'r');
+
+  $query->join('users', 'u', 'u.uid = r.uid');
+
+  // Add all fields from the {node_revision} table.
+  $node_revision_fields = drupal_schema_fields_sql('node_revision');
+
+  // Add fields from the {users} table.
+  $user_fields = array('name', 'picture', 'data');
+  $query->fields('u', $user_fields);
+
+  if ($vids) {
+    $query->condition('v.nid', $vids, 'IN');
+  }
+  if ($conditions) {
+    foreach ($conditions as $field => $value) {
+      $query->condition('r.' . $field, $value);
+    }
+  }
+  $queried_node_revisions = $query->execute()->fetchAllAssoc('vid');
+
+  // Pass all nodes loaded from the database through the node type specific
+  // callbacks and hook_nodeapi_load(), then add them to the internal cache.
+  if (!empty($queried_node_revisions)) {
+    // Create an array of nodes for each content type and pass this to the
+    // node type specific callback.
+    $typed_node_revisions = array();
+    foreach ($queried_node_revisions as $vid => $node_revision) {
+      $typed_node_revisions[$node_revision->type][$vid] = $node_revision;
+    }
+
+    // Call node type specific callbacks on each typed array of nodes.
+    foreach ($typed_node_revisions as $type => $node_revisions_of_type) {
+      if (node_hook($type, 'node_revision_load')) {
+        $function = node_get_types('base', $type) . '_node_revision_load';
+        $function($node_revisions_of_type);
+      }
+    }
+
+    // Call hook_nodeapi_load(), pass the node types so modules can return early
+    // if not acting on types in the array.
+    foreach (module_implements('nodeapi_revision_load') as $module) {
+      $function = $module . '_nodeapi_revision_load';
+      $function($queried_node_revisions, array_keys($typed_node_revisions));
+    }
+    $node_revisions += $queried_node_revisions;
+  }
+
+  // Ensure that the returned array is ordered the same as the original $nids
+  // array if this was passed in and remove any invalid nids.
+  if ($passed_vids) {
+    // Remove any invalid nids from the array.
+    $passed_vids = array_intersect_key($passed_vids, $node_revisions);
+    foreach ($node_revisions as $node_revision) {
+      $passed_vids[$node_revision->vid] = $node_revision;
+    }
+    $node_revisions = $passed_vids;
+  }
+
+  return $node_revisions;
+}
+
+/**
+ * Load a node_revision object from the database.
+ *
+ * @param $vid
+ *   The revision ID.
+ * @param $reset
+ *   Whether to reset the internal node_load cache.
+ *
+ * @return
+ *   A fully-populated node object.
+ */
+function node_revision_load($vid, $reset = FALSE) {
+  $node_revision = node_revision_load_multiple(array($vid), NULL, $reset);
+
+  return $node_revision ? $node_revision[$vid] : FALSE;
+}
+
+/**
+ * Save a revision with the uid of the current user.
+ *
+ * Node is taken by reference, becuse drupal_write_record() updates the
+ * $node with the revision id, and we need to pass that back to the caller.
+ */
+function node_revision_save(&$node, $uid, $update = NULL) {
+  $temp_uid = $node->uid;
+  $node->uid = $uid;
+  if (isset($update)) {
+    drupal_write_record('node_revision', $node, $update);
+  }
+  else {
+    drupal_write_record('node_revision', $node);
+  }
+  $node->uid = $temp_uid;
+}
+
+/**
+ * Generate a page displaying a single node revision.
+ * 
+ * Optionally change the title to show revision information
+ * and pass through to node_view(). Don't show comments and
+ * don't update the history table as node_show() does.  
+ */
+function node_revision_show($node_revision, $message = FALSE) {
+  if ($message) {
+    drupal_set_title(t('Revision of %title from %date', array('%title' => $node_revision->title, '%date' => format_date($node_revision->revision_timestamp))), PASS_THROUGH);
+  }
+  return node_view($node_revision, FALSE, TRUE);
+}
+
+/**
+ * Return a list of all the existing revision numbers.
+ */
+function node_revision_list($node) {
+  $revisions = array();
+  $result = db_query('SELECT r.vid, r.title, r.log, r.uid, n.vid AS current_vid, r.timestamp, u.name FROM {node_revision} r LEFT JOIN {node} n ON n.vid = r.vid INNER JOIN {users} u ON u.uid = r.uid WHERE r.nid = %d ORDER BY r.timestamp DESC', $node->nid);
+  while ($revision = db_fetch_object($result)) {
+    $revisions[$revision->vid] = $revision;
+  }
+  return $revisions;
+}
+
+/**
+ * Theme a log message.
+ *
+ * @ingroup themeable
+ */
+function theme_node_revision_log_message($log) {
+  return '<div class="log"><div class="title">' . t('Log') . ':</div>' . $log . '</div>';
+}
+
