[OpenLayers-Commits] r3158 - in trunk/openlayers: examples lib/OpenLayers lib/OpenLayers/Format tests/Format

commits at openlayers.org commits at openlayers.org
Mon May 21 10:24:56 EDT 2007


Author: tschaub
Date: 2007-05-21 10:24:55 -0400 (Mon, 21 May 2007)
New Revision: 3158

Modified:
   trunk/openlayers/examples/wkt.html
   trunk/openlayers/lib/OpenLayers/Format/WKT.js
   trunk/openlayers/lib/OpenLayers/Geometry.js
   trunk/openlayers/tests/Format/test_WKT.html
Log:
#708 - make the WKT format like the other vector formats - serialize/deserialize features instead of geometries

Modified: trunk/openlayers/examples/wkt.html
===================================================================
--- trunk/openlayers/examples/wkt.html	2007-05-18 15:20:58 UTC (rev 3157)
+++ trunk/openlayers/examples/wkt.html	2007-05-21 14:24:55 UTC (rev 3158)
@@ -78,7 +78,7 @@
         }
         
         function displayWKT(feature) {
-            var str = wkt.write(feature.geometry);
+            var str = wkt.write(feature);
             // not a good idea in general, just for this demo
             str = str.replace(/,/g, ', ');
             document.getElementById('info').innerHTML = str;
@@ -86,19 +86,18 @@
 
         function parseWKT() {
             var element = document.getElementById('wkt');
-            var collection = wkt.read(element.value);
+            var features = wkt.read(element.value);
             var bounds;
-            if(collection) {
-                if(collection.constructor != Array) {
-                    collection = [collection];
+            if(features) {
+                if(features.constructor != Array) {
+                    features = [features];
                 }
-                var features = [];
-                for(var i=0; i<collection.length; ++i) {
-                    features.push(new OpenLayers.Feature.Vector(collection[i]));
+                for(var i=0; i<features.length; ++i) {
                     if (!bounds) {
-                        bounds = collection[i].getBounds();
+                        bounds = features[i].geometry.getBounds();
+                    } else {
+                        bounds.extend(features[i].geometry.getBounds());
                     }
-                    bounds.extend(collection[i].getBounds());
                     
                 }
                 vectors.addFeatures(features);

Modified: trunk/openlayers/lib/OpenLayers/Format/WKT.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Format/WKT.js	2007-05-18 15:20:58 UTC (rev 3157)
+++ trunk/openlayers/lib/OpenLayers/Format/WKT.js	2007-05-21 14:24:55 UTC (rev 3158)
@@ -25,38 +25,41 @@
     },
 
     /**
-     * Deserialize a WKT string and return an OpenLayers.Geometry or an array
-     * of OpenLayers.Geometry.  Supports WKT for POINT, MULTIPOINT, LINESTRING,
-     * MULTILINESTRING, POLYGON, MULTIPOLYGON, and GEOMETRYCOLLECTION.
+     * Deserialize a WKT string and return an OpenLayers.Feature.Vector or an
+     * array of OpenLayers.Feature.Vector.  Supports WKT for POINT, MULTIPOINT,
+     * LINESTRING, MULTILINESTRING, POLYGON, MULTIPOLYGON, and
+     * GEOMETRYCOLLECTION.
      * @param {String} wkt A WKT string
-     * @returns {OpenLayers.Geometry|Array} A geometry or array of geometries
-     *                                      for GEOMETRYCOLLECTION WKT.
+     * @returns {OpenLayers.Feature.Vector|Array} A feature or array of
+     *                                            features for
+     *                                            GEOMETRYCOLLECTION WKT.
      */
     read: function(wkt) {
-        var geometry, type, str;
+        var features, type, str;
         var matches = this.regExes.typeStr.exec(wkt);
         if(matches) {
             type = matches[1].toLowerCase();
             str = matches[2];
             if(this.parse[type]) {
-                geometry = this.parse[type].apply(this, [str]);
+                features = this.parse[type].apply(this, [str]);
             }
         }
-        return geometry;
+        return features;
     },
 
     /**
-     * Serialize a geometry or array of geometries into a WKT string.
-     * @param {OpenLayers.Geometry|Array} geom A geometry or array of geometries
+     * Serialize a feature or array of features into a WKT string.
+     * @param {OpenLayers.Feature.Vector|Array} features A feature or array of
+     *                                                   features
      * @returns {String} The WKT string representation of the input geometries
      */
-    write: function(geom) {
+    write: function(features) {
         var collection, geometry, type, data, isCollection;
-        if(geom.constructor == Array) {
-            collection = geom;
+        if(features.constructor == Array) {
+            collection = features;
             isCollection = true;
         } else {
-            collection = [geom];
+            collection = [features];
             isCollection = false;
         }
         var pieces = [];
@@ -67,7 +70,7 @@
             if(isCollection && i>0) {
                 pieces.push(',');
             }
-            geometry = collection[i];
+            geometry = collection[i].geometry;
             type = geometry.CLASS_NAME.split('.')[2].toLowerCase();
             if(!this.extract[type]) {
                 return null;
@@ -178,47 +181,58 @@
      */
     parse: {
         /**
-         * Return point geometry given a point WKT fragment.
+         * Return point feature given a point WKT fragment.
          * @param {String} str A WKT fragment representing the point
-         * @returns {OpenLayers.Geometry.Point} A point geometry
+         * @returns {OpenLayers.Feature.Vector} A point feature
+         * @private
          */
         'point': function(str) {
             var coords = str.trim().split(this.regExes.spaces);
-            return new OpenLayers.Geometry.Point(coords[0], coords[1]);
+            return new OpenLayers.Feature.Vector(
+                new OpenLayers.Geometry.Point(coords[0], coords[1])
+            );
         },
 
         /**
-         * Return a multipoint geometry given a multipoint WKT fragment.
+         * Return a multipoint feature given a multipoint WKT fragment.
          * @param {String} A WKT fragment representing the multipoint
-         * @returns {OpenLayers.Geometry.MultiPoint} A multipoint geometry
+         * @returns {OpenLayers.Feature.Vector} A multipoint feature
+         * @private
          */
         'multipoint': function(str) {
             var points = str.trim().split(',');
             var components = [];
             for(var i=0; i<points.length; ++i) {
-                components.push(this.parse.point.apply(this, [points[i]]));
+                components.push(this.parse.point.apply(this, [points[i]]).geometry);
             }
-            return new OpenLayers.Geometry.MultiPoint(components);
+            return new OpenLayers.Feature.Vector(
+                new OpenLayers.Geometry.MultiPoint(components)
+            );
         },
         
         /**
-         * Return a linestring geometry given a linestring WKT fragment.
+         * Return a linestring feature given a linestring WKT fragment.
          * @param {String} A WKT fragment representing the linestring
-         * @returns {OpenLayers.Geometry.LineString} A linestring geometry
+         * @returns {OpenLayers.Feature.Vector} A linestring feature
+         * @private
          */
         'linestring': function(str) {
             var points = str.trim().split(',');
             var components = [];
             for(var i=0; i<points.length; ++i) {
-                components.push(this.parse.point.apply(this, [points[i]]));
+                components.push(this.parse.point.apply(this, [points[i]]).geometry);
             }
-            return new OpenLayers.Geometry.LineString(components);
+            console.log(components);
+            return new OpenLayers.Feature.Vector(
+                new OpenLayers.Geometry.LineString(components)
+            );
         },
 
         /**
-         * Return a multilinestring geometry given a multilinestring WKT fragment.
+         * Return a multilinestring feature given a multilinestring WKT fragment.
          * @param {String} A WKT fragment representing the multilinestring
-         * @returns {OpenLayers.Geometry.LineString} A multilinestring geometry
+         * @returns {OpenLayers.Feature.Vector} A multilinestring feature
+         * @private
          */
         'multilinestring': function(str) {
             var line;
@@ -226,15 +240,18 @@
             var components = [];
             for(var i=0; i<lines.length; ++i) {
                 line = lines[i].replace(this.regExes.trimParens, '$1');
-                components.push(this.parse.linestring.apply(this, [line]));
+                components.push(this.parse.linestring.apply(this, [line]).geometry);
             }
-            return new OpenLayers.Geometry.MultiLineString(components);
+            return new OpenLayers.Feature.Vector(
+                new OpenLayers.Geometry.MultiLineString(components)
+            );
         },
         
         /**
-         * Return a polygon geometry given a polygon WKT fragment.
+         * Return a polygon feature given a polygon WKT fragment.
          * @param {String} A WKT fragment representing the polygon
-         * @returns {OpenLayers.Geometry.Polygon} A polygon geometry
+         * @returns {OpenLayers.Feature.Vector} A polygon feature
+         * @private
          */
         'polygon': function(str) {
             var ring, linestring, linearring;
@@ -242,17 +259,20 @@
             var components = [];
             for(var i=0; i<rings.length; ++i) {
                 ring = rings[i].replace(this.regExes.trimParens, '$1');
-                linestring = this.parse.linestring.apply(this, [ring]);
-                linearring  = new OpenLayers.Geometry.LinearRing(linestring.components);
+                linestring = this.parse.linestring.apply(this, [ring]).geometry;
+                linearring = new OpenLayers.Geometry.LinearRing(linestring.components)
                 components.push(linearring);
             }
-            return new OpenLayers.Geometry.Polygon(components);
+            return new OpenLayers.Feature.Vector(
+                new OpenLayers.Geometry.Polygon(components)
+            );
         },
 
         /**
-         * Return a multipolygon geometry given a multipolygon WKT fragment.
+         * Return a multipolygon feature given a multipolygon WKT fragment.
          * @param {String} A WKT fragment representing the multipolygon
-         * @returns {OpenLayers.Geometry.MultiPolygon} A multipolygon geometry
+         * @returns {OpenLayers.Feature.Vector} A multipolygon feature
+         * @private
          */
         'multipolygon': function(str) {
             var polygon;
@@ -260,15 +280,18 @@
             var components = [];
             for(var i=0; i<polygons.length; ++i) {
                 polygon = polygons[i].replace(this.regExes.trimParens, '$1');
-                components.push(this.parse.polygon.apply(this, [polygon]));
+                components.push(this.parse.polygon.apply(this, [polygon]).geometry);
             }
-            return new OpenLayers.Geometry.MultiPolygon(components);
+            return new OpenLayers.Feature.Vector(
+                new OpenLayers.Geometry.MultiPolygon(components)
+            );
         },
 
         /**
-         * Return an array of geometries given a geometrycollection WKT fragment.
+         * Return an array of features given a geometrycollection WKT fragment.
          * @param {String} A WKT fragment representing the geometrycollection
-         * @returns {Array} An array of OpenLayers.Geometry
+         * @returns {Array} An array of OpenLayers.Feature.Vector
+         * @private
          */
         'geometrycollection': function(str) {
             // separate components of the collection with |

Modified: trunk/openlayers/lib/OpenLayers/Geometry.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Geometry.js	2007-05-18 15:20:58 UTC (rev 3157)
+++ trunk/openlayers/lib/OpenLayers/Geometry.js	2007-05-21 14:24:55 UTC (rev 3158)
@@ -5,6 +5,7 @@
 /**
  * @class
  * @requires OpenLayers/Format/WKT.js
+ * @requires OpenLayers/Feature/Vector.js
  */
 OpenLayers.Geometry = OpenLayers.Class.create();
 OpenLayers.Geometry.prototype = {
@@ -150,7 +151,9 @@
      * @type String
      */
     toString: function() {
-       return OpenLayers.Format.WKT.prototype.write(this);
+        return OpenLayers.Format.WKT.prototype.write(
+            new OpenLayers.Feature.Vector(this)
+        );
     },
 
     /** @final @type String */

Modified: trunk/openlayers/tests/Format/test_WKT.html
===================================================================
--- trunk/openlayers/tests/Format/test_WKT.html	2007-05-18 15:20:58 UTC (rev 3157)
+++ trunk/openlayers/tests/Format/test_WKT.html	2007-05-21 14:24:55 UTC (rev 3158)
@@ -5,37 +5,53 @@
      
     var points = []; 
     for(var i=0; i<12; ++i) { 
-        points.push(new OpenLayers.Geometry.Point(Math.random() * 100, 
-                                                  Math.random() * 100)); 
+        points.push(new OpenLayers.Feature.Vector(
+            new OpenLayers.Geometry.Point(Math.random() * 100,
+                                          Math.random() * 100))
+        ); 
     } 
-    var multipoint = new OpenLayers.Geometry.MultiPoint([ 
-        points[0], points[1], points[2] 
-    ]); 
+    var multipoint = new OpenLayers.Feature.Vector(
+        new OpenLayers.Geometry.MultiPoint([ 
+            points[0].geometry, points[1].geometry, points[2].geometry
+        ])
+    ); 
      
     var linestrings = [ 
-        new OpenLayers.Geometry.LineString([points[0], points[1], points[2]]), 
-        new OpenLayers.Geometry.LineString([points[3], points[4], points[5]]) 
+        new OpenLayers.Feature.Vector(
+            new OpenLayers.Geometry.LineString([points[0].geometry, points[1].geometry, points[2].geometry])
+        ), 
+        new OpenLayers.Feature.Vector(
+            new OpenLayers.Geometry.LineString([points[3].geometry, points[4].geometry, points[5].geometry])
+        )
     ]; 
      
-    var multilinestring = new OpenLayers.Geometry.MultiLineString([ 
-        linestrings[0], linestrings[1] 
-    ]); 
+    var multilinestring = new OpenLayers.Feature.Vector(
+        new OpenLayers.Geometry.MultiLineString([ 
+            linestrings[0].geometry, linestrings[1].geometry
+        ])
+    ); 
  
     var rings = [ 
-        new OpenLayers.Geometry.LinearRing([points[0], points[1], points[2]]), 
-        new OpenLayers.Geometry.LinearRing([points[3], points[4], points[5]]), 
-        new OpenLayers.Geometry.LinearRing([points[6], points[7], points[8]]), 
-        new OpenLayers.Geometry.LinearRing([points[9], points[10], points[11]]) 
+        new OpenLayers.Geometry.LinearRing([points[0].geometry, points[1].geometry, points[2].geometry]), 
+        new OpenLayers.Geometry.LinearRing([points[3].geometry, points[4].geometry, points[5].geometry]), 
+        new OpenLayers.Geometry.LinearRing([points[6].geometry, points[7].geometry, points[8].geometry]), 
+        new OpenLayers.Geometry.LinearRing([points[9].geometry, points[10].geometry, points[11].geometry]) 
     ]; 
  
     var polygons = [ 
-        new OpenLayers.Geometry.Polygon([rings[0], rings[1]]), 
-        new OpenLayers.Geometry.Polygon([rings[2], rings[3]]) 
+        new OpenLayers.Feature.Vector(
+            new OpenLayers.Geometry.Polygon([rings[0], rings[1]])
+        ), 
+        new OpenLayers.Feature.Vector(
+            new OpenLayers.Geometry.Polygon([rings[2], rings[3]])
+        )
     ]; 
      
-    var multipolygon = new OpenLayers.Geometry.MultiPolygon([ 
-        polygons[0], polygons[1] 
-    ]); 
+    var multipolygon = new OpenLayers.Feature.Vector(
+        new OpenLayers.Geometry.MultiPolygon([ 
+            polygons[0].geometry, polygons[1].geometry 
+        ])
+    ); 
      
     var collection = [points[0], linestrings[0]]; 
      
@@ -53,74 +69,74 @@
     function test_Format_WKT_write(t) { 
         t.plan(7); 
         var format = new OpenLayers.Format.WKT(); 
-         
+
         // test a point 
         t.eq(format.write(points[0]), 
-             "POINT(" + points[0].x + " " + points[0].y + ")", 
+             "POINT(" + points[0].geometry.x + " " + points[0].geometry.y + ")", 
              "format correctly writes Point WKT"); 
  
         // test a multipoint 
         t.eq(format.write(multipoint), 
-             "MULTIPOINT(" + points[0].x + " " + points[0].y + "," + 
-                             points[1].x + " " + points[1].y + "," + 
-                             points[2].x + " " + points[2].y + ")", 
+             "MULTIPOINT(" + points[0].geometry.x + " " + points[0].geometry.y + "," + 
+                             points[1].geometry.x + " " + points[1].geometry.y + "," + 
+                             points[2].geometry.x + " " + points[2].geometry.y + ")", 
              "format correctly writes MultiPoint WKT"); 
  
         // test a linestring 
         t.eq(format.write(linestrings[0]), 
-             "LINESTRING(" + points[0].x + " " + points[0].y + "," + 
-                             points[1].x + " " + points[1].y + "," + 
-                             points[2].x + " " + points[2].y + ")", 
+             "LINESTRING(" + points[0].geometry.x + " " + points[0].geometry.y + "," + 
+                             points[1].geometry.x + " " + points[1].geometry.y + "," + 
+                             points[2].geometry.x + " " + points[2].geometry.y + ")", 
              "format correctly writes LineString WKT"); 
  
         // test a multilinestring 
         t.eq(format.write(multilinestring), 
-             "MULTILINESTRING((" + points[0].x + " " + points[0].y + "," + 
-                                   points[1].x + " " + points[1].y + "," + 
-                                   points[2].x + " " + points[2].y + ")," + 
-                             "(" + points[3].x + " " + points[3].y + "," + 
-                                   points[4].x + " " + points[4].y + "," + 
-                                   points[5].x + " " + points[5].y + "))", 
+             "MULTILINESTRING((" + points[0].geometry.x + " " + points[0].geometry.y + "," + 
+                                   points[1].geometry.x + " " + points[1].geometry.y + "," + 
+                                   points[2].geometry.x + " " + points[2].geometry.y + ")," + 
+                             "(" + points[3].geometry.x + " " + points[3].geometry.y + "," + 
+                                   points[4].geometry.x + " " + points[4].geometry.y + "," + 
+                                   points[5].geometry.x + " " + points[5].geometry.y + "))", 
              "format correctly writes MultiLineString WKT"); 
  
         // test a polygon 
         t.eq(format.write(polygons[0]), 
-             "POLYGON((" + points[0].x + " " + points[0].y + "," + 
-                           points[1].x + " " + points[1].y + "," + 
-                           points[2].x + " " + points[2].y + "," + 
-                           points[0].x + " " + points[0].y + ")," + 
-                     "(" + points[3].x + " " + points[3].y + "," + 
-                           points[4].x + " " + points[4].y + "," + 
-                           points[5].x + " " + points[5].y + "," + 
-                           points[3].x + " " + points[3].y + "))", 
+             "POLYGON((" + points[0].geometry.x + " " + points[0].geometry.y + "," + 
+                           points[1].geometry.x + " " + points[1].geometry.y + "," + 
+                           points[2].geometry.x + " " + points[2].geometry.y + "," + 
+                           points[0].geometry.x + " " + points[0].geometry.y + ")," + 
+                     "(" + points[3].geometry.x + " " + points[3].geometry.y + "," + 
+                           points[4].geometry.x + " " + points[4].geometry.y + "," + 
+                           points[5].geometry.x + " " + points[5].geometry.y + "," + 
+                           points[3].geometry.x + " " + points[3].geometry.y + "))", 
              "format correctly writes Polygon WKT"); 
  
         // test a multipolygon 
         t.eq(format.write(multipolygon), 
-             "MULTIPOLYGON(((" + points[0].x + " " + points[0].y + "," + 
-                                 points[1].x + " " + points[1].y + "," + 
-                                 points[2].x + " " + points[2].y + "," + 
-                                 points[0].x + " " + points[0].y + ")," + 
-                           "(" + points[3].x + " " + points[3].y + "," + 
-                                 points[4].x + " " + points[4].y + "," + 
-                                 points[5].x + " " + points[5].y + "," + 
-                                 points[3].x + " " + points[3].y + "))," + 
-                          "((" + points[6].x + " " + points[6].y + "," + 
-                                 points[7].x + " " + points[7].y + "," + 
-                                 points[8].x + " " + points[8].y + "," + 
-                                 points[6].x + " " + points[6].y + ")," + 
-                           "(" + points[9].x + " " + points[9].y + "," + 
-                                 points[10].x + " " + points[10].y + "," + 
-                                 points[11].x + " " + points[11].y + "," + 
-                                 points[9].x + " " + points[9].y + ")))", 
+             "MULTIPOLYGON(((" + points[0].geometry.x + " " + points[0].geometry.y + "," + 
+                                 points[1].geometry.x + " " + points[1].geometry.y + "," + 
+                                 points[2].geometry.x + " " + points[2].geometry.y + "," + 
+                                 points[0].geometry.x + " " + points[0].geometry.y + ")," + 
+                           "(" + points[3].geometry.x + " " + points[3].geometry.y + "," + 
+                                 points[4].geometry.x + " " + points[4].geometry.y + "," + 
+                                 points[5].geometry.x + " " + points[5].geometry.y + "," + 
+                                 points[3].geometry.x + " " + points[3].geometry.y + "))," + 
+                          "((" + points[6].geometry.x + " " + points[6].geometry.y + "," + 
+                                 points[7].geometry.x + " " + points[7].geometry.y + "," + 
+                                 points[8].geometry.x + " " + points[8].geometry.y + "," + 
+                                 points[6].geometry.x + " " + points[6].geometry.y + ")," + 
+                           "(" + points[9].geometry.x + " " + points[9].geometry.y + "," + 
+                                 points[10].geometry.x + " " + points[10].geometry.y + "," + 
+                                 points[11].geometry.x + " " + points[11].geometry.y + "," + 
+                                 points[9].geometry.x + " " + points[9].geometry.y + ")))", 
              "format correctly writes MultiPolygon WKT"); 
          
         // test a geometrycollection 
         t.eq(format.write(collection), 
-             "GEOMETRYCOLLECTION(POINT(" + points[0].x + " " + points[0].y + ")," + 
-                                "LINESTRING(" + points[0].x + " " + points[0].y + "," + 
-                                                points[1].x + " " + points[1].y + "," + 
-                                                points[2].x + " " + points[2].y + "))", 
+             "GEOMETRYCOLLECTION(POINT(" + points[0].geometry.x + " " + points[0].geometry.y + ")," + 
+                                "LINESTRING(" + points[0].geometry.x + " " + points[0].geometry.y + "," + 
+                                                points[1].geometry.x + " " + points[1].geometry.y + "," + 
+                                                points[2].geometry.x + " " + points[2].geometry.y + "))", 
              "format correctly writes GeometryCollection WKT"); 
  
     } 
@@ -134,35 +150,35 @@
          */ 
  
         // test a point 
-        t.ok(points[0].equals(format.read(format.write(points[0]))), 
+        t.ok(points[0].geometry.equals(format.read(format.write(points[0])).geometry), 
              "format correctly reads Point WKT"); 
- 
+
         // test a multipoint 
-        t.ok(multipoint.equals(format.read(format.write(multipoint))), 
+        t.ok(multipoint.geometry.equals(format.read(format.write(multipoint)).geometry), 
              "format correctly reads MultiPoint WKT"); 
  
         // test a linestring 
-        t.ok(linestrings[0].equals(format.read(format.write(linestrings[0]))), 
+        t.ok(linestrings[0].geometry.equals(format.read(format.write(linestrings[0])).geometry), 
              "format correctly reads LineString WKT"); 
  
         // test a multilinestring 
-        t.ok(multilinestring.equals(format.read(format.write(multilinestring))), 
+        t.ok(multilinestring.geometry.equals(format.read(format.write(multilinestring)).geometry), 
              "format correctly reads MultiLineString WKT"); 
  
         // test a polygon 
-        t.ok(polygons[0].equals(format.read(format.write(polygons[0]))), 
+        t.ok(polygons[0].geometry.equals(format.read(format.write(polygons[0])).geometry), 
              "format correctly reads Polygon WKT"); 
  
         // test a multipolygon 
-        t.ok(multipolygon.equals(format.read(format.write(multipolygon))), 
+        t.ok(multipolygon.geometry.equals(format.read(format.write(multipolygon)).geometry), 
              "format correctly reads MultiPolygon WKT"); 
          
         // test a geometrycollection 
         t.eq(format.write(collection), 
-             "GEOMETRYCOLLECTION(POINT(" + points[0].x + " " + points[0].y + ")," + 
-                                "LINESTRING(" + points[0].x + " " + points[0].y + "," + 
-                                                points[1].x + " " + points[1].y + "," + 
-                                                points[2].x + " " + points[2].y + "))", 
+             "GEOMETRYCOLLECTION(POINT(" + points[0].geometry.x + " " + points[0].geometry.y + ")," + 
+                                "LINESTRING(" + points[0].geometry.x + " " + points[0].geometry.y + "," + 
+                                                points[1].geometry.x + " " + points[1].geometry.y + "," + 
+                                                points[2].geometry.x + " " + points[2].geometry.y + "))", 
              "format correctly writes GeometryCollection WKT"); 
  
     } 



More information about the Commits mailing list