Index: includes/menu.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/menu.inc,v
retrieving revision 1.176
diff -u -p -r1.176 menu.inc
--- includes/menu.inc	5 Jun 2007 12:13:20 -0000	1.176
+++ includes/menu.inc	6 Jun 2007 02:08:25 -0000
@@ -1217,7 +1217,7 @@ function _menu_navigation_links_rebuild(
   foreach ($menu as $path => $item) {
     $item = _menu_link_build($item);
     // We add nonexisting items.
-    if ($item['_visible'] && !db_result(db_query("SELECT COUNT(*) FROM {menu_links} WHERE menu_name = '%s' AND link_path = '%s'", $item['menu_name'], $item['link_path']))) {
+    if ($item['_visible']) {
       $menu_links[$path] = $item;
       $sort[$path] = $item['_number_parts'];
     }
@@ -1227,7 +1227,14 @@ function _menu_navigation_links_rebuild(
     array_multisort($sort, SORT_NUMERIC, $menu_links);
 
     foreach ($menu_links as $item) {
-      menu_link_save($item);
+      $existing_item = db_fetch_array(db_query("SELECT mlid, customized FROM {menu_links} WHERE menu_name = '%s' AND link_path = '%s' AND module = 'system'", $item['menu_name'], $item['link_path']));
+      if ($existing_item) {
+        $item['mlid'] = $existing_item['mlid'];
+        if (!$existing_item || !$existing_item['customized']) {
+          menu_link_save($item);
+        }
+      }
+
     }
   }
   $placeholders = implode(', ', array_fill(0, count($menu), "'%s'"));
@@ -1310,19 +1317,13 @@ function menu_link_save(&$item) {
     'expanded' => 0,
     'options' => array(),
     'module' => 'menu',
+    'customized' => 0,
   );
   $menu_name = $item['menu_name'];
   $existing_item = FALSE;
   if (isset($item['mlid'])) {
     $existing_item = db_fetch_array(db_query("SELECT * FROM {menu_links} WHERE mlid = %d", $item['mlid']));
   }
-  else {
-    $existing_item = db_fetch_array(db_query("SELECT * FROM {menu_links} WHERE menu_name = '%s' AND link_path = '%s'", $menu_name, $item['link_path']));
-  }
-
-  if ($existing_item) {
-    $item['mlid'] = $existing_item['mlid'];
-  }
 
   // Find the parent - it must be in the same menu.
   if (isset($item['plid'])) {
@@ -1343,21 +1344,22 @@ function menu_link_save(&$item) {
   else {
     $item['plid'] = $parent['mlid'];
   }
-  db_query("INSERT INTO {menu_links} (
-    menu_name, plid, link_path,
-    hidden, external, has_children,
-    expanded, weight,
-    module, link_title, options) VALUES (
-    '%s', %d, '%s',
-    %d, %d, %d,
-    %d, %d,
-    '%s', '%s', '%s')",
-    $item['menu_name'], $item['plid'], $item['link_path'],
-    $item['hidden'], $item['_external'], $item['has_children'],
-    $item['expanded'], $item['weight'],
-    $item['module'],  $item['link_title'], serialize($item['options']));
-  $item['mlid'] = db_last_insert_id('menu_links', 'mlid');
-
+  if (!$existing_item) {
+    db_query("INSERT INTO {menu_links} (
+       menu_name, plid, link_path,
+      hidden, external, has_children,
+      expanded, weight,
+      module, link_title, options) VALUES (
+      '%s', %d, '%s',
+      %d, %d, %d,
+      %d, %d,
+      '%s', '%s', '%s')",
+      $item['menu_name'], $item['plid'], $item['link_path'],
+      $item['hidden'], $item['_external'], $item['has_children'],
+      $item['expanded'], $item['weight'],
+      $item['module'],  $item['link_title'], serialize($item['options']));
+    $item['mlid'] = db_last_insert_id('menu_links', 'mlid');
+  }
 
   if (!$item['plid']) {
     $item['p1'] = $item['mlid'];
Index: modules/menu/menu.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/menu/menu.module,v
retrieving revision 1.115
diff -u -p -r1.115 menu.module
--- modules/menu/menu.module	5 Jun 2007 09:15:02 -0000	1.115
+++ modules/menu/menu.module	6 Jun 2007 02:08:25 -0000
@@ -242,7 +242,7 @@ function menu_edit_item(&$form_state, $t
   }
   else {
     // This is an add form.
-    // The mlid argument (if set) will be the default pid to use.
+    // The $id argument is the menu_name
     $item = array('mlid' => 0, 'plid' => 0, 'menu_name' => $id, 'weight' => 0, 'link_title' => '', 'link_path' => '', 'options' => array(), 'module' => 'menu', 'expanded' => 0, 'hidden' => 0, 'has_children' => 0);
   }
   foreach (array('link_path', 'mlid', 'module', 'hidden', 'menu_name', 'has_children') as $key) {
@@ -539,8 +539,8 @@ function menu_nodeapi($node, $op) {
         // Deliberate no break.
       case 'insert':
       case 'update':
-        if ($item['delete']) {
-          _menu_delete_item($item);
+        if (!empty($item['delete'])) {
+          menu_link_delete($item);
         }
         else {
           $item['link_path'] = "node/$node->nid";
Index: modules/system/system.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.install,v
retrieving revision 1.120
diff -u -p -r1.120 system.install
--- modules/system/system.install	5 Jun 2007 12:13:22 -0000	1.120
+++ modules/system/system.install	6 Jun 2007 02:08:26 -0000
@@ -3288,24 +3288,158 @@ function system_update_6019() {
 function system_update_6020() {
   $ret = array();
 
-  $schema['menu_router'] = drupal_get_schema_unprocessed('system', 'menu_router');
-  $schema['menu_links'] = drupal_get_schema_unprocessed('system', 'menu_links');
+  $schema['menu_router'] = array(
+    'fields' => array(
+      'path'             => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''),
+      'load_functions'   => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''),
+      'to_arg_functions' => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''),
+      'access_callback'  => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''),
+      'access_arguments' => array('type' => 'text', 'not null' => FALSE),
+      'page_callback'    => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''),
+      'page_arguments'   => array('type' => 'text', 'not null' => FALSE),
+      'fit'              => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
+      'number_parts'     => array('type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'small'),
+      'tab_parent'       => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''),
+      'tab_root'         => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''),
+      'title'            => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''),
+      'title_callback'   => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''),
+      'title_arguments'  => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''),
+      'type'             => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
+      'block_callback'   => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''),
+      'description'      => array('type' => 'text', 'not null' => TRUE),
+      'position'         => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''),
+      'weight'           => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
+      'file'             => array('type' => 'text', 'size' => 'medium')
+    ),
+    'indexes' => array(
+      'fit'        => array('fit'),
+      'tab_parent' => array('tab_parent')
+    ),
+    'primary key' => array('path'),
+  );
+
+  $schema['menu_links'] = array(
+    'fields' => array(
+      'menu_name'    => array('type' => 'varchar', 'length' => 64, 'not null' => TRUE, 'default' => ''),
+      'mlid'         => array('type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE),
+      'plid'         => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0),
+      'link_path'    => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''),
+      'router_path'  => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''),
+      'hidden'       => array('type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'small'),
+      'external'     => array('type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'small'),
+      'has_children' => array('type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'small'),
+      'expanded'     => array('type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'small'),
+      'weight'       => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
+      'depth'        => array('type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'small'),
+      'customized'   => array('type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'small'),
+      'p1'           => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0),
+      'p2'           => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0),
+      'p3'           => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0),
+      'p4'           => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0),
+      'p5'           => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0),
+      'p6'           => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0),
+      'module'       => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => 'system'),
+      'link_title'   => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''),
+      'options'      => array('type' => 'text', 'not null' => FALSE)
+    ),
+    'indexes' => array(
+      'expanded_children' => array('expanded', 'has_children'),
+      'menu_name_path' => array('menu_name', 'link_path'),
+      'plid'=> array('plid'),
+      'parents' => array('p1', 'p2', 'p3', 'p4', 'p5'),
+      'router_path' => array('router_path'),
+    ),
+    'primary key' => array('mlid'),
+  );
+
   _drupal_initialize_schema('system', $schema);
   $ret = array();
   foreach ($schema as $table) {
     db_create_table($ret, $table);
   }
+
   return $ret;
 }
 
 function system_update_6021() {
   $ret = array();
-  // TODO - menu module updates. These need to happen before we do the menu_rebuild
+  // We should die a horrible death here if this query fails.
+  $menu = unserialize(db_result(db_query("SELECT data FROM {cache_menu} WHERE cid LIKE '1:%%'")));
+  $new_menu = menu_router_build(TRUE);
+  if ($menu && module_exists('menu')) {
+    $items = $menu['items'];
+    drupal_install_schema('menu');
+    $menu_names = array();
+    $system_menus = array(
+      1 => 'navigation',
+      variable_get('menu_primary_menu', 2) => 'primary-links',
+      variable_get('menu_secondary_menu', 0) => 'secondary-links',
+    );
+    // These are the root menus.
+    foreach ($items[0]['children'] as $mid) {
+      $item = $items[$mid];
+      if (isset($system_menus[$mid])) {
+        $menu_name = $system_menus[$mid];
+      }
+      else {
+        $title = $item['title'];
+        $menu_name = preg_replace('[^a-z0-9]', '-', $title);
+        if (isset($menu_names[$menu_name])) {
+          $counter = 0;
+          while (isset($menu_names[$menu_name . ++$counter]));
+          $menu_name = $menu_name . $counter;
+        }
+        $description = db_result(db_query('SELECT description FROM {menu} WHERE mid = %d', $mid));
+        db_query("INSERT INTO {menu_custom} (menu_name, title, description) VALUES ('%s', '%s', '%s')", $menu_name, $title, $description);
+      }
+      $menu_names[$menu_name] = $mid;
+      if (isset($item['children'])) {
+        foreach ($item['children'] as $child_mid) {
+          _system_update_6021($items, $menu_name, $child_mid);
+        }
+      }
+      menu_cache_clear($menu_name);
+    }
+    array_flip($menu_names);
+    $menu_parent_items = variable_get('menu_parent_items', NULL);
+    if (isset($menu_parent_items)) {
+      if ($menu_parent_items) {
+        variable_set('menu_parent_items', $menu_names[$menu_parent_items]);
+      }
+      else {
+        drupal_set_message(t('The menu name for on-the-fly creation of menu links has been set the navigation'), 'warning');
+        variable_set('menu_parent_items', 'navigation');
+      }
+    }
+  }
+  _menu_navigation_links_rebuild($new_menu);
 
-  menu_rebuild();
   return $ret;
 }
 
+function _system_update_6021($items, $menu_name, $mid) {
+  static $map;
+  $item = $items[$mid];
+  if ($item['type'] & MENU_VISIBLE_IN_BREADCRUMB) {
+    $item = _menu_link_build($item);
+    $item['menu_name'] = $menu_name;
+    $item['plid'] = isset($map[$item['pid']]) ? $map[$item['pid']] : 0;
+    if ($mid > 0) {
+      $item['description'] = db_result(db_query('SELECT description FROM {menu} WHERE mid = %d', $mid));
+      if ($item['type'] & MENU_CREATED_BY_ADMIN) {
+        $item['module'] = 'menu';
+      }
+    }
+    $item['expanded'] = (bool)($item['type'] & 0x0100);
+    $map[$mid] = menu_link_save($item);
+  }
+  if (isset($item['children'])) {
+    foreach ($item['children'] as $child_mid) {
+      _system_update_6021($items, $menu_name, $child_mid);
+    }
+  }
+}
+
 /**
  * Update files tables to associate files to a uid by default instead of a nid.
  * Rename file_revisions to upload since it should only be used by the upload
Index: modules/system/system.schema
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.schema,v
retrieving revision 1.5
diff -u -p -r1.5 system.schema
--- modules/system/system.schema	5 Jun 2007 09:33:57 -0000	1.5
+++ modules/system/system.schema	6 Jun 2007 02:08:26 -0000
@@ -110,6 +110,7 @@ function system_schema() {
       'expanded'     => array('type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'small'),
       'weight'       => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
       'depth'        => array('type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'small'),
+      'customized'   => array('type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'small'),
       'p1'           => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0),
       'p2'           => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0),
       'p3'           => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0),
