Anonymous avatar Anonymous committed a1d31bf

Moved to the 0.2 ak and engine version.

Comments (0)

Files changed (7)

+// Copyright (c) 2009, Anton Korenyushkin
+// All rights reserved.
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above copyright
+//       notice, this list of conditions and the following disclaimer in the
+//       documentation and/or other materials provided with the distribution.
+//     * Neither the name of the author nor the names of contributors may be
+//       used to endorse or promote products derived from this software
+//       without specific prior written permission.
+
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+
+log = new ak.Module('log', '0.1');
+
+
+log.MAX_MESSAGE_LENGTH = 10 * 1024;
+
+
+log.log = function (level, message) {
+  level = +level;
+  if (level % 1 != 0)
+    throw new ak.UsageError('Log level must be integer');
+  message += '';
+  if (message.length > log.MAX_MESSAGE_LENGTH)
+    message = message.substr(0, log.MAX_MESSAGE_LENGTH - 3) + '...';
+  var data = {level: level, message: message};
+  if (ak.app.spot)
+    data.spot = ak.app.spot;
+  var response = ak.requestApp(
+    'log',
+    {
+      method: 'post',
+      data: JSON.stringify(data)
+    });
+  if (response.status != ak.http.CREATED)
+    throw Error(response.content);
+};
+
+
+log.DEBUG    = 10;
+log.INFO     = 20;
+log.WARNING  = 30;
+log.ERROR    = 40;
+log.CRITICAL = 50;
+
+
+log.debug    = ak.partial(log.log, log.DEBUG);
+log.info     = ak.partial(log.log, log.INFO);
+log.warning  = ak.partial(log.log, log.WARNING);
+log.error    = ak.partial(log.log, log.ERROR);
+log.critical = ak.partial(log.log, log.CRITICAL);
+
+
+log;
+// Copyright (c) 2009, Anton Korenyushkin
+// All rights reserved.
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above copyright
+//       notice, this list of conditions and the following disclaimer in the
+//       documentation and/or other materials provided with the distribution.
+//     * Neither the name of the author nor the names of contributors may be
+//       used to endorse or promote products derived from this software
+//       without specific prior written permission.
+
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+var ak = require('ak', '0.2');
+
+
+exports.MAX_MESSAGE_LENGTH = 10 * 1024;
+
+
+exports.log = function (level, message) {
+  level = +level;
+  if (level % 1 != 0)
+    throw new ak.UsageError('Log level must be integer');
+  message += '';
+  if (message.length > exports.MAX_MESSAGE_LENGTH)
+    message = message.substr(0, exports.MAX_MESSAGE_LENGTH - 3) + '...';
+  var data = {level: level, message: message};
+  if (require.main.spot) {
+    data.owner = require.main.owner;
+    data.spot = require.main.spot;
+  }
+  var response = ak.requestApp(
+    'log',
+    {
+      method: 'post',
+      data: JSON.stringify(data)
+    });
+  if (response.status != ak.http.CREATED)
+    throw Error(response.content);
+};
+
+
+exports.DEBUG    = 10;
+exports.INFO     = 20;
+exports.WARNING  = 30;
+exports.ERROR    = 40;
+exports.CRITICAL = 50;
+
+
+exports.debug    = ak.partial(exports.log, exports.DEBUG);
+exports.info     = ak.partial(exports.log, exports.INFO);
+exports.warning  = ak.partial(exports.log, exports.WARNING);
+exports.error    = ak.partial(exports.log, exports.ERROR);
+exports.critical = ak.partial(exports.log, exports.CRITICAL);

__init__.js

-// Copyright (c) 2009, Anton Korenyushkin
-// All rights reserved.
-
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above copyright
-//       notice, this list of conditions and the following disclaimer in the
-//       documentation and/or other materials provided with the distribution.
-//     * Neither the name of the author nor the names of contributors may be
-//       used to endorse or promote products derived from this software
-//       without specific prior written permission.
-
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND ANY
-// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-// POSSIBILITY OF SUCH DAMAGE.
-
-
-log = new ak.Module('log', '0.1');
-
-
-log.MAX_MESSAGE_LENGTH = 10 * 1024;
-
-
-log.log = function (level, message) {
-  level = +level;
-  if (level % 1 != 0)
-    throw new ak.UsageError('Log level must be integer');
-  message += '';
-  if (message.length > log.MAX_MESSAGE_LENGTH)
-    message = message.substr(0, log.MAX_MESSAGE_LENGTH - 3) + '...';
-  var data = {level: level, message: message};
-  if (ak.app.spot)
-    data.spot = ak.app.spot;
-  var response = ak.requestApp(
-    'log',
-    {
-      method: 'post',
-      data: JSON.stringify(data)
-    });
-  if (response.status != ak.http.CREATED)
-    throw Error(response.content);
-};
-
-
-log.DEBUG    = 10;
-log.INFO     = 20;
-log.WARNING  = 30;
-log.ERROR    = 40;
-log.CRITICAL = 50;
-
-
-log.debug    = ak.partial(log.log, log.DEBUG);
-log.info     = ak.partial(log.log, log.INFO);
-log.warning  = ak.partial(log.log, log.WARNING);
-log.error    = ak.partial(log.log, log.ERROR);
-log.critical = ak.partial(log.log, log.CRITICAL);
-
-
-log;

__main__.js

-// Copyright (c) 2009, Anton Korenyushkin
-// All rights reserved.
-
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above copyright
-//       notice, this list of conditions and the following disclaimer in the
-//       documentation and/or other materials provided with the distribution.
-//     * Neither the name of the author nor the names of contributors may be
-//       used to endorse or promote products derived from this software
-//       without specific prior written permission.
-
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND ANY
-// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-// POSSIBILITY OF SUCH DAMAGE.
-
-ak.use('ak', '0.1');
-ak.update(this, ak);
-
-include('__init__.js');
-include('tests.js');
-
-
-var EMPTY_MESSAGE_SIZE = 20;
-var MAX_LOG_SIZE = 1024 * 1024;
-var MAX_SPOT_NUMBER = 5;
-var DELETE_NUMBER = 10;
-
-
-function init() {
-  db.create(
-    'Place',
-    {
-      id: 'unique serial',
-      app: 'string',
-      owner: 'string',
-      spot: 'string',
-      count: 'integer',
-      size: 'integer'
-    },
-    'check (owner && spot) || (!owner && !spot)',
-    'unique [app, owner, spot]');
-  db.create(
-    'Record',
-    {
-      id: 'unique serial',
-      date: 'date',
-      level: 'integer',
-      message: 'string',
-      place: 'integer -> Place.id'
-    });
-}
-
-
-var IndexHandler = Handler.subclass(
-  {
-    get: function (request) {
-      return render(
-        'index.html',
-        {
-          request: request,
-          groups: [
-            {header: 'Admined Apps', apps: getAdminedApps(request.user)},
-            {header: 'Developed Apps', apps: getDevelopedApps(request.user)}
-          ]
-        });
-    }
-  }).decorated(loggingIn);
-
-
-function describeApp(app) {
-  try {
-    return getAppDescription(app);
-  } catch (error) {
-    throw (error instanceof NoSuchAppError
-           ? NotFound('No such app: ' + repr(app))
-           : error);
-  }
-}
-
-
-function develops(user, appDescr) {
-  return user == appDescr.admin || appDescr.developers.indexOf(user) != -1;
-}
-
-
-var LogHandler = IndexHandler.subclass(
-  {
-    get: function (request, app, owner, spot) {
-      var appDescr = describeApp(app);
-      if (!develops(request.user, appDescr))
-        throw Forbidden('You are not a developer of ' + app + ' app');
-      owner = (owner || request.get.owner || request.user).replace(/-/g, ' ');
-      if (!develops(owner, appDescr))
-        throw NotFound(owner + ' is not a developer of ' + app + ' app');
-      spot = spot || '';
-      var places = rv.Place.where({app: app}).get(
-        {by: ['spot != ""', 'owner != $', 'owner', 'spot']}, request.user);
-      var releasePlace = (places.length && !places[0].spot
-                          ? places.shift()
-                          : {count: 0});
-      var place;
-      if (spot) {
-        for (var i = 0; i < places.length; ++i) {
-          if (places[i].owner == owner && places[i].spot == spot) {
-            place = places[i];
-            break;
-          }
-        }
-        if (!place)
-          throw NotFound('Spot ' + spot + ' has no logs');
-      } else {
-        place = releasePlace;
-      }
-      records = (place.count
-                 ? rv.Record.where({place: place.id}).get({by: '-id'})
-                 : []);
-      return render(
-        'log.html',
-        {
-          request: request,
-          app: app,
-          owner: owner,
-          isAdmin: request.user == appDescr.admin,
-          spot: spot,
-          count: place.count,
-          releasePlace: releasePlace,
-          spotPlaces: places,
-          records: records
-        });
-    },
-
-    post: function (request, app, owner, spot) {
-      var delSpot = request.post.spot || '';
-      if (!(delSpot || request.user == describeApp(app).admin))
-        throw Forbidden();
-      var place = rv.Place.where(
-        {
-          app: app,
-          owner: delSpot ? request.user : '',
-          spot: delSpot
-        }).getOne();
-      rv.Record.where({place: place.id}).del();
-      rv.Place.where({id: place.id}).del();
-      return redirect(
-        spot && spot == delSpot && request.user == owner.replace(/-/g, ' ')
-        ? reverse('release', app)
-        : '.');
-    }
-  });
-
-
-__root__ = new URLMap(
-  IndexHandler, 'index',
-  ['', LogHandler, 'release',
-   ['',
-    ['', LogHandler, 'spot']]]);
-
-
-function __main__(request) {
-  if (!request.issuer)
-    return defaultServe(request);
-  if (request.method != 'post')
-    return new Response('', http.METHOD_NOT_ALLOWED);
-  if (request.path != '/')
-    return new Response('', http.NOT_FOUND);
-  try {
-    var data = JSON.parse(request.data);
-  } catch (error) {
-    return new Response(error.message, http.BAD_REQUEST);
-  }
-  if (typeof(data.level) != 'number' || data.level % 1 != 0)
-    return new Response('Level must be integer', http.BAD_REQUEST);
-  if (data.message.length > log.MAX_MESSAGE_LENGTH)
-    return new Response('Max message length is ' + log.MAX_MESSAGE_LENGTH,
-                        http.BAD_REQUEST);
-  var place = {
-    app: request.issuer,
-    owner: data.spot ? data.spot.owner : '',
-    spot: data.spot ? data.spot.name : ''
-  };
-  place = rv.Place.where(place).get()[0] || place;
-  if (place.count) {
-    place.size += EMPTY_MESSAGE_SIZE + data.message.length;
-    ++place.count;
-    while (place.size > MAX_LOG_SIZE) {
-      var parts = [];
-      rv.Record.where({place: place.id}).get(
-        {by: 'id', length: DELETE_NUMBER}).forEach(
-          function (record) {
-            parts.push('id==' + record.id);
-            place.size -= EMPTY_MESSAGE_SIZE + record.message.length;
-            --place.count;
-          });
-      rv.Record.where(parts.join('||')).del();
-    }
-    rv.Place.where({id: place.id}).update(
-      {size: place.size, count: place.count});
-  } else {
-    if (place.owner &&
-        rv.Place.where(
-          {app: place.app, owner: place.owner}).count() >= MAX_SPOT_NUMBER)
-      return new Response(
-        'Please clear logs of deleted spots before proceeding', http.FORBIDDEN);
-    place = rv.Place.insert(
-      place.update({count: 1, size: EMPTY_MESSAGE_SIZE + data.message.length}));
-  }
-  rv.Record.insert(
-    {
-      date: new Date(),
-      level: data.level,
-      message: data.message,
-      place: place.id
-    });
-  return new Response('', http.CREATED);
-}
+// Copyright (c) 2009, Anton Korenyushkin
+// All rights reserved.
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above copyright
+//       notice, this list of conditions and the following disclaimer in the
+//       documentation and/or other materials provided with the distribution.
+//     * Neither the name of the author nor the names of contributors may be
+//       used to endorse or promote products derived from this software
+//       without specific prior written permission.
+
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+require('ak', '0.2').setup();
+var log = require('0.2/index');
+exports.tests = require('tests');
+
+
+exports.EMPTY_MESSAGE_SIZE = 20;
+exports.MAX_LOG_SIZE = 1024 * 1024;
+exports.MAX_SPOT_NUMBER = 5;
+exports.DELETE_NUMBER = 10;
+
+
+exports.init = function () {
+  rv.Place.create(
+    {
+      id: 'unique serial',
+      app: 'string',
+      owner: 'string',
+      spot: 'string',
+      count: 'integer',
+      size: 'integer'
+    },
+    'check (owner && spot) || (!owner && !spot)',
+    'unique [app, owner, spot]');
+  rv.Record.create(
+    {
+      id: 'unique serial',
+      date: 'date',
+      level: 'integer',
+      message: 'string',
+      place: 'integer -> Place.id'
+    });
+};
+
+
+var IndexHandler = Handler.subclass(
+  {
+    get: function (request) {
+      return render(
+        'index.html',
+        {
+          request: request,
+          groups: [
+            {header: 'Admined Apps', apps: getAdminedApps(request.user)},
+            {header: 'Developed Apps', apps: getDevelopedApps(request.user)}
+          ]
+        });
+    }
+  }).decorated(loggingIn);
+
+
+function describeApp(app) {
+  try {
+    return getAppDescription(app);
+  } catch (error) {
+    throw (error instanceof NoSuchAppError
+           ? NotFound('No such app: ' + repr(app))
+           : error);
+  }
+}
+
+
+function develops(user, appDescr) {
+  return user == appDescr.admin || appDescr.developers.indexOf(user) != -1;
+}
+
+
+var LogHandler = IndexHandler.subclass(
+  {
+    get: function (request, app, owner, spot) {
+      var appDescr = describeApp(app);
+      if (!develops(request.user, appDescr))
+        throw Forbidden('You are not a developer of ' + app + ' app');
+      owner = (owner || request.get.owner || request.user).replace(/-/g, ' ');
+      if (!develops(owner, appDescr))
+        throw NotFound(owner + ' is not a developer of ' + app + ' app');
+      spot = spot || '';
+      var places = rv.Place.where({app: app}).get(
+        {by: ['spot != ""', 'owner != $', 'owner', 'spot']}, request.user);
+      var releasePlace = (places.length && !places[0].spot
+                          ? places.shift()
+                          : {count: 0});
+      var place;
+      if (spot) {
+        for (var i = 0; i < places.length; ++i) {
+          if (places[i].owner == owner && places[i].spot == spot) {
+            place = places[i];
+            break;
+          }
+        }
+        if (!place)
+          throw NotFound('Spot ' + spot + ' has no logs');
+      } else {
+        place = releasePlace;
+      }
+      records = (place.count
+                 ? rv.Record.where({place: place.id}).get({by: '-id'})
+                 : []);
+      return render(
+        'log.html',
+        {
+          request: request,
+          app: app,
+          owner: owner,
+          isAdmin: request.user == appDescr.admin,
+          spot: spot,
+          count: place.count,
+          releasePlace: releasePlace,
+          spotPlaces: places,
+          records: records
+        });
+    },
+
+    post: function (request, app, owner, spot) {
+      var delSpot = request.post.spot || '';
+      if (!(delSpot || request.user == describeApp(app).admin))
+        throw Forbidden();
+      var place = rv.Place.where(
+        {
+          app: app,
+          owner: delSpot ? request.user : '',
+          spot: delSpot
+        }).getOne();
+      rv.Record.where({place: place.id}).del();
+      rv.Place.where({id: place.id}).del();
+      return redirect(
+        spot && spot == delSpot && request.user == owner.replace(/-/g, ' ')
+        ? reverse('release', app)
+        : '.');
+    }
+  });
+
+
+exports.root = new URLMap(
+  IndexHandler, 'index',
+  ['', LogHandler, 'release',
+   ['',
+    ['', LogHandler, 'spot']]]);
+
+
+exports.main = function (request) {
+  if (!request.issuer)
+    return defaultServe(request);
+  if (request.method != 'post')
+    return new Response('', http.METHOD_NOT_ALLOWED);
+  if (request.path != '/')
+    return new Response('', http.NOT_FOUND);
+  try {
+    var data = JSON.parse(request.data);
+  } catch (error) {
+    return new Response(error.message, http.BAD_REQUEST);
+  }
+  if (typeof(data.level) != 'number' || data.level % 1 != 0)
+    return new Response('Level must be integer', http.BAD_REQUEST);
+  if (data.message.length > log.MAX_MESSAGE_LENGTH)
+    return new Response('Max message length is ' + log.MAX_MESSAGE_LENGTH,
+                        http.BAD_REQUEST);
+  var place = {
+    app: request.issuer,
+    owner: data.owner || '',
+    spot: data.spot || ''
+  };
+  place = rv.Place.where(place).get()[0] || place;
+  if (place.count) {
+    place.size += exports.EMPTY_MESSAGE_SIZE + data.message.length;
+    ++place.count;
+    while (place.size > exports.MAX_LOG_SIZE) {
+      var parts = [];
+      rv.Record.where({place: place.id}).get(
+        {by: 'id', length: exports.DELETE_NUMBER}).forEach(
+          function (record) {
+            parts.push('id==' + record.id);
+            place.size -= exports.EMPTY_MESSAGE_SIZE + record.message.length;
+            --place.count;
+          });
+      rv.Record.where(parts.join('||')).del();
+    }
+    rv.Place.where({id: place.id}).update(
+      {size: place.size, count: place.count});
+  } else {
+    if (place.owner &&
+        rv.Place.where(
+          {
+            app: place.app,
+            owner: place.owner
+          }).count() >= exports.MAX_SPOT_NUMBER)
+      return new Response(
+        'Please clear logs of deleted spots before proceeding', http.FORBIDDEN);
+    update(place,
+           {
+             count: 1,
+             size: exports.EMPTY_MESSAGE_SIZE + data.message.length
+           });
+    place = rv.Place.insert(place);
+  }
+  rv.Record.insert(
+    {
+      date: new Date(),
+      level: data.level,
+      message: data.message,
+      place: place.id
+    });
+  return new Response('', http.CREATED);
+};

templates/base.html

-{% extends 'ak:0.1/templates/base.html' %}
+{% extends 'ak:0.2/templates/base.html' %}
 
 {% block head %}
   <link rel="stylesheet" href="{% code 'static/main.css' %}" type="text/css">
 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 // POSSIBILITY OF SUCH DAMAGE.
 
+var log = require('0.2/index');
+var main = require('main');
+
 
 function repeat(text, times) {
   var array = [];
 }
 
 
-var LogTestCase = TestCase.subclass(
+exports.LogTestCase = TestCase.subclass(
   {
     setUp: function () {
-      init();
+      main.init();
 
       this._client = new TestClient(
         ['Bob Smith', 'Alice Hacker', 'Ku Bo Ng'],
     },
 
     tearDown: function () {
-      db.drop(keys(rv));
+      db.drop(db.list());
     },
 
     _log: function (app, message, level, owner, spot, status) {
       var object = {level: level || log.DEBUG, message: message};
       if (spot)
-        object.update({spot: {name: spot, owner: owner}});
+        update(object, {owner: owner, spot: spot});
       assertSame(
         this._client.request(
           {
 
     testIndexHandler: function () {
       var groups = this._get('/').context.groups;
-      assertEqual(groups[0].apps, ['useful', 'great']);
+      assertEqual(groups[0].apps, ['great', 'useful']);
       assertEqual(groups[1].apps, ['very-useful']);
       this._client.logout();
       assertSame(this._get('/').status, http.FOUND);
       assertSame(context.spot, '');
       assertSame(context.count, 2);
       assertEqual(context.releasePlace.count, 2);
-      assertEqual(context.releasePlace.size, 2 * EMPTY_MESSAGE_SIZE + 17);
+      assertEqual(context.releasePlace.size, 2 * main.EMPTY_MESSAGE_SIZE + 17);
       assertEqual(
         context.spotPlaces.map(
           function (place) {
       this._log('great', 'hi', log.DEBUG, '', '', http.BAD_REQUEST);
       log.MAX_MESSAGE_LENGTH = oldMaxMessageLength;
 
-      var oldMaxLogSize = MAX_LOG_SIZE;
-      MAX_LOG_SIZE = 3 * EMPTY_MESSAGE_SIZE * DELETE_NUMBER;
-      for (var i = 0; i < 3 * DELETE_NUMBER; ++i)
+      var oldMaxLogSize = main.MAX_LOG_SIZE;
+      main.MAX_LOG_SIZE = 3 * main.EMPTY_MESSAGE_SIZE * main.DELETE_NUMBER;
+      for (var i = 0; i < 3 * main.DELETE_NUMBER; ++i)
         this._log('great', '');
-      assertSame(this._get('/great/').context.count, 3 * DELETE_NUMBER);
-      var chunk = repeat(' ', EMPTY_MESSAGE_SIZE);
-      this._log('great', repeat(chunk, DELETE_NUMBER - 1));
+      assertSame(this._get('/great/').context.count, 3 * main.DELETE_NUMBER);
+      var chunk = repeat(' ', main.EMPTY_MESSAGE_SIZE);
+      this._log('great', repeat(chunk, main.DELETE_NUMBER - 1));
       var place = rv.Place.where({app: 'great', spot: ''}).getOne();
-      assertSame(place.count, 2 * DELETE_NUMBER + 1);
-      assertSame(place.size, MAX_LOG_SIZE);
-      this._log('great', repeat(chunk, DELETE_NUMBER));
+      assertSame(place.count, 2 * main.DELETE_NUMBER + 1);
+      assertSame(place.size, main.MAX_LOG_SIZE);
+      this._log('great', repeat(chunk, main.DELETE_NUMBER));
       place = rv.Place.where({app: 'great', spot: ''}).getOne();
       assertSame(place.count, 2);
-      assertSame(place.size, EMPTY_MESSAGE_SIZE * (2 * DELETE_NUMBER + 1));
-      MAX_LOG_SIZE = oldMaxLogSize;
+      assertSame(place.size,
+                 main.EMPTY_MESSAGE_SIZE * (2 * main.DELETE_NUMBER + 1));
+      main.MAX_LOG_SIZE = oldMaxLogSize;
 
-      for (i = 0; i < MAX_SPOT_NUMBER; ++i)
+      for (i = 0; i < main.MAX_SPOT_NUMBER; ++i)
         this._log('great', '', log.DEBUG, 'Bob Smith', 'spot' + i);
       this._log('great', '', log.DEBUG, 'Bob Smith', 'extra', http.FORBIDDEN);
     },
 
     testLibrary: function () {
       var data;
-      var aspect = weave(InsteadOf, ak, 'requestApp',
+      var aspect = weave(InsteadOf, require('ak', '0.2'), 'requestApp',
                          function (app, request) {
                            assertSame(app, 'log');
                            assertSame(request.method, 'post');
                            return {status: http.CREATED};
                          });
       assertThrow(UsageError, log.log);
-      var oldSpot = ak.app.spot;
-      ak.app.spot = 42;
+      var oldOwner = require.main.owner;
+      var oldSpot = require.main.spot;
+      require.main.owner = 'Alice Hacker';
+      require.main.spot = '42';
       log.debug('hi');
-      assertEqual(items(data).sort(),
-                  [['level', 10], ['message', 'hi'], ['spot', 42]]);
-      delete ak.app.spot;
+      assertEqual(items(data),
+                  [
+                    ['level', 10],
+                    ['message', 'hi'],
+                    ['owner', 'Alice Hacker'],
+                    ['spot', '42']
+                  ]);
+      delete require.main.spot;
+      delete require.main.owner;
       log.log(15, 'hello');
-      assertEqual(items(data).sort(),
-                  [['level', 15], ['message', 'hello']]);
+      assertEqual(items(data), [['level', 15], ['message', 'hello']]);
 
       var oldMaxMessageLength = log.MAX_MESSAGE_LENGTH;
       log.MAX_MESSAGE_LENGTH = 7;
       log.critical('');
       assertSame(data.level, log.CRITICAL);
 
-      ak.app.spot = oldSpot;
+      if (oldSpot) {
+        require.main.owner = oldOwner;
+        require.main.spot = oldSpot;
+      }
       aspect.unweave();
     }
   });
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.