Demo for query storing

Change-Id: I947bcac841992c3f6cfd01ab337c265b0d01cb70
diff --git a/node_modules/grunt-contrib-copy/tasks/copy.js b/node_modules/grunt-contrib-copy/tasks/copy.js
new file mode 100644
index 0000000..bdb476c
--- /dev/null
+++ b/node_modules/grunt-contrib-copy/tasks/copy.js
@@ -0,0 +1,128 @@
+/*
+ * grunt-contrib-copy
+ * http://gruntjs.com/
+ *
+ * Copyright (c) 2016 Chris Talkington, contributors
+ * Licensed under the MIT license.
+ * https://github.com/gruntjs/grunt-contrib-copy/blob/master/LICENSE-MIT
+ */
+
+'use strict';
+
+module.exports = function(grunt) {
+  var path = require('path');
+  var fs = require('fs');
+  var chalk = require('chalk');
+  var fileSyncCmp = require('file-sync-cmp');
+  var isWindows = process.platform === 'win32';
+
+  grunt.registerMultiTask('copy', 'Copy files.', function() {
+
+    var options = this.options({
+      encoding: grunt.file.defaultEncoding,
+      // processContent/processContentExclude deprecated renamed to process/noProcess
+      processContent: false,
+      processContentExclude: [],
+      timestamp: false,
+      mode: false
+    });
+
+    var copyOptions = {
+      encoding: options.encoding,
+      process: options.process || options.processContent,
+      noProcess: options.noProcess || options.processContentExclude
+    };
+
+    var detectDestType = function(dest) {
+      if (grunt.util._.endsWith(dest, '/')) {
+        return 'directory';
+      } else {
+        return 'file';
+      }
+    };
+
+    var unixifyPath = function(filepath) {
+      if (isWindows) {
+        return filepath.replace(/\\/g, '/');
+      } else {
+        return filepath;
+      }
+    };
+
+    var syncTimestamp = function (src, dest) {
+      var stat = fs.lstatSync(src);
+      if (path.basename(src) !== path.basename(dest)) {
+        return;
+      }
+
+      if (stat.isFile() && !fileSyncCmp.equalFiles(src, dest)) {
+        return;
+      }
+
+      var fd = fs.openSync(dest, isWindows ? 'r+' : 'r');
+      fs.futimesSync(fd, stat.atime, stat.mtime);
+      fs.closeSync(fd);
+    };
+
+    var isExpandedPair;
+    var dirs = {};
+    var tally = {
+      dirs: 0,
+      files: 0
+    };
+
+    this.files.forEach(function(filePair) {
+      isExpandedPair = filePair.orig.expand || false;
+
+      filePair.src.forEach(function(src) {
+        src = unixifyPath(src);
+        var dest = unixifyPath(filePair.dest);
+
+        if (detectDestType(dest) === 'directory') {
+          dest = isExpandedPair ? dest : path.join(dest, src);
+        }
+
+        if (grunt.file.isDir(src)) {
+          grunt.verbose.writeln('Creating ' + chalk.cyan(dest));
+          grunt.file.mkdir(dest);
+          if (options.mode !== false) {
+            fs.chmodSync(dest, (options.mode === true) ? fs.lstatSync(src).mode : options.mode);
+          }
+
+          if (options.timestamp) {
+            dirs[dest] = src;
+          }
+
+          tally.dirs++;
+        } else {
+          grunt.verbose.writeln('Copying ' + chalk.cyan(src) + ' -> ' + chalk.cyan(dest));
+          grunt.file.copy(src, dest, copyOptions);
+          syncTimestamp(src, dest);
+          if (options.mode !== false) {
+            fs.chmodSync(dest, (options.mode === true) ? fs.lstatSync(src).mode : options.mode);
+          }
+          tally.files++;
+        }
+      });
+    });
+
+    if (options.timestamp) {
+      Object.keys(dirs).sort(function (a, b) {
+        return b.length - a.length;
+      }).forEach(function (dest) {
+        syncTimestamp(dirs[dest], dest);
+      });
+    }
+
+    if (tally.dirs) {
+      grunt.log.write('Created ' + chalk.cyan(tally.dirs.toString()) + (tally.dirs === 1 ? ' directory' : ' directories'));
+    }
+
+    if (tally.files) {
+      grunt.log.write((tally.dirs ? ', copied ' : 'Copied ') + chalk.cyan(tally.files.toString()) + (tally.files === 1 ? ' file' : ' files'));
+    }
+
+    grunt.log.writeln();
+  });
+
+};