=== modified file 'modules/system/system.install'
--- modules/system/system.install       2007-08-22 08:40:04 +0000
+++ modules/system/system.install       2007-08-25 14:58:22 +0000
@@ -3373,10 +3322,102 @@ function system_update_6020() {
 
 function system_update_6021() {
   $ret = array();
-  // TODO - menu module updates. These need to happen before we do the menu_rebuild
-
-  menu_rebuild();
-  return $ret;
+  // Multi-part update
+  if (!isset($_SESSION['system_update_6021'])) {
+    $_SESSION['system_update_6021'] = 0;
+    $_SESSION['system_update_6021_max'] = db_result(db_query('SELECT COUNT(*) FROM {menu}'));
+    $_SESSION['menu_menu_map'] = array(1 => 'navigation');
+    // 0 => FALSE is for new menus, 1 => FALSE is for the navigation.
+    $_SESSION['menu_item_map'] = array(0 => FALSE, 1 => FALSE);
+    foreach (array('primary', 'secondary') as $menu) {
+      if ($mid = variable_get('menu_'. $menu .'_menu', 0)) {
+        $_SESSION['menu_menu_map'][$mid] = $menu .'-links';
+        $_SESSION['menu_item_map'][$mid] = FALSE;
+      }
+    }
+    switch ($GLOBALS['db_type']) {
+      case 'mysql': case 'mysqli':
+        update_sql('ALTER TABLE {menu} ADD converted tinyint unsigned default 0 NOT NULL');
+        break;
+      case 'pgsql':
+        db_add_column($ret, 'menu', 'converted', 'smallint', array('default' => 0, 'not null' => TRUE));
+        break;
+    }
+    $table = array(
+      'fields' => array(
+        'menu_name'   => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''),
+        'title'       => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''),
+        'description' => array('type' => 'text', 'not null' => FALSE),
+      ),
+      'primary key' => array('menu_name'),
+    );
+    db_create_table($ret, 'menu_custom', $table);
+  }
+
+  $limit = 20;
+  while ($limit-- && ($item = db_fetch_array(db_query_range('SELECT * FROM {menu} WHERE converted = 0', 0, 1)))) {
+    // If it's not a menu...
+    if ($item['pid']) {
+      // Let's climb up until we find an item with a converted parent.
+      while (!isset($_SESSION['menu_item_map'][$item['pid']])) {
+        $item = db_fetch_array(db_query('SELECT * FROM {menu} WHERE mid = %d', $item['pid']));
+      }
+    }
+    // We need to recheck because item might have changed.
+    if ($item['pid']) {
+      // Fill the new fields.
+      $item['link_title'] = $item['title'];
+      $item['link_path'] = $item['path'];
+      // We know the parent is already set. If it's not FALSE then it's an item.
+      if ($_SESSION['menu_item_map'][$item['pid']]) {
+        // The new menu system parent link id.
+        $item['plid'] = $_SESSION['menu_item_map'][$item['pid']]['mlid'];
+        // The new menu system menu name.
+        $item['menu_name'] = $_SESSION['menu_item_map'][$item['pid']]['menu_name'];
+      }
+      else {
+        // This a top level element.
+        $item['plid'] = 0;
+        // The menu name is stored among the menus.
+        $item['menu_name'] = $_SESSION['menu_menu_map'][$item['pid']];
+      }
+      // Is the element visible in the menu block?
+      $item['hidden'] = !($item['type'] & MENU_VISIBLE_IN_TREE);
+      // Is it a custom(ized) element?
+      if ($item['type' ] & (MENU_CREATED_BY_ADMIN | MENU_MODIFIED_BY_ADMIN)) {
+        $item['module'] = 'menu';
+        $item['customized'] = TRUE;
+      }
+      else {
+        $item['module'] = 'system';
+        $item['customized'] = FALSE;
+      }
+      // Save the link.
+      menu_link_save($item);
+      $_SESSION['menu_item_map'][$item['mid']] = $item;
+    }
+    elseif (!isset($_SESSION['menu_menu_map'][$item['mid']])) {
+      $item['menu_name'] = preg_replace('/[^a-zA-Z0-9]/' , '-', strtolower($item['title']));
+      $i = 0;
+      while (db_result(db_query("SELECT menu_name FROM {menu_custom} WHERE menu_name = 'menu-%s'", $item['menu_name']))) {
+        $item['menu_name'] .= $i++;
+      }
+      $form_state = array('values' => $item);
+      // We have a batch running, drupal_execute won't work. And we do not 
+      // validate anyways.
+      menu_edit_menu_submit(array('#insert' => TRUE), $form_state);
+      $_SESSION['menu_menu_map'][$item['mid']] = $item['menu_name'];
+      $_SESSION['menu_item_map'][$item['mid']] = FALSE;
+    }
+    db_query('UPDATE {menu} SET converted = 1 WHERE mid  = %d', $item['mid']);
+    $_SESSION['system_update_6021']++;
+  }
+  if ($_SESSION['system_update_6021'] == $_SESSION['system_update_6021_max']) {
+    unset($_SESSION['system_update_6021'], $_SESSION['system_update_6021_max'], $_SESSION['menu_menu_map'], $_SESSION['menu_item_map']);
+    menu_rebuild();
+    return array();
+  }
+  return array('#finished' => $_SESSION['system_update_6021'] / $_SESSION['system_update_6021_max']);
 }
 
 /**
