Index: src/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorWriter.java =================================================================== --- src/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorWriter.java (revision 963961) +++ src/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorWriter.java (working copy) @@ -425,6 +425,9 @@ } out.print("\""); } + if (!conf.isTransitive()) { + out.println(" transitive=\"false\""); + } if (conf.getDeprecated() != null) { out.print(" deprecated=\"" + XMLHelper.escape(conf.getDeprecated()) + "\""); } Index: test/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorWriterTest.java =================================================================== --- test/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorWriterTest.java (revision 963961) +++ test/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorWriterTest.java (working copy) @@ -22,13 +22,17 @@ import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; +import java.util.Date; import java.util.GregorianCalendar; import junit.framework.TestCase; import org.apache.ivy.Ivy; +import org.apache.ivy.core.module.descriptor.Configuration; import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor; import org.apache.ivy.core.module.descriptor.ModuleDescriptor; +import org.apache.ivy.core.module.descriptor.Configuration.Visibility; +import org.apache.ivy.core.module.id.ModuleId; import org.apache.ivy.core.module.id.ModuleRevisionId; import org.apache.ivy.core.settings.IvySettings; import org.apache.ivy.util.FileUtil; @@ -107,19 +111,68 @@ assertEquals(expected, wrote); } - public void testExtends() throws Exception { - ModuleDescriptor md = XmlModuleDescriptorParser.getInstance().parseDescriptor( - new IvySettings(), XmlModuleDescriptorWriterTest.class.getResource("test-extends-all.xml"), false); - XmlModuleDescriptorWriter.write(md, LICENSE, dest); + public void testExtends() throws Exception { + ModuleDescriptor md = XmlModuleDescriptorParser.getInstance().parseDescriptor( + new IvySettings(), + XmlModuleDescriptorWriterTest.class.getResource("test-extends-all.xml"), false); + XmlModuleDescriptorWriter.write(md, LICENSE, dest); - assertTrue(dest.exists()); - String wrote = FileUtil.readEntirely(new BufferedReader(new FileReader(dest))) - .replaceAll("\r\n?", "\n"); - String expected = readEntirely("test-write-extends.xml") - .replaceAll("\r\n?", "\n") - .replaceAll("working@localhost", Ivy.getWorkingRevision()); - assertEquals(expected, wrote); - } + assertTrue(dest.exists()); + String wrote = FileUtil.readEntirely(new BufferedReader(new FileReader(dest))).replaceAll( + "\r\n?", "\n"); + String expected = readEntirely("test-write-extends.xml").replaceAll("\r\n?", "\n") + .replaceAll("working@localhost", Ivy.getWorkingRevision()); + assertEquals(expected, wrote); + } + + /** + * Test that the transitive attribute is written for non-transitive configurations. + * + * + * + * @see IVY-1207 + * @throws Exception + */ + public void testTransitiveAttributeForNonTransitiveConfs() throws Exception { + // Given a ModuleDescriptor with a non-transitive configuration + DefaultModuleDescriptor md = new DefaultModuleDescriptor(new ModuleRevisionId(new ModuleId( + "myorg", "myname"), "1.0"), "integration", new Date()); + Configuration conf = new Configuration("conf", Visibility.PUBLIC, "desc", null, false, null); + md.addConfiguration(conf); + + // When the ModuleDescriptor is written + XmlModuleDescriptorWriter.write(md, LICENSE, dest); + + // Then the transitive attribute must be set to false + String output = FileUtil.readEntirely(dest); + String writtenConf = output.substring(output.indexOf("") + 16, output.indexOf("")).trim(); + assertTrue("Transitive attribute not set to false: " + writtenConf, writtenConf.contains("transitive=\"false\"")); + } + + /** + * Test that the transitive attribute is not written when the configuration IS transitive. + * + * This is the default and writing it will only add noise and cause a deviation from the known + * behavior (before fixing IVY-1207). + * + * @see IVY-1207 + * @throws Exception + */ + public void testTransitiveAttributeNotWrittenForTransitiveConfs() throws Exception { + // Given a ModuleDescriptor with a transitive configuration + DefaultModuleDescriptor md = new DefaultModuleDescriptor(new ModuleRevisionId(new ModuleId( + "myorg", "myname"), "1.0"), "integration", new Date()); + Configuration conf = new Configuration("conf", Visibility.PUBLIC, "desc", null, true, null); + md.addConfiguration(conf); + + // When the ModuleDescriptor is written + XmlModuleDescriptorWriter.write(md, LICENSE, dest); + + // Then the transitive attribute must NOT be written + String output = FileUtil.readEntirely(dest); + String writtenConf = output.substring(output.indexOf("") + 16, output.indexOf("")).trim(); + assertFalse("Transitive attribute set: " + writtenConf, writtenConf.contains("transitive=")); + } private String readEntirely(String resource) throws IOException { return FileUtil.readEntirely(new BufferedReader(new InputStreamReader(