Index: trunk/cgi-bin/IPDB.pm
===================================================================
--- trunk/cgi-bin/IPDB.pm	(revision 732)
+++ trunk/cgi-bin/IPDB.pm	(revision 733)
@@ -25,5 +25,5 @@
 @EXPORT_OK    = qw(
 	%disp_alloctypes %list_alloctypes %def_custids @citylist @poplist
-	%IPDBacl %aclmsg %rpcacl $maxfcgi
+	%IPDBacl %merge_display %aclmsg %rpcacl $maxfcgi
 	$errstr
 	&initIPDBGlobals &connectDB &finish &checkDBSanity
@@ -41,5 +41,5 @@
 %EXPORT_TAGS	= ( ALL => [qw(
 		%disp_alloctypes %list_alloctypes %def_custids @citylist @poplist
-		%IPDBacl %aclmsg %rpcacl $maxfcgi
+		%IPDBacl %merge_display %aclmsg %rpcacl $maxfcgi
 		$errstr
 		&initIPDBGlobals &connectDB &finish &checkDBSanity
@@ -67,4 +67,12 @@
 # Mapping hash for pooltype -> poolip-as-netblock conversions
 my %poolmap = (sd => 'en', cd => 'cn', dp => 'cn', mp => 'cn', wp => 'cn', ld => 'in', ad => 'in', bd => 'in');
+
+# Friendly display strings for merge scopes
+our %merge_display = (
+	keepall	  => "Keep mergeable allocations as suballocations of new block",
+	mergepeer => "Keep suballocations of mergeable allocations",
+	clearpeer => "Keep only suballocations of the selected block",
+	clearall  => "Clear all suballocations"
+	);
 
 # mapping table for functional-area => error message
@@ -916,4 +924,6 @@
   my $btype = shift || 'a';
   $btype = 'a' if $btype !~/^[af]$/;
+  my $incsub = shift;
+  $incsub = 1 if !defined($incsub);
 
   my $sql;
@@ -929,14 +939,18 @@
   } else {
 ##fixme:  Not sure about the casting hackery in "SELECT ?::integer AS id", but it works as intended
-    my $ret = $dbh->selectall_arrayref(q(
-	SELECT cidr,id FROM freeblocks
-	WHERE parent_id IN (SELECT ?::integer AS id UNION
-		SELECT id FROM allocations WHERE parent_id = ? AND cidr <<= ?
-	) AND cidr <<= ?
-	ORDER BY cidr
-	),
-	{ Slice => {} }, $parent, $parent, $newblock, $newblock) or print $dbh->errstr;
+    my @dbargs = ($parent, "$newblock");
+    push @dbargs, $parent, $newblock if $incsub;
+    my $ret = $dbh->selectall_arrayref(q{
+        SELECT cidr,id FROM freeblocks
+        WHERE parent_id IN (
+      }.($incsub ? "SELECT id FROM allocations WHERE parent_id = ? AND cidr <<= ? UNION " : '').q{
+	        SELECT ?::integer AS id
+            ) AND cidr <<= ?
+        ORDER BY cidr
+      },
+	{ Slice => {} }, @dbargs);
     return $ret;
   }
+  return;
 } # end listForMerge()
 
@@ -2003,4 +2017,5 @@
 # Takes a "base" block ID and a hash with a mask length and a scope argument to decide
 # how much existing allocation data to delete.
+# Returns a list starting with the new merged block, then the merged allocations with comment
 ## Merge scope:
 # Merge to container
@@ -2064,5 +2079,11 @@
   $args{newtype} = $binfo->{type} if !$args{newtype};
   # if the "primary" block being changed is a master, it must remain one.
-  $args{newtype} = 'mm' if $binfo->{type} eq 'mm';
+  # Also force the scope, since otherwise things get ugly.
+  if ($binfo->{type} eq 'mm') {
+    $args{newtype} = 'mm';
+    # don't want to make a peer master a sub of the existing one;  too many special cases go explodey,
+    # but want to retain all other allocations
+    $args{scope} = 'mergepeer';
+  }
   my ($newcontainerclass) = ($args{newtype} =~ /^(.).$/);
 
@@ -2123,5 +2144,6 @@
       ## Container
 
-      # In case of merging a master block
+      # In case of merging a master block.  Somewhat redundant with calls to $fbreparentsth,
+      # but not *quite* entirely.
       my $mfbsth = $dbh->prepare("UPDATE freeblocks SET master_id = ? WHERE master_id = ?");
 
@@ -2131,16 +2153,22 @@
         # and now retrieve the new parent ID
         ($prime) = $dbh->selectrow_array("SELECT currval('allocations_id_seq')");
+        # snag the new parent info for the return list
+        push @retlist, { block => "$newblock", type => $disp_alloctypes{$args{newtype}}, id => $prime };
         # Reparent the free blocks in the new block
         $fbreparentsth->execute($prime, $binfo->{master_id}, $binfo->{city}, $newcontainerclass, $binfo->{vrf},
             $binfo->{parent_id}, $newblock);
         # keep existing allocations (including the original primary), just push them down a level
-        while (my ($pcidr,$peer_id,$ptype,$m_id) = $peersth->fetchrow_array) {
+        while (my ($peercidr, $peer_id, $peertype, $m_id) = $peersth->fetchrow_array) {
           $reparentsth->execute($prime, $binfo->{master_id}, $peer_id);
           # Fix up master_id on free blocks if we're merging a master block
-          $mfbsth->execute($binfo->{master_id}, $m_id) if $ptype eq 'mm';
+          $mfbsth->execute($binfo->{master_id}, $m_id) if $peertype eq 'mm';
+          # capture block for return
+          push @retlist, { block => $peercidr, mtype => $disp_alloctypes{$peertype} };
         }
 
       } elsif ($args{scope} =~ /^clear/) {
         # clearpeer and clearall share a starting point
+        # snag the new parent info for the return list
+        push @retlist, { block => "$newblock", type => $disp_alloctypes{$args{newtype}}, id => $prime };
         # update the primary allocation info
         $dbh->do("UPDATE allocations SET cidr = ?, type = ? WHERE id = ?", undef, ($newblock, $args{newtype}, $prime) );
@@ -2153,6 +2181,6 @@
               $binfo->{master_id});
         }
-        # delete the peers
-        while (my ($pcidr,$peer_id) = $peersth->fetchrow_array) {
+        # delete the peers.
+        while (my ($peercidr, $peer_id, $peertype, $m_id) = $peersth->fetchrow_array) {
           next if $peer_id == $prime;
           # push existing allocations down a level before deleting,
@@ -2163,5 +2191,7 @@
           # aren't special cases fun?
           $dbh->do("INSERT INTO freeblocks (cidr,routed,parent_id,master_id) values (?,?,?,?)",
-                undef, ($pcidr, 'm', $prime, $prime) ) if $binfo->{type} eq 'mm';
+              undef, ($peercidr, 'm', $prime, $prime) ) if $binfo->{type} eq 'mm';
+          # capture block for return
+          push @retlist, { block => $peercidr, mtype => $disp_alloctypes{$peertype} };
         }
         if ($args{scope} eq 'clearall') {
@@ -2182,4 +2212,6 @@
       } elsif ($args{scope} eq 'mergepeer') { # should this just be an else?
         # Default case.  Merge "peer" blocks, but keep all suballocations
+        # snag the new parent info for the return list
+        push @retlist, {block => "$newblock", type => $disp_alloctypes{$args{newtype}}, id => $prime};
         my $substh = $dbh->prepare("UPDATE allocations SET parent_id = ? WHERE parent_id = ?");
         my $delsth = $dbh->prepare("DELETE FROM allocations WHERE id = ?");
@@ -2202,7 +2234,9 @@
               $binfo->{master_id}) if $peertype =~ /.[enr]/;
           # Convert pool IPs into allocations or aggregated free blocks
-          _poolToAllocations($dbh, $peerfull, $pinfo, newparent => $prime) if $peertype =~ /.[dp];
+          _poolToAllocations($dbh, $peerfull, $pinfo, newparent => $prime) if $peertype =~ /.[dp]/;
           # Fix up master_id on free blocks if we're merging a master block
           $mfbsth->execute($binfo->{master_id}, $m_id) if $peertype eq 'mm';
+          # capture block for return
+          push @retlist, { block => $peercidr, mtype => $disp_alloctypes{$peertype} };
         } # merge peers
         # update the primary allocation info.  Do this last so we don't stomp extra data-retrieval in the loop above
Index: trunk/cgi-bin/main.cgi
===================================================================
--- trunk/cgi-bin/main.cgi	(revision 732)
+++ trunk/cgi-bin/main.cgi	(revision 733)
@@ -1221,4 +1221,10 @@
   $page->param(typelist => getTypeList($ip_dbh, 'n', $binfo->{type}));  # down the rabbit hole we go...
 
+  # Strings for scope;  do this way so we don't have to edit them many places
+  $page->param(vis_keepall => $merge_display{keepall});
+  $page->param(vis_mergepeer => $merge_display{mergepeer});
+  $page->param(vis_clearpeer => $merge_display{clearpeer});
+  $page->param(vis_clearall => $merge_display{clearall});
+
   # Tree navigation
   my $crumbs = getBreadCrumbs($ip_dbh, $binfo->{parent_id});
@@ -1265,13 +1271,5 @@
   $page->param(mergefree => $fb_list);
 
-##fixme:  push this up the stack somewhere so the labels can be fed to the relevant templates when/as needed
-  # scope
-  my %merge_friendly = (
-	keepall   => "Keep mergeable allocations as suballocations of new block",
-	mergepeer => "Keep suballocations of mergeable allocations",
-	clearpeer => "Keep only suballocations of $binfo->{block}",
-	clearall  => "Clear all suballocations"
-    );
-  $page->param(vis_scope => $merge_friendly{$webvar{scope}});
+  $page->param(vis_scope => $merge_display{$webvar{scope}});
   $page->param(scope => $webvar{scope});
 } # confMerge()
