| 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 |