Hi all,

I have to compare two ldif files and I use the ldifdiff.pl script to do
this. This week, I have this two entries like this :

# new.ldif
dn: cn=Tonio,ou=Washington,dc=company,dc=com
objectclass: inetOrgPerson
cn: Tonio
ou: Washington
sn: Tonio
employeenumber: 888999

# old.ldif
dn: cn=Tony,ou=Los Angeles,dc=company,dc=com
objectclass: inetOrgPerson
cn: Tony
ou: Los Angeles
sn: Tony
employeenumber: 888999

The result of ldifdiff -k employeenumber new.ldif old.ldif was :

dn: cn=Tony,ou=Los Angeles,dc=company,dc=com
changetype: modrdn
newrdn: cn=Tonio
deleteoldrdn: 1

dn: cn=Tonio,ou=Washington,dc=company,dc=com
changetype: modify
replace: ou
ou: Washington
-
replace: sn
sn: Tonio

I think that's wrong the changetype would be moddn and not modrdn.
I propose this patch to do this. The result was :

dn: cn=Tony,ou=Los Angeles,dc=company,dc=com
changetype: moddn
newrdn: cn=Tonio
deleteoldrdn: 1
newsuperior: ou=Washington,dc=company,dc=com

dn: cn=Tonio,ou=Washington,dc=company,dc=com
changetype: modify
replace: ou
ou: Washington
-
replace: sn
sn: Tonio

Hope that helps anyway.

Regards,
-- 
Anthony Milan
--- ldifdiff.pl.ori	2006-04-21 17:54:52.679165936 +0200
+++ ldifdiff.pl	2006-04-21 18:03:27.324927888 +0200
@@ -111,6 +111,12 @@
 # Gets the relative distinguished name (RDN) value
 sub rdnval { my $rv = ($_[0]->dn =~ /=(.*)/)[0]; $rv =~ s/(?<!\\),.*//; $rv }
 
+# Gets the relative distinguished name (RDN)
+sub rdn { ( $_[0]->dn =~ /^([^,]+),/ )[0] }
+
+# Gets the DN superior to the relative distinguished name (RDN)
+sub superior { ( $_[0]->dn =~ /^[^,]+,(.*)/ )[0] }
+
 sub cmpEntries
 { 
     my ($a, $b) = @_;
@@ -176,23 +182,48 @@
 		# When we get here, we're dealing with the same person in $sourceentry
 		# and $targetentry. Compare the data and generate the update.
 
-		# If a modRDN is necessary, it needs to happen before other mods
 		if (lc(canonical_dn($sourceentry->dn)) 
 		 ne lc(canonical_dn($targetentry->dn))) {
 			my $rdnattr = rdnattr($sourceentry);
 			my $rdnval = rdnval($sourceentry);
 
-			$targetentry->{changetype} = 'modrdn';
-			$targetentry->add(newrdn => "$rdnattr=$rdnval",
+ 			# If a modDN is necessary, it needs to happen before other mods
+		 	if (lc(superior($sourceentry)) ne lc(superior($targetentry))) {
+		 
+				$targetentry->{changetype} = 'moddn';
+				$targetentry->add(newrdn => "$rdnattr=$rdnval",
+							  deleteoldrdn => '1',
+							  newsuperior  => superior($sourceentry),
+							  );
+				$ldifout->write_entry($targetentry);
+				$targetentry->delete('newrdn');
+				$targetentry->delete('deleteoldrdn');
+				$targetentry->delete('newsuperior');
+				delete($targetentry->{changetype});
+			
+				$targetentry->dn($sourceentry->dn);
+				$targetentry->replace($rdnattr,
+						$sourceentry->get_value($rdnattr))
+					if $sourceentry->exists($rdnattr);
+			}
+
+ 			# If a modRDN is necessary, it needs to happen before other mods
+			# but after modDN
+		 	if (lc(rdn($sourceentry)) ne lc(rdn($targetentry))) {
+		 
+				$targetentry->{changetype} = 'modrdn';
+				$targetentry->add(newrdn => "$rdnattr=$rdnval",
 							  deleteoldrdn => '1');
-			$ldifout->write_entry($targetentry);
-			$targetentry->delete('newrdn');
-			$targetentry->delete('deleteoldrdn');
-			delete($targetentry->{changetype});
+				$ldifout->write_entry($targetentry);
+				$targetentry->delete('newrdn');
+				$targetentry->delete('deleteoldrdn');
+				delete($targetentry->{changetype});
 			
-			$targetentry->dn($sourceentry->dn);
-			$targetentry->replace($rdnattr, $sourceentry->get_value($rdnattr))
-				if $sourceentry->exists($rdnattr);
+				$targetentry->dn($sourceentry->dn);
+				$targetentry->replace($rdnattr,
+						$sourceentry->get_value($rdnattr))
+					if $sourceentry->exists($rdnattr);
+			}
 		}
 
 		# Check for differences and generate LDIF as appropriate

Reply via email to