OLD | NEW |
(Empty) | |
| 1 # Copyright 2011 Google Inc. All Rights Reserved. |
| 2 # |
| 3 # Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 # you may not use this file except in compliance with the License. |
| 5 # You may obtain a copy of the License at |
| 6 # |
| 7 # http://www.apache.org/licenses/LICENSE-2.0 |
| 8 # |
| 9 # Unless required by applicable law or agreed to in writing, software |
| 10 # distributed under the License is distributed on an "AS IS" BASIS, |
| 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 # See the License for the specific language governing permissions and |
| 13 # limitations under the License. |
| 14 |
| 15 import boto |
| 16 import os |
| 17 import re |
| 18 import sys |
| 19 |
| 20 from boto.pyami.config import BotoConfigLocations |
| 21 from gslib.command import Command |
| 22 from gslib.command import COMMAND_NAME |
| 23 from gslib.command import COMMAND_NAME_ALIASES |
| 24 from gslib.command import CONFIG_REQUIRED |
| 25 from gslib.command import FILE_URIS_OK |
| 26 from gslib.command import MAX_ARGS |
| 27 from gslib.command import MIN_ARGS |
| 28 from gslib.command import PROVIDER_URIS_OK |
| 29 from gslib.command import SUPPORTED_SUB_ARGS |
| 30 from gslib.command import URIS_START_ARG |
| 31 from gslib.help_provider import HELP_NAME |
| 32 from gslib.help_provider import HELP_NAME_ALIASES |
| 33 from gslib.help_provider import HELP_ONE_LINE_SUMMARY |
| 34 from gslib.help_provider import HELP_TEXT |
| 35 from gslib.help_provider import HelpType |
| 36 from gslib.help_provider import HELP_TYPE |
| 37 from hashlib import md5 |
| 38 |
| 39 _detailed_help_text = (""" |
| 40 <B>SYNOPSIS</B> |
| 41 gsutil version |
| 42 |
| 43 |
| 44 <B>DESCRIPTION</B> |
| 45 Prints information about the version of gsutil, boto, and Python being |
| 46 run on your system. |
| 47 """) |
| 48 |
| 49 |
| 50 class VersionCommand(Command): |
| 51 """Implementation of gsutil version command.""" |
| 52 |
| 53 # Command specification (processed by parent class). |
| 54 command_spec = { |
| 55 # Name of command. |
| 56 COMMAND_NAME : 'version', |
| 57 # List of command name aliases. |
| 58 COMMAND_NAME_ALIASES : ['ver'], |
| 59 # Min number of args required by this command. |
| 60 MIN_ARGS : 0, |
| 61 # Max number of args required by this command, or NO_MAX. |
| 62 MAX_ARGS : 0, |
| 63 # Getopt-style string specifying acceptable sub args. |
| 64 SUPPORTED_SUB_ARGS : '', |
| 65 # True if file URIs acceptable for this command. |
| 66 FILE_URIS_OK : False, |
| 67 # True if provider-only URIs acceptable for this command. |
| 68 PROVIDER_URIS_OK : False, |
| 69 # Index in args of first URI arg. |
| 70 URIS_START_ARG : 0, |
| 71 # True if must configure gsutil before running command. |
| 72 CONFIG_REQUIRED : False, |
| 73 } |
| 74 help_spec = { |
| 75 # Name of command or auxiliary help info for which this help applies. |
| 76 HELP_NAME : 'version', |
| 77 # List of help name aliases. |
| 78 HELP_NAME_ALIASES : ['ver'], |
| 79 # Type of help: |
| 80 HELP_TYPE : HelpType.COMMAND_HELP, |
| 81 # One line summary of this help. |
| 82 HELP_ONE_LINE_SUMMARY : 'Print version info about gsutil', |
| 83 # The full help text. |
| 84 HELP_TEXT : _detailed_help_text, |
| 85 } |
| 86 |
| 87 # Command entry point. |
| 88 def RunCommand(self): |
| 89 for path in BotoConfigLocations: |
| 90 f = None |
| 91 try: |
| 92 f = open(path, 'r') |
| 93 break |
| 94 except IOError: |
| 95 pass |
| 96 finally: |
| 97 if f: |
| 98 f.close() |
| 99 else: |
| 100 path = "no config found" |
| 101 |
| 102 try: |
| 103 f = open(os.path.join(self.gsutil_bin_dir, 'CHECKSUM')) |
| 104 shipped_checksum = f.read().strip() |
| 105 f.close() |
| 106 except IOError: |
| 107 shipped_checksum = 'MISSING' |
| 108 try: |
| 109 cur_checksum = self._ComputeCodeChecksum() |
| 110 except IOError: |
| 111 cur_checksum = 'MISSING FILES' |
| 112 if shipped_checksum == cur_checksum: |
| 113 checksum_ok_str = 'OK' |
| 114 else: |
| 115 checksum_ok_str = '!= %s' % shipped_checksum |
| 116 sys.stderr.write( |
| 117 'gsutil version %s\nchecksum %s (%s)\n' |
| 118 'boto version %s\npython version %s\n' |
| 119 'config path: %s\ngsutil path: %s\n' % ( |
| 120 self.gsutil_ver, cur_checksum, checksum_ok_str, |
| 121 boto.__version__, sys.version, path, os.path.realpath(sys.argv[0]))) |
| 122 |
| 123 return 0 |
| 124 |
| 125 def _ComputeCodeChecksum(self): |
| 126 """ |
| 127 Computes a checksum of gsutil code so we can see if users locally modified |
| 128 gsutil when requesting support. (It's fine for users to make local mods, |
| 129 but when users ask for support we ask them to run a stock version of |
| 130 gsutil so we can reduce possible variables.) |
| 131 """ |
| 132 m = md5() |
| 133 # Checksum gsutil and all .py files under gsutil bin (including bundled |
| 134 # libs). Although we will eventually make gsutil allow use of a centrally |
| 135 # installed boto (once boto shifts to more frequent releases), in that case |
| 136 # the local copies still should not have any user modifications. |
| 137 files_to_checksum = [os.path.join(self.gsutil_bin_dir, 'gsutil')] |
| 138 for root, sub_folders, files in os.walk(self.gsutil_bin_dir): |
| 139 for file in files: |
| 140 if file[-3:] == '.py': |
| 141 files_to_checksum.append(os.path.join(root, file)) |
| 142 # Sort to ensure consistent checksum build, no matter how os.walk |
| 143 # orders the list. |
| 144 for file in sorted(files_to_checksum): |
| 145 f = open(file, 'r') |
| 146 content = f.read() |
| 147 content = re.sub(r'(\r\n|\r|\n)', '\n', content) |
| 148 m.update(content) |
| 149 f.close() |
| 150 return m.hexdigest() |
OLD | NEW |