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