Adjustments to cros_gestures for external partner use.

Relax validation to allow mix-dir manifest filenames.

Improve environment script to setup for building the untrusted bundle
using run_remote_tool.

Also avoid new conflict with hardware_Trackpad/constants by disambiguating
constants.

BUG=chromium-os:29901
TEST=ran local cros_gestures commands on test machine.

Change-Id: I3fd97c270cf9d92cca513cb4b6a5644c74d8b0f3
Reviewed-on: https://gerrit.chromium.org/gerrit/20902
Tested-by: Mike Truty <truty@chromium.org>
Commit-Ready: Mike Truty <truty@chromium.org>
Reviewed-by: Mike Truty <truty@chromium.org>
diff --git a/cros_gestures/README b/cros_gestures/README
index f04f07f..48f95e5 100644
--- a/cros_gestures/README
+++ b/cros_gestures/README
@@ -4,31 +4,43 @@
 The command line tool is modeled very closely on (and depends) on the Google
 Storage command line client (gsutil).
 
-Contents:
+CONTENTS:
  - cros_gestures is the command line tool
  - setup_cros_gestures.sh helps establish proper environment variables to find
    both gsutil and the needed .boto file for authentication.
+ - run_remote_tool builds a bundle to install on a test machine (and can
+   run it on a test machine).
+ - remote/install_cros_gestures.py can setup a test machine from the public,
+   untrusted bundle.
 
-For more information on installing and using gsutil, see
+FOR MORE INFORMATION ON INSTALLING AND USING GSUTIL, SEE:
 <http://code.google.com/apis/storage/docs/gsutil.html>.
 
-To install gsutils:
+TO INSTALL GSUTILS:
  - cd ~
  - wget http://commondatastorage.googleapis.com/pub/gsutil.tar.gz
  - gzip -d gsutil.tar.gz
  - tar -xvf gsutil.tar
 
-To install cros_gestures:
-...git clone
+TO BUILD A TRUSTED PACKAGE TO ./CROS_GESTURES.TAR.BZ2:
+ - . ./setup_cros_gestures.sh trusted
+ - ./run_remote_tool
 
-To install cros_gestures_boto:
-...git clone
+TO BUILD AN UNTRUSTED PACKAGE TO ./CROS_GESTURES.TAR.BZ2:
+ - . ./setup_cros_gestures.sh untrusted
+ - ./run_remote_tool
 
-DEPLOYMENT PLAN:
+TO DEPLOY THE BUNDLES:
+ - gsutil cp /tmp/cros_gestures.tar.bz2  \
+       gs://chromeos-gestures-valid/downloads/untrusted/cros_gestures.tar.bz2
+ - gsutil cp /tmp/install_cros_gestures.py  \
+       gs://chromeos-gestures-valid/downloads/untrusted/install_cros_gestures.py
+ - gsutil setacl public-read \
+       gs://chromeos-gestures-valid/downloads/untrusted/cros_gestures.tar.bz2
+ - gsutil setacl public-read \
+       gs://chromeos-gestures-valid/downloads/untrusted/install_cros_gestures.py
 
-cros_gestures
--cros_gestures
--cros_gestures_boto
--gsutil
-
-Fix environment variables in ./setup_cros_gestures.sh.
+TO INSTALL CROS_GESTURES TO /USR/LOCAL/CROS_GESTURES (TEST MACHINES):
+ - cd /tmp
+ - wget http://chromeos-gestures-valid.commondatastorage.googleapis.com/downloads/untrusted/install_cros_gestures.py
+ - python ./install_cros_gestures.py
diff --git a/cros_gestures/cros_gestures b/cros_gestures/cros_gestures
index 66c2920..de24fd7 100755
--- a/cros_gestures/cros_gestures
+++ b/cros_gestures/cros_gestures
@@ -1,5 +1,5 @@
 #!/usr/bin/python
-# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
@@ -18,7 +18,7 @@
 import signal
 import sys
 
-import constants
+import cros_gestures_constants
 import cros_gestures_logging
 import cros_gestures_utils
 from exception import CrosGesturesException
@@ -87,7 +87,7 @@
 options, args, command_string = cros_gestures_options.ParseArgs(USAGE_STRING,
                                                                 commands)
 cros_gestures_logging.SetupLogging(options)
-if constants.debug > 1:
+if cros_gestures_constants.debug > 1:
   LOG.debug('Using\n\tGSUTIL_BIN_DIR=%s\n\tBOTO_CONFIG=%s.', gsutil_bin_dir,
                                                              boto_config)
   LOG.debug('Accepted funtionalities:\n%s.',
diff --git a/cros_gestures/cros_gestures_admin b/cros_gestures/cros_gestures_admin
index 06f6cbf..f9684d5 100755
--- a/cros_gestures/cros_gestures_admin
+++ b/cros_gestures/cros_gestures_admin
@@ -1,5 +1,5 @@
 #!/usr/bin/python
-# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
@@ -18,7 +18,7 @@
 import signal
 import sys
 
-import constants
+import cros_gestures_constants
 import cros_gestures_logging
 import cros_gestures_utils
 from exception import CrosGesturesException
@@ -74,7 +74,7 @@
                                                                 commands,
                                                                 admin=True)
 cros_gestures_logging.SetupLogging(options)
-if constants.debug > 1:
+if cros_gestures_constants.debug > 1:
   LOG.debug('Using\n\tGSUTIL_BIN_DIR=%s\n\tBOTO_CONFIG=%s.', gsutil_bin_dir,
                                                              boto_config)
   LOG.debug('Accepted funtionalities:\n%s.',
diff --git a/cros_gestures/cros_gestures_commands.py b/cros_gestures/cros_gestures_commands.py
index 24e1024..db395f1 100644
--- a/cros_gestures/cros_gestures_commands.py
+++ b/cros_gestures/cros_gestures_commands.py
@@ -1,5 +1,5 @@
 #!/usr/bin/python
-# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
@@ -9,7 +9,7 @@
 gsutil/gslib/command.py for maximum re-use.
 """
 
-__version__ = '0.9.1'
+__version__ = '1.0.0'
 
 import datetime
 import hashlib
@@ -19,7 +19,7 @@
 import re
 import sys
 
-import constants
+import cros_gestures_constants
 import cros_gestures_utils
 from exception import CrosGesturesException
 
@@ -122,8 +122,6 @@
   """
   options.uploadarea = None  # Create nonexistent attributes
   options.uploadcreated = None
-  # TODO(Truty): handle firmware version in the filename.
-  #              also, possible for no sub-name
   filename_parse = re.compile(
       '([\w]+)-([\w]+)\.[\w.]+-([\w]+)-([\w]+)-([\w]+)')
   m = re.match(filename_parse, source_file)
@@ -153,7 +151,7 @@
   if gs_time:
     options.uploadcreated = datetime.datetime.strptime(
         gs_time, FILE_TIME_FORMAT).strftime(DISPLAY_TIME_FORMAT)
-  # Extra validations
+  # Extra validations.
   if options.uploadfunctionality not in options.config_options:
       raise CrosGesturesException('The config file does not expect this '
                                   'functionality: %s' %
@@ -201,7 +199,7 @@
       raise CrosGesturesException('Please supply a user to MakeGestureUri.')
     if not uri_str:
       raise CrosGesturesException('Unexpected empty uri.')
-    if constants.trusted:
+    if cros_gestures_constants.trusted:
       user_type = 'trusted-dev'
     else:
       user_type = 'untrusted-dev'
diff --git a/cros_gestures/constants.py b/cros_gestures/cros_gestures_constants.py
similarity index 67%
rename from cros_gestures/constants.py
rename to cros_gestures/cros_gestures_constants.py
index 716be52..396fded 100644
--- a/cros_gestures/constants.py
+++ b/cros_gestures/cros_gestures_constants.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
diff --git a/cros_gestures/cros_gestures_logging.py b/cros_gestures/cros_gestures_logging.py
index 03e2e6d..04ac1e7 100644
--- a/cros_gestures/cros_gestures_logging.py
+++ b/cros_gestures/cros_gestures_logging.py
@@ -1,5 +1,5 @@
 #!/usr/bin/python
-# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
@@ -12,7 +12,7 @@
 import logging
 import sys
 
-import constants
+import cros_gestures_constants
 
 
 class NoLoggingFilter(logging.Filter):
@@ -27,9 +27,9 @@
   if options.detaileddebugout or options.debugout:
     logging_level = logging.DEBUG
     if options.detaileddebugout:
-      constants.debug = 3  # from gsutil show httplib headers
+      cros_gestures_constants.debug = 3  # from gsutil show httplib headers
     else:
-      constants.debug = 2  # from gsutil
+      cros_gestures_constants.debug = 2  # from gsutil
   else:
     logging_level = logging.INFO
     # Mute verbose oauth logging.
diff --git a/cros_gestures/cros_gestures_options.py b/cros_gestures/cros_gestures_options.py
index f208e3d..cb7f368 100644
--- a/cros_gestures/cros_gestures_options.py
+++ b/cros_gestures/cros_gestures_options.py
@@ -50,7 +50,11 @@
     msg = 'Unable to find config file: %s.' % trackpad_test_conf
     cros_gestures_utils.OutputAndExit(msg, red=True)
 
-  config_options = {}
+  # 'dir':['mix'] is a custom config entry for a handmade manifest file
+  # with an area of 'mix' and a functionality of 'dir'.
+  # examples: 'mix-dir.all-alex-mary_tut1-20111215_233052'
+  #           'mix-dir.all-alex-user_tut1-20111215_233052'
+  config_options = {'dir': ['mix']}
   for f in read_trackpad_test_conf('functionality_list', path):
     if f.name in config_options.iteritems():
       msg = ('Found a repeated functionality. Please check the conf file '
diff --git a/cros_gestures/cros_gestures_utils.py b/cros_gestures/cros_gestures_utils.py
index 46f2370..c55f6bb 100644
--- a/cros_gestures/cros_gestures_utils.py
+++ b/cros_gestures/cros_gestures_utils.py
@@ -1,5 +1,5 @@
 #!/usr/bin/python
-# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
@@ -15,7 +15,7 @@
 import sys
 import traceback
 
-import constants
+import cros_gestures_constants
 
 
 FILE_PREFIX = 'file://'
@@ -104,7 +104,7 @@
 
   # .boto enforces the trustworthiness - this is just a hint.
   if boto_config.find('untrusted') > -1:
-    constants.trusted = False
+    cros_gestures_constants.trusted = False
 
   # Before importing boto, find where gsutil is installed and include its
   # boto sub-directory at the start of the PYTHONPATH, to ensure the versions of
@@ -132,7 +132,7 @@
   """Called if we fall through all known/handled exceptions.
   Allows us to # print a stacktrace if -D option used.
   """
-  if constants.debug > 2:
+  if cros_gestures_constants.debug > 2:
     stack_trace = traceback.format_exc()
     prefix = color.Color(Color.RED, 'DEBUG: Exception stack trace:')
     OutputAndExit('%s\n    %s\n' % (prefix, re.sub('\\n', '\n    ',
@@ -154,7 +154,7 @@
   """Called when user hits ^C so we can print a brief message.
   This is instead of the normal Python stack trace (unless -D option is used).
   """
-  if constants.debug > 2:
+  if cros_gestures_constants.debug > 2:
     stack_trace = ''.join(traceback.format_list(traceback.extract_stack()))
     prefix = color.Color(Color.RED, 'DEBUG: Caught signal %d - '
                                     'Exception stack trace:' % signal_num)
@@ -218,8 +218,8 @@
   else:
     args = ''
   cmd = ('%s %s %s %s %s %s' % (os.path.join(bin_dir, 'gsutil'),
-                                debug_options[constants.debug], headers,
-                                cmd, sub_opts, args)).strip()
+                                debug_options[cros_gestures_constants.debug],
+                                headers, cmd, sub_opts, args)).strip()
   logger.debug('Running command "%s"', cmd)
   try:
     p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
diff --git a/cros_gestures/remote/install_cros_gestures.py b/cros_gestures/remote/install_cros_gestures.py
index cce26a9..957712d 100755
--- a/cros_gestures/remote/install_cros_gestures.py
+++ b/cros_gestures/remote/install_cros_gestures.py
@@ -1,5 +1,5 @@
 #!/usr/bin/python
-# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
@@ -10,7 +10,7 @@
 """
 
 __author__ = 'truty@chromium.org (Mike Truty)'
-__version__ = '0.9.1'
+__version__ = '1.0.0'
 
 
 import logging
@@ -20,13 +20,15 @@
 import subprocess
 import sys
 import tempfile
+import urlparse
 
 
 LOG = logging.getLogger('cros_gestures')
 
 GESTURES_INSTALL_DIR = '/usr/local/cros_gestures'
 GESTURE_SERVER_URL = (
-    'http://chromeos-gestures.commondatastorage.googleapis.com/downloads')
+    'http://chromeos-gestures-valid.commondatastorage.googleapis.com/'
+    'downloads/untrusted')
 GESTURE_ARCHIVE = 'cros_gestures.tar.bz2'
 
 
@@ -74,7 +76,7 @@
         self.url = repository_url
 
 
-    def _QuickHttpTest(self, custom_quick_url=None):
+    def _QuickHttpTest(self):
         """ Run a simple 30 second wget on the repository to see if it is
         reachable. This avoids the need to wait for a full 10min timeout.
         """
@@ -84,8 +86,10 @@
 
         try:
             # build up a wget command
-            if custom_quick_url:
-                try_url = custom_quick_url
+            if self.url == GESTURE_SERVER_URL:
+                parts = urlparse.urlparse(self.url)
+                try_url = urlparse.urlunparse([parts.scheme, parts.netloc, '',
+                                               None, None, None])
             else:
                 try_url = self.url
             http_cmd = self.wget_cmd_pattern % (try_url, dest_file_path)
@@ -99,12 +103,12 @@
             temp_file.close()
 
 
-    def FetchPkgFile(self, filename, dest_path, custom_quick_url=None):
+    def FetchPkgFile(self, filename, dest_path):
         logging.info('Fetching %s from %s to %s', filename, self.url,
                      dest_path)
 
         # do a quick test to verify the repo is reachable
-        self._QuickHttpTest(custom_quick_url=custom_quick_url)
+        self._QuickHttpTest()
 
         # try to retrieve the package via http
         package_url = os.path.join(self.url, filename)
@@ -157,10 +161,7 @@
 def DownloadPackage(repo_url, package_name, install_dir):
     """Download a package."""
     fetcher = HttpFetcher(repo_url)
-    # gs urls don't allow quick fetch because directories are not full
-    # download targets - rather they are just members of a namespace hierarchy.
-    fetcher.FetchPkgFile(package_name, install_dir,
-                         custom_quick_url='/'.join(repo_url.split('/')[0:-1]))
+    fetcher.FetchPkgFile(package_name, install_dir)
 
 
 def InstallPackage(source_dir, package_name, install_dir):
diff --git a/cros_gestures/run_remote_tool b/cros_gestures/run_remote_tool
index 1d72abd..8f315b6 100755
--- a/cros_gestures/run_remote_tool
+++ b/cros_gestures/run_remote_tool
@@ -51,9 +51,10 @@
   # Copy gsutil
   shutil.copytree(os.path.abspath(gsutil_bin_dir),
                   os.path.join(temp_dir, 'cros_gestures', 'gsutil'))
-  # Copy .boto
-  shutil.copyfile(os.path.abspath(boto_config),
-                  os.path.join(temp_dir, 'cros_gestures', '.boto'))
+  # Copy .boto if trusted - otherwise untrusted one already present.
+  if os.environ['BOTO_CONFIG'].find('untrusted') == -1:
+    shutil.copyfile(os.path.abspath(boto_config),
+                    os.path.join(temp_dir, 'cros_gestures', '.boto'))
   return temp_dir
 
 
diff --git a/cros_gestures/setup_cros_gestures.sh b/cros_gestures/setup_cros_gestures.sh
index 54678f8..2cc8d38 100755
--- a/cros_gestures/setup_cros_gestures.sh
+++ b/cros_gestures/setup_cros_gestures.sh
@@ -1,12 +1,13 @@
 #!/bin/bash
 
-# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
 # Script to setup environment variables so that cros_gestures cli can
 # find .boto files for authentication and related gsutil files.
 
+declare SCRIPT_DIR="$(pwd)"
 declare GSUTIL_BASE="$HOME/gsutil"
 declare SRC_BASE="$HOME/cros"
 declare TESTBOTO=\
@@ -25,14 +26,31 @@
   fi
 }
 
+function clear_vars() {
+  for v in BOTO_CONFIG BOTO_VALIDATE_CONFIG GSUTIL_BIN_DIR TRACKPAD_TEST_DIR
+  do
+    unset $v
+  done
+}
+
 echo ---------------------------------------------------------------------
+clear_vars
+if [[ $1 == trusted ]]; then
+  echo "---Setting TRUSTED values"
+  check_and_set_var BOTO_CONFIG \
+      ${TESTBOTO}/trusted_dev/chromeos.gestures.trusted.write.boto file
+  check_and_set_var BOTO_VALIDATE_CONFIG \
+      ${TESTBOTO}/validator/chromeos.gestures.full.boto file
+else
+  echo "---Setting UNTRUSTED values"
+  check_and_set_var BOTO_CONFIG \
+      ${SCRIPT_DIR}/untrusted/chromeos.gestures.untrusted.write.boto file
+fi
+
 check_and_set_var GSUTIL_BIN_DIR ${GSUTIL_BASE} dir
-check_and_set_var BOTO_CONFIG \
-    ${TESTBOTO}/trusted_dev/chromeos.gestures.trusted.write.boto file
-check_and_set_var BOTO_VALIDATE_CONFIG \
-    ${TESTBOTO}/validator/chromeos.gestures.full.boto file
 check_and_set_var TRACKPAD_TEST_DIR \
     ${AUTOTEST_SRC}/client/site_tests/hardware_Trackpad dir
+
 echo Done.
 echo ---------------------------------------------------------------------
 echo "Do not forget to run this as . ./setup_cros_gestures.sh"