geertjanw closed pull request #494: Adding LICENSE/NOTICE/DISCLAIMER to NBMs, 
packing OSGi jars into NBMs…
URL: https://github.com/apache/incubator-netbeans/pull/494
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/apisupport.harness/build.xml b/apisupport.harness/build.xml
index 45ccec305..b305b9a8b 100644
--- a/apisupport.harness/build.xml
+++ b/apisupport.harness/build.xml
@@ -24,14 +24,14 @@
     <import file="../nbbuild/templates/projectized.xml"/>
 
     <target name="nbantext" depends="build-init">
-        <jar jarfile="${cluster}/tasks.jar" 
compress="${build.package.compress}" index="${build.package.index}">
+        <nb-ext-jar jarfile="${cluster}/tasks.jar" 
compress="${build.package.compress}" index="${build.package.index}">
             <manifest>
                 <attribute name="NetBeans-Own-Library" value="true"/>
             </manifest>
             <!-- XXX would be more maintainable to use depfind.sf.net / 
genjar.sf.net / sadun-util.sf.net/pack.html -->
             <zipfileset src="${nbantext.jar}" includes="${bundled.tasks}"/>
             <zipfileset file="taskdefs.properties" 
fullpath="org/netbeans/nbbuild/taskdefs.properties"/>
-        </jar>
+        </nb-ext-jar>
     </target>
 
     <target name="compile-jnlp-launcher" depends="init,compile">
diff --git a/nbbuild/antsrc/org/netbeans/nbbuild/MakeNBM.java 
b/nbbuild/antsrc/org/netbeans/nbbuild/MakeNBM.java
index ad0ae3bac..f8524e387 100644
--- a/nbbuild/antsrc/org/netbeans/nbbuild/MakeNBM.java
+++ b/nbbuild/antsrc/org/netbeans/nbbuild/MakeNBM.java
@@ -39,6 +39,7 @@
 import java.util.Date;
 import java.util.Enumeration;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Locale;
@@ -46,6 +47,7 @@
 import java.util.Properties;
 import java.util.Set;
 import java.util.StringTokenizer;
+import java.util.function.Supplier;
 import java.util.jar.Attributes;
 import java.util.jar.Attributes.Name;
 import java.util.jar.JarEntry;
@@ -301,12 +303,13 @@ public void setAlias(String s) {
     private boolean isStandardInclude = true;
     private ArrayList<ExternalPackage> externalPackages = null;
     private ArrayList<String> locales = null;
-    private ArrayList<Attributes> moduleAttributes = null;
     private Attributes englishAttr = null;
     private Path updaterJar;
     private FileSet executablesSet;
+    private ZipFileSet extraNBMFiles;
     private boolean usePack200;
     private String pack200excludes;
+    private boolean alwaysCreateNBM;
 
     /** Try to find and create localized info.xml files */
     public void setLocales(String s) {
@@ -340,11 +343,19 @@ public void setPack200Excludes(String pack200excludes) {
         this.pack200excludes = pack200excludes;
     }
 
+    public void setAlwaysCreateNBM(boolean alwaysCreateNBM) {
+        this.alwaysCreateNBM = alwaysCreateNBM;
+    }
+
     /** List of executable files in NBM concatinated by ${line.separator}. */
     public FileSet createExecutables() {
         return (executablesSet = new FileSet());
     }
     
+    public ZipFileSet createExtraNBMFiles() {
+        return (extraNBMFiles = new ZipFileSet());
+    }
+    
     /** Module manifest needed for versioning.
      * @deprecated Use {@link #setModule} instead.
      */
@@ -496,6 +507,8 @@ private Attributes getModuleAttributesForLocale(String 
locale) throws BuildExcep
         try {
             try (JarFile mjar = new JarFile(mfile)) {
                 if 
(mjar.getManifest().getMainAttributes().getValue("Bundle-SymbolicName") != 
null) {
+                    englishAttr = new Attributes();
+                    englishAttr.putValue("OpenIDE-Module", 
JarWithModuleAttributes.extractCodeName(mjar.getManifest().getMainAttributes()));
                     // #181025: treat bundles specially.
                     return null;
                 }
@@ -581,25 +594,30 @@ public void execute () throws BuildException {
        overrideLicenseIfNeeded() ;
         
         
-        moduleAttributes = new ArrayList<> ();
+        Map<String, Supplier<Document>> moduleAttributes = new 
LinkedHashMap<>();
         File module = new File( productDir, moduleName );
         Attributes attr = getModuleAttributesForLocale("");
         if (attr == null) {
-            // #181025: OSGi bundle, copy unmodified.
-            Copy copy = new Copy();
-            copy.setProject(getProject());
-            copy.setOwningTarget(getOwningTarget());
-            copy.setFile(module);
-            copy.setTofile(new 
File(nbm.getAbsolutePath().replaceFirst("[.]nbm$", ".jar")));
-            copy.execute();
-            // XXX possibly sign it
-            // XXX could try to run pack200, though not if it was signed
-            return;
+            if (!alwaysCreateNBM) {
+                // #181025: OSGi bundle, copy unmodified.
+                Copy copy = new Copy();
+                copy.setProject(getProject());
+                copy.setOwningTarget(getOwningTarget());
+                copy.setFile(module);
+                copy.setTofile(new 
File(nbm.getAbsolutePath().replaceFirst("[.]nbm$", ".jar")));
+                copy.execute();
+                // XXX possibly sign it
+                // XXX could try to run pack200, though not if it was signed
+                return;
+            } else {
+                moduleAttributes.put("", () -> createFakeOSGiInfo(module));
+            }
+        } else {
+            moduleAttributes.put("", () -> createInfoXml(attr));
         }
-        moduleAttributes.add(attr);
         for (String locale : locales) {
             Attributes a = getModuleAttributesForLocale(locale);
-            if (a != null) moduleAttributes.add(a);
+            if (a != null) moduleAttributes.put(locale, () -> 
createInfoXml(a));
         }
 
         // Will create a file Info/info.xml to be stored in tmp
@@ -615,10 +633,10 @@ public void execute () throws BuildException {
         }
         
         ArrayList<ZipFileSet> infoXMLFileSets = new ArrayList<>();
-        for (Attributes modAttr : moduleAttributes) {
-            Document infoXmlContents = createInfoXml(modAttr);
+        for (Map.Entry<String, Supplier<Document>> modAttr : 
moduleAttributes.entrySet()) {
+            Document infoXmlContents = modAttr.getValue().get();
             File infofile;
-            String loc = modAttr.getValue("locale");
+            String loc = modAttr.getKey();
             if (loc == null)
                 throw new BuildException("Found attributes without assigned 
locale code", getLocation());
             try {
@@ -643,7 +661,6 @@ public void execute () throws BuildException {
         String codename = englishAttr.getValue("OpenIDE-Module");
         if (codename == null)
            new BuildException( "Can't get codenamebase" );
-       
        UpdateTracking tracking = new 
UpdateTracking(productDir.getAbsolutePath());
        Set<String> _files = new 
LinkedHashSet<>(Arrays.asList(tracking.getListOfNBM(codename)));
     List<String> __files = new ArrayList<>(_files);
@@ -731,6 +748,10 @@ public void execute () throws BuildException {
             jar.addFileset(zfs);
         }
 
+        if (extraNBMFiles != null) {
+            jar.addZipfileset(extraNBMFiles);
+        }
+
         if (main != null) { // Add the main dir
             main.setPrefix("main"); // use main prefix
             jar.addZipfileset(main);
@@ -941,14 +962,7 @@ private Document createInfoXml(final Attributes attr) 
throws BuildException {
         } else {
             throw new BuildException("NBM distribution URL is not set", 
getLocation());
         }
-        // Here we only write a name for the license.
-        if (license != null) {
-            String name = license.getName();
-            if (name == null) {
-                throw new BuildException("Every license must have a name or 
file attribute", getLocation());
-            }
-            module.setAttribute("license", name);
-        }
+        maybeAddLicenseName(module);
         module.setAttribute("downloadsize", "0");
         if (needsrestart != null) {
             module.setAttribute("needsrestart", needsrestart);
@@ -1008,13 +1022,7 @@ private Document createInfoXml(final Attributes attr) 
throws BuildException {
             }
         }
         module.appendChild(el);
-        // Maybe write out license text.
-        if (license != null) {
-            el = doc.createElement("license");
-            el.setAttribute("name", license.getName());
-            el.appendChild(license.getTextNode(doc));
-            module.appendChild(el);
-        }
+        maybeAddLicense(module);
         if (updaterJar != null && updaterJar.size() > 0) {
             try {
                 ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -1029,6 +1037,53 @@ private Document createInfoXml(final Attributes attr) 
throws BuildException {
         return doc;
     }
 
+    private Document createFakeOSGiInfo(File osgiJar) {
+        DOMImplementation domimpl;
+        try {
+            domimpl = 
DocumentBuilderFactory.newInstance().newDocumentBuilder().getDOMImplementation();
+        } catch (ParserConfigurationException x) {
+            throw new BuildException(x, getLocation());
+        }
+
+        log("Creating fake info.xml for OSGi bundle", Project.MSG_VERBOSE);
+        
+        String pub = "-//NetBeans//DTD Autoupdate Module Info 2.5//EN";
+        String sys = "http://www.netbeans.org/dtds/autoupdate-info-2_5.dtd";;
+        Document doc = domimpl.createDocument(null, "module", 
domimpl.createDocumentType("module", pub, sys));
+        
+        try (JarFile jf = new JarFile(osgiJar)) {
+            MakeUpdateDesc.fakeOSGiInfoXml(jf, osgiJar, doc);
+            maybeAddLicenseName(doc.getDocumentElement());
+            maybeAddLicense(doc.getDocumentElement());
+        } catch (IOException x) {
+            throw new BuildException(x, getLocation());
+        }
+
+        return doc;
+    }
+
+    private void maybeAddLicenseName(Element module) {
+        // Here we only write a name for the license.
+        if (license != null) {
+            String name = license.getName();
+            if (name == null) {
+                throw new BuildException("Every license must have a name or 
file attribute", getLocation());
+            }
+            module.setAttribute("license", name);
+        }
+    }
+
+    private void maybeAddLicense(Element module) {
+        // Maybe write out license text.
+        if (license != null) {
+            Document doc = module.getOwnerDocument();
+            Element el = doc.createElement("license");
+            el.setAttribute("name", license.getName());
+            el.appendChild(license.getTextNode(doc));
+            module.appendChild(el);
+        }
+    }
+
     static void validateAgainstAUDTDs(InputSource input, final Path 
updaterJar, final Task task) throws IOException, SAXException {
         XMLUtil.parse(input, true, false, XMLUtil.rethrowHandler(), new 
EntityResolver() {
             ClassLoader loader = new AntClassLoader(task.getProject(), 
updaterJar);
diff --git a/nbbuild/antsrc/org/netbeans/nbbuild/MakeUpdateDesc.java 
b/nbbuild/antsrc/org/netbeans/nbbuild/MakeUpdateDesc.java
index 8ae5d48f7..825ffba2f 100644
--- a/nbbuild/antsrc/org/netbeans/nbbuild/MakeUpdateDesc.java
+++ b/nbbuild/antsrc/org/netbeans/nbbuild/MakeUpdateDesc.java
@@ -35,6 +35,7 @@
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
+import java.nio.file.Files;
 import java.text.Collator;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
@@ -111,6 +112,13 @@ public void setDesc(File d) {
         desc = d;
     }
 
+    private File descLicense;
+
+    /** Description file license to use. */
+    public void setDescLicense(File d) {
+        descLicense = d;
+    }
+
     /** Module group to create **/
     public Group createGroup () {
        Group g = new Group ();
@@ -275,6 +283,9 @@ private static String xmlEscape(String s) {
                 PrintWriter pw = new PrintWriter(new OutputStreamWriter(os, 
"UTF-8")); //NOI18N
                pw.println ("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"); 
//NOI18N
                pw.println ();
+                if (descLicense != null) {
+                    pw.println(new 
String(Files.readAllBytes(descLicense.toPath()), "UTF-8"));
+                }
                 DateFormat format = new 
SimpleDateFormat("ss/mm/HH/dd/MM/yyyy"); //NOI18N
                 format.setTimeZone(TimeZone.getTimeZone("GMT")); //NOI18N
                 String date = format.format(new Date());
@@ -664,7 +675,11 @@ private long externalSize(InputStream is) throws 
IOException {
      * @return a {@code <module ...><manifest .../></module>} valid according 
to
      *         <a 
href="http://www.netbeans.org/dtds/autoupdate-info-2_5.dtd";>DTD</a>
      */
-    private Element fakeOSGiInfoXml(JarFile jar, File whereFrom) throws 
IOException {
+    private static Element fakeOSGiInfoXml(JarFile jar, File whereFrom) throws 
IOException {
+        return fakeOSGiInfoXml(jar, whereFrom, 
XMLUtil.createDocument("module"));
+    }
+    //TODO: javadoc
+    public static Element fakeOSGiInfoXml(JarFile jar, File whereFrom, 
Document doc) throws IOException {
         Attributes attr = jar.getManifest().getMainAttributes();
         Properties localized = new Properties();
         String bundleLocalization = attr.getValue("Bundle-Localization");
@@ -673,10 +688,12 @@ private Element fakeOSGiInfoXml(JarFile jar, File 
whereFrom) throws IOException
                 localized.load(is);
             }
         }
-        return fakeOSGiInfoXml(attr, localized, whereFrom);
+        return fakeOSGiInfoXml(attr, localized, whereFrom, doc);
+    }
+    static Element fakeOSGiInfoXml(Attributes attr, Properties localized, File 
whereFrom) { //tests
+        return fakeOSGiInfoXml(attr, localized, whereFrom, 
XMLUtil.createDocument("module"));
     }
-    static Element fakeOSGiInfoXml(Attributes attr, Properties localized, File 
whereFrom) {
-        Document doc = XMLUtil.createDocument("module");
+    private static Element fakeOSGiInfoXml(Attributes attr, Properties 
localized, File whereFrom, Document doc) {
         Element module = doc.getDocumentElement();
         String cnb = JarWithModuleAttributes.extractCodeName(attr);
         module.setAttribute("codenamebase", cnb);
diff --git 
a/nbbuild/antsrc/org/netbeans/nbbuild/extlibs/CreateLicenseSummary.java 
b/nbbuild/antsrc/org/netbeans/nbbuild/extlibs/CreateLicenseSummary.java
index 945a32f7c..69089c9bf 100644
--- a/nbbuild/antsrc/org/netbeans/nbbuild/extlibs/CreateLicenseSummary.java
+++ b/nbbuild/antsrc/org/netbeans/nbbuild/extlibs/CreateLicenseSummary.java
@@ -50,6 +50,8 @@
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.types.Resource;
 import org.apache.tools.ant.types.selectors.SelectorUtils;
 import org.netbeans.nbbuild.JUnitReportWriter;
 import org.netbeans.nbbuild.extlibs.licenseinfo.Fileset;
@@ -122,6 +124,11 @@ public void setBinary(boolean binary) {
         this.binary = binary;
     }
     
+    private FileSet moduleFiles;
+    public FileSet createModuleFiles() {
+        return (moduleFiles = new FileSet());
+    }
+
     private Map<String, String> pseudoTests;
 
     public @Override
@@ -289,6 +296,17 @@ private void evaluateBinaries(final PrintWriter 
licenseWriter, final PrintWriter
         List<String> ignoredPatterns = 
VerifyLibsAndLicenses.loadPatterns("ignored-binary-overlaps");
         if (build != null)
             findBinaries(build, binaries2LicenseHeaders, crc2License, new 
HashMap<>(), "", testBinariesAreUnique, ignoredPatterns);
+        if (moduleFiles != null) {
+            for (Resource r : moduleFiles) {
+                try (InputStream is = r.getInputStream()) {
+                    long crc = computeCRC32(is);
+                    Map<String, String> headers = crc2License.get(crc);
+                    if (headers != null) {
+                        binaries2LicenseHeaders.put(r.getName(), headers);
+                    }
+                }
+            }
+        }
         if (binaries2LicenseHeaders.isEmpty())
             return ;
         pseudoTests.put("testBinariesAreUnique", 
testBinariesAreUnique.length() > 0 ? "Some binaries are duplicated (edit 
nbbuild/antsrc/org/netbeans/nbbuild/extlibs/ignored-binary-overlaps as needed)" 
+ testBinariesAreUnique : null);
diff --git a/nbbuild/build.xml b/nbbuild/build.xml
index a1c5a3633..07fa60f4e 100644
--- a/nbbuild/build.xml
+++ b/nbbuild/build.xml
@@ -211,6 +211,7 @@
       <subant-junit target="nbm" failonerror="${nbms.fail.on.error}" 
report="${nb.build.dir}/build-nbms.xml" inheritall="false">
           <buildpath path="${modules.sorted}"/>
           <property name="base.nbm.target.dir" value="${base.nbm.target.dir}"/>
+          <property name="nbm.always.create" value="true" />
       </subant-junit>
   </target>
 
@@ -1894,9 +1895,10 @@ It is possible to use -Ddebug.port=3234 -Ddebug.pause=y 
to start the system in d
       <property name="catalog.notification.url"     value=""/>
       <property name="catalog.content.description"  value=""/>
       <property name="catalog.content.description.url" value=""/>
+      <property name="catalog.license.header" 
value="${nb_all}/nbbuild/catalog-license-header.txt"/>
 
 <!--      <genau config="ausrc/modules.setup" nbmLocation="${nbms.location}" 
catalog="${catalog.file}" catalogDeploymentLocation="${catalog.base.url}"/>-->
-      <makeupdatedesc desc="${catalog.file}" distbase="${catalog.base.url}" 
automaticgrouping="true" uselicenseurl="${use.license.url.in.catalog}" 
notificationmessage="${catalog.notification.message}" 
notificationurl="${catalog.notification.url}" 
contentdescription="${catalog.content.description}" 
contentdescriptionurl="${catalog.content.description.url}">
+      <makeupdatedesc desc="${catalog.file}" distbase="${catalog.base.url}" 
automaticgrouping="true" uselicenseurl="${use.license.url.in.catalog}" 
notificationmessage="${catalog.notification.message}" 
notificationurl="${catalog.notification.url}" 
contentdescription="${catalog.content.description}" 
contentdescriptionurl="${catalog.content.description.url}" 
desclicense="${catalog.license.header}">
           <fileset dir="${nbms.location}">
               <include name="**/*.nbm"/>
               <include name="**/*.jar"/>
diff --git a/nbbuild/catalog-license-header.txt 
b/nbbuild/catalog-license-header.txt
new file mode 100644
index 000000000..a0eb9fbf8
--- /dev/null
+++ b/nbbuild/catalog-license-header.txt
@@ -0,0 +1,20 @@
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
diff --git a/nbbuild/templates/common.xml b/nbbuild/templates/common.xml
index 252dc7f5e..afe5635ea 100644
--- a/nbbuild/templates/common.xml
+++ b/nbbuild/templates/common.xml
@@ -427,7 +427,11 @@
         <fileset dir="${cluster}" id="module.executable.files" 
includes="${nbm.executable.files}"/>
     </target>
 
-    <target name="nbm" 
depends="init,netbeans,-nbm-prompt-for-storepass,-init-executables" 
description="Build NBM archive.">
+    <target name="-init-extra.nbm.files" unless="extra.nbm.files.provided"> 
<!-- fallback -->
+        <zipfileset dir="${cluster}" id="extra.nbm.files" 
includes="[NOTHING]"/>
+    </target>
+
+    <target name="nbm" 
depends="init,netbeans,-nbm-prompt-for-storepass,-init-executables,-init-extra.nbm.files"
 description="Build NBM archive.">
         <mkdir dir="${build.dir}"/>
         <property name="nbm.target.cluster" value=""/> <!-- fallback -->
         <property name="license.file.override" value="${license.file}"/>
@@ -444,6 +448,7 @@
                  preferredupdate="${nbm.is.preferredupdate}"
                  usepack200="${use.pack200}"
                  pack200excludes="${pack200.excludes}"
+                 alwayscreatenbm="${nbm.always.create}"
                  targetcluster="${nbm.target.cluster}"
                  releasedate="${nbm.release.date}"
                  moduleauthor="${nbm.module.author}"
@@ -458,6 +463,7 @@
                 </pathfileset>
             </updaterjar>
             <executables refid="module.executable.files"/>
+            <extranbmfiles refid="extra.nbm.files"/>
         </makenbm>
     </target>
 
diff --git a/nbbuild/templates/projectized.xml 
b/nbbuild/templates/projectized.xml
index b112e65cf..6a1727994 100644
--- a/nbbuild/templates/projectized.xml
+++ b/nbbuild/templates/projectized.xml
@@ -409,11 +409,42 @@ If you are sure you want to build with JDK 9+ anyway, 
use: -Dpermit.jdk9.builds=
     </target>
 
     <target name="-create-license.file" depends="init">
-        <mkdir dir="${build.dir}"/>
-        <property name="license.file.override" 
location="${build.dir}/license"/>
+        <mkdir dir="${build.dir}/nbm-extras/META-INF"/>
+        <taskdef name="createlicensesummary" 
classname="org.netbeans.nbbuild.extlibs.CreateLicenseSummary" 
classpath="${nbantext.jar}"/>
+        <property name="module.name.temp" location="." />
+        <basename property="module.name" file="${module.name.temp}" />
+        <createlicensesummary licenseStub="${nb_all}/LICENSE"
+                              noticeStub="${nb_all}/nbbuild/notice-stub.txt"
+                              nball="${nb_all}"
+                              
license="${build.dir}/nbm-extras/META-INF/LICENSE"
+                              notice="${build.dir}/notice-temp"
+                              binary="true"
+                              modules="${module.name}"
+        >
+            <moduleFiles dir="${cluster}">
+                <patternset refid="module.files"/>
+            </moduleFiles>
+        </createlicensesummary>
+
+        <concat destfile="${build.dir}/nbm-extras/META-INF/NOTICE">
+          <fileset file="${build.dir}/notice-temp" />
+          <fileset dir="."
+                   includes="notice.txt" />
+          <filterchain>
+              <tokenfilter>
+                  <filetokenizer />
+                  <replaceregex pattern="(\r?\n)(\r?\n)+"
+                                replace="\1\1"
+                                flags="g" />
+             </tokenfilter>
+          </filterchain>
+        </concat>
+
+        <copy file="${nb_all}/DISCLAIMER" 
todir="${build.dir}/nbm-extras/META-INF/" />
+        <property name="license.file.override" 
location="${build.dir}/nbm-extras/META-INF/LICENSE"/>
         <property name="extra.license.files" value=""/>
-        <taskdef name="releasefileslicense" 
classname="org.netbeans.nbbuild.extlibs.ReleaseFilesLicense" 
classpath="${nbantext.jar}"/>
-        <releasefileslicense license="${license.file.override}" 
standardlicense="${nb_all}/nbbuild/standard-nbm-license.txt" 
extralicensefiles="${extra.license.files}"/>
+        <zipfileset id="extra.nbm.files" dir="${build.dir}/nbm-extras/" />
+        <property name="extra.nbm.files.provided" value=""/>
     </target>
 
     <target name="nbm" 
depends="-create-dest-dir-nbm,-create-license.file,projectized-common.nbm"/>


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services

---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscr...@netbeans.apache.org
For additional commands, e-mail: notifications-h...@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists

Reply via email to