Synchronise all repackage downloads.
[cc0/argeo-build.git] / src / org / argeo / build / Repackage.java
index 3c03a10cee78dffee8b01b09b2678667dbcd6af9..9827b06622295d6bd97673b4c34a32834df01ab7 100644 (file)
@@ -98,13 +98,14 @@ public class Repackage {
 
                List<CompletableFuture<Void>> toDos = new ArrayList<>();
                for (int i = 1; i < args.length; i++) {
-                       Path p = Paths.get(args[i]);
-                       if (sequential)
-                               factory.processCategory(p);
+                       Path categoryPath = Paths.get(args[i]);
+                       factory.cleanPreviousFailedBuild(categoryPath);
+                       if (sequential) // sequential processing happens here
+                               factory.processCategory(categoryPath);
                        else
-                               toDos.add(CompletableFuture.runAsync(() -> factory.processCategory(p)));
+                               toDos.add(CompletableFuture.runAsync(() -> factory.processCategory(categoryPath)));
                }
-               if (!sequential)
+               if (!sequential)// parallel processing
                        CompletableFuture.allOf(toDos.toArray(new CompletableFuture[toDos.size()])).join();
 
                // Summary
@@ -115,6 +116,25 @@ public class Repackage {
                logger.log(INFO, "# License summary:\n" + sb);
        }
 
+       /** Deletes remaining sub directories. */
+       void cleanPreviousFailedBuild(Path categoryPath) {
+               Path outputCategoryPath = a2Base.resolve(categoryPath);
+               if (!Files.exists(outputCategoryPath))
+                       return;
+               // clean previous failed build
+               try {
+                       for (Path subDir : Files.newDirectoryStream(outputCategoryPath, (d) -> Files.isDirectory(d))) {
+                               if (Files.exists(subDir)) {
+                                       logger.log(WARNING, "Bundle dir " + subDir
+                                                       + " already exists, probably from a previous failed build, deleting it...");
+                                       deleteDirectory(subDir);
+                               }
+                       }
+               } catch (IOException e) {
+                       logger.log(ERROR, "Cannot clean previous build", e);
+               }
+       }
+
        /** MANIFEST headers. */
        enum ManifestHeader {
                // OSGi
@@ -584,6 +604,10 @@ public class Repackage {
                                                } else if (entry.getName().startsWith("org/apache/batik/")) {
                                                        logger.log(TRACE, "Skip " + entry.getName());
                                                        continue entries;
+                                               } else if (entry.getName().startsWith("META-INF/NOTICE")) {
+                                                       logger.log(WARNING, "Skip " + entry.getName() + " from " + artifact);
+                                                       // TODO merge them?
+                                                       continue entries;
                                                } else {
                                                        throw new IllegalStateException("File " + target + " from " + artifact + " already exists");
                                                }
@@ -910,6 +934,10 @@ public class Repackage {
                                                                        map.put(key.toString(), commonProps.getProperty(key.toString()));
                                                                A2Origin origin = new A2Origin();
                                                                Path bundleDir = processBundleJar(file, targetCategoryBase, map, origin);
+                                                               if (bundleDir == null) {
+                                                                       logger.log(WARNING, "No bundle dir created for " + file + ", skipping...");
+                                                                       return FileVisitResult.CONTINUE;
+                                                               }
                                                                origins.put(bundleDir, origin);
                                                                logger.log(DEBUG, () -> "Processed " + file);
                                                        }
@@ -993,6 +1021,8 @@ public class Repackage {
                Manifest sourceManifest;
                try (JarInputStream jarIn = new JarInputStream(Files.newInputStream(file), false)) {
                        sourceManifest = jarIn.getManifest();
+                       if (sourceManifest == null)
+                               logger.log(WARNING, file + " has no manifest");
                        manifest = sourceManifest != null ? new Manifest(sourceManifest) : new Manifest();
 
                        String rawSourceSymbolicName = manifest.getMainAttributes().getValue(BUNDLE_SYMBOLICNAME.toString());
@@ -1015,6 +1045,8 @@ public class Repackage {
                                nameVersion = new NameVersion(ourSymbolicName, ourVersion);
                        } else {
                                nameVersion = nameVersionFromManifest(manifest);
+                               if (nameVersion == null)
+                                       throw new IllegalStateException("Could not compute name/version from Manifest");
                                if (ourVersion != null && !nameVersion.getVersion().equals(ourVersion)) {
                                        logger.log(WARNING,
                                                        "Original version is " + nameVersion.getVersion() + " while new version is " + ourVersion);
@@ -1025,6 +1057,7 @@ public class Repackage {
                                        nameVersion.setName(ourSymbolicName);
                                }
                        }
+
                        bundleDir = targetBase.resolve(nameVersion.getName() + "." + nameVersion.getBranch());
 
                        // copy original MANIFEST
@@ -1050,7 +1083,6 @@ public class Repackage {
                                arch = libRelativePath.getName(1).toString();
                        }
 
-//                     if (!embed) {
                        // copy entries
                        JarEntry entry;
                        entries: while ((entry = jarIn.getNextJarEntry()) != null) {
@@ -1117,7 +1149,6 @@ public class Repackage {
                                        origin.deleted.add(bundleDir.relativize(target).toString());
                                }
                                logger.log(TRACE, () -> "Copied " + target);
-//                             }
                        }
                }
 
@@ -1130,11 +1161,6 @@ public class Repackage {
                                        entries.get(BUNDLE_SYMBOLICNAME.toString()) + ";singleton:=true");
                }
 
-//             if (embed) {// copy embedded jar
-//                     Files.copy(file, bundleDir.resolve(file.getFileName()));
-//                     entries.put(ManifestHeader.BUNDLE_CLASSPATH.toString(), file.getFileName().toString());
-//             }
-
                // Final MANIFEST decisions
                // We also check the original OSGi metadata and compare with our changes
                for (String key : entries.keySet()) {
@@ -1317,15 +1343,17 @@ public class Repackage {
        }
 
        /**
-        * Effectively download. Synchronised in order to avoid downloading twice in
-        * parallel.
+        * Effectively download an archive.
         */
-       synchronized Path downloadArchive(URL url, Path dir) throws IOException {
+       Path downloadArchive(URL url, Path dir) throws IOException {
                return download(url, dir, (String) null);
        }
 
-       /** Effectively download. */
-       Path download(URL url, Path dir, String name) throws IOException {
+       /**
+        * Effectively download. Synchronised in order to avoid downloading twice in
+        * parallel.
+        */
+       synchronized Path download(URL url, Path dir, String name) throws IOException {
 
                Path dest;
                if (name == null) {
@@ -1473,30 +1501,31 @@ public class Repackage {
                                if (url != null) {
                                        writer.write("which is available here: " + url + "\n");
                                } else {
-                                       logger.log(ERROR, "No licne URL for " + jarDir);
+                                       logger.log(ERROR, "No licence URL for " + jarDir);
                                }
                        }
-                       writer.write("\n");
 
                        // origin
-                       String m2Repo = ARGEO_ORIGIN_M2_REPO.get(mapping);
-                       String originDesc = ARGEO_ORIGIN_M2.get(mapping);
+                       String originDesc = ARGEO_ORIGIN_URI.get(mapping);
                        if (originDesc != null)
-                               writer.append("The original component has M2 coordinates:\n" + originDesc.replace(',', '\n') + "\n"
-                                               + (m2Repo != null ? "\nin M2 repository " + m2Repo + "\n" : ""));
+                               writer.append("\nThe original component comes from " + originDesc + ".\n");
                        else {
-                               originDesc = ARGEO_ORIGIN_URI.get(mapping);
+                               String m2Repo = ARGEO_ORIGIN_M2_REPO.get(mapping);
+                               originDesc = ARGEO_ORIGIN_M2.get(mapping);
                                if (originDesc != null)
-                                       writer.append("The original component comes from " + originDesc + ".\n");
+                                       writer.append("\nThe original component has M2 coordinates:\n" + originDesc.replace(',', '\n')
+                                                       + "\n" + (m2Repo != null ? "\nin M2 repository " + m2Repo + "\n" : ""));
                                else
                                        logger.log(ERROR, "Cannot find origin information in " + jarDir);
                        }
                        String originSources = ARGEO_ORIGIN_SOURCES_URI.get(mapping);
                        if (originSources != null)
-                               writer.append("The original sources come from " + originDesc + ".\n");
+                               writer.append("\nThe original sources come from " + originSources + ".\n");
 
-                       if (!jarDir.getFileName().endsWith(".src")) {// binary archive
+                       if (Files.exists(jarDir.resolve(CHANGES)))
                                writer.append("\nA detailed list of changes is available under " + CHANGES + ".\n");
+
+                       if (!jarDir.getFileName().toString().endsWith(".src")) {// binary archive
                                if (separateSources)
                                        writer.append("Corresponding sources are available in the related archive named "
                                                        + jarDir.toString() + ".src.jar.\n");
@@ -1504,7 +1533,6 @@ public class Repackage {
                                        writer.append("Corresponding sources are available under OSGI-OPT/src.\n");
                        }
                }
-
        }
 
        /**
@@ -1523,6 +1551,8 @@ public class Repackage {
 
                /** Append changes to the A2-ORIGIN/changes file. */
                void appendChanges(Path baseDirectory) throws IOException {
+                       if (modified.isEmpty() && deleted.isEmpty() && added.isEmpty() && moved.isEmpty())
+                               return; // no changes
                        Path changesFile = baseDirectory.resolve(CHANGES);
                        Files.createDirectories(changesFile.getParent());
                        try (BufferedWriter writer = Files.newBufferedWriter(changesFile, APPEND, CREATE)) {