18d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# -*- coding: utf-8 -*- 28d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# Copyright 2011 Google Inc. All Rights Reserved. 38d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# 48d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# Licensed under the Apache License, Version 2.0 (the "License"); 58d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# you may not use this file except in compliance with the License. 68d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# You may obtain a copy of the License at 78d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# 88d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# http://www.apache.org/licenses/LICENSE-2.0 98d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# 108d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# Unless required by applicable law or agreed to in writing, software 118d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# distributed under the License is distributed on an "AS IS" BASIS, 128d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# See the License for the specific language governing permissions and 148d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# limitations under the License. 158d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi"""Implementation of gsutil version command.""" 168d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 178d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoifrom __future__ import absolute_import 188d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 198d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoifrom hashlib import md5 208d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoiimport os 218d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoiimport platform 228d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoiimport re 238d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoiimport sys 248d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 258d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoiimport boto 268d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoiimport crcmod 278d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoiimport gslib 288d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoifrom gslib.command import Command 29cef7893435aa41160dd1255c43cb8498279738ccChris Craikfrom gslib.util import CheckMultiprocessingAvailableAndInit 308d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoifrom gslib.util import GetConfigFilePath 318d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoifrom gslib.util import UsingCrcmodExtension 328d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 338d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 348d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi_SYNOPSIS = """ 358d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi gsutil version 368d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi""" 378d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 388d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi_DETAILED_HELP_TEXT = (""" 398d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi<B>SYNOPSIS</B> 408d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi""" + _SYNOPSIS + """ 418d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 428d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 438d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi<B>DESCRIPTION</B> 448d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi Prints information about the version of gsutil. 458d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 468d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi<B>OPTIONS</B> 478d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi -l Prints additional information, such as the version of Python 488d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi being used, the version of the Boto library, a checksum of the 498d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi code, the path to gsutil, and the path to gsutil's configuration 508d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi file. 518d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi""") 528d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 538d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 548d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoiclass VersionCommand(Command): 558d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi """Implementation of gsutil version command.""" 568d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 578d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # Command specification. See base class for documentation. 588d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi command_spec = Command.CreateCommandSpec( 598d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 'version', 608d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi command_name_aliases=['ver'], 618d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi usage_synopsis=_SYNOPSIS, 628d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi min_args=0, 638d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi max_args=0, 648d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi supported_sub_args='l', 658d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi file_url_ok=False, 668d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi provider_url_ok=False, 678d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi urls_start_arg=0, 688d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi ) 698d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # Help specification. See help_provider.py for documentation. 708d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi help_spec = Command.HelpSpec( 718d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi help_name='version', 728d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi help_name_aliases=['ver'], 738d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi help_type='command_help', 748d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi help_one_line_summary='Print version info about gsutil', 758d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi help_text=_DETAILED_HELP_TEXT, 768d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi subcommand_help_text={}, 778d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi ) 788d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 798d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi def RunCommand(self): 808d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi """Command entry point for the version command.""" 818d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi long_form = False 828d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi if self.sub_opts: 838d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi for o, _ in self.sub_opts: 848d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi if o == '-l': 858d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi long_form = True 868d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 878d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi config_path = GetConfigFilePath() 888d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 898d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi shipped_checksum = gslib.CHECKSUM 908d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi try: 918d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi cur_checksum = self._ComputeCodeChecksum() 928d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi except IOError: 938d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi cur_checksum = 'MISSING FILES' 948d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi if shipped_checksum == cur_checksum: 958d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi checksum_ok_str = 'OK' 968d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi else: 978d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi checksum_ok_str = '!= %s' % shipped_checksum 988d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 998d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi sys.stdout.write('gsutil version: %s\n' % gslib.VERSION) 1008d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 1018d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi if long_form: 1028d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 1038d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi long_form_output = ( 1048d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 'checksum: {checksum} ({checksum_ok})\n' 1058d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 'boto version: {boto_version}\n' 1068d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 'python version: {python_version}\n' 1078d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 'OS: {os_version}\n' 1088d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 'multiprocessing available: {multiprocessing_available}\n' 1098d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 'using cloud sdk: {cloud_sdk}\n' 1108d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 'config path: {config_path}\n' 1118d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 'gsutil path: {gsutil_path}\n' 1128d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 'compiled crcmod: {compiled_crcmod}\n' 1138d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 'installed via package manager: {is_package_install}\n' 1148d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 'editable install: {is_editable_install}\n' 1158d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi ) 1168d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 1178d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi sys.stdout.write(long_form_output.format( 1188d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi checksum=cur_checksum, 1198d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi checksum_ok=checksum_ok_str, 1208d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi boto_version=boto.__version__, 1218d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi python_version=sys.version.replace('\n', ''), 1228d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi os_version='%s %s' % (platform.system(), platform.release()), 123cef7893435aa41160dd1255c43cb8498279738ccChris Craik multiprocessing_available=( 124cef7893435aa41160dd1255c43cb8498279738ccChris Craik CheckMultiprocessingAvailableAndInit().is_available), 1258d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi cloud_sdk=(os.environ.get('CLOUDSDK_WRAPPER') == '1'), 1268d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi config_path=config_path, 1278d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi gsutil_path=gslib.GSUTIL_PATH, 1288d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi compiled_crcmod=UsingCrcmodExtension(crcmod), 1298d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi is_package_install=gslib.IS_PACKAGE_INSTALL, 1308d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi is_editable_install=gslib.IS_EDITABLE_INSTALL, 1318d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi )) 1328d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 1338d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi return 0 1348d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 1358d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi def _ComputeCodeChecksum(self): 1368d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi """Computes a checksum of gsutil code. 1378d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 1388d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi This checksum can be used to determine if users locally modified 1398d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi gsutil when requesting support. (It's fine for users to make local mods, 1408d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi but when users ask for support we ask them to run a stock version of 1418d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi gsutil so we can reduce possible variables.) 1428d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 1438d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi Returns: 1448d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi MD5 checksum of gsutil code. 1458d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi """ 1468d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi if gslib.IS_PACKAGE_INSTALL: 1478d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi return 'PACKAGED_GSUTIL_INSTALLS_DO_NOT_HAVE_CHECKSUMS' 1488d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi m = md5() 1498d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # Checksum gsutil and all .py files under gslib directory. 1508d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi files_to_checksum = [gslib.GSUTIL_PATH] 1518d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi for root, _, files in os.walk(gslib.GSLIB_DIR): 1528d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi for filepath in files: 1538d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi if filepath.endswith('.py'): 1548d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi files_to_checksum.append(os.path.join(root, filepath)) 1558d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # Sort to ensure consistent checksum build, no matter how os.walk 1568d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # orders the list. 1578d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi for filepath in sorted(files_to_checksum): 1588d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi f = open(filepath, 'r') 1598d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi content = f.read() 1608d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi content = re.sub(r'(\r\n|\r|\n)', '\n', content) 1618d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi m.update(content) 1628d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi f.close() 1638d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi return m.hexdigest() 164