# -*- coding: utf-8 -*- # Copyright 2011 Google Inc. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Implementation of gsutil version command.""" from __future__ import absolute_import from hashlib import md5 import os import platform import re import sys import boto import crcmod import gslib from gslib.command import Command from gslib.util import CheckMultiprocessingAvailableAndInit from gslib.util import GetConfigFilePath from gslib.util import UsingCrcmodExtension _SYNOPSIS = """ gsutil version """ _DETAILED_HELP_TEXT = (""" <B>SYNOPSIS</B> """ + _SYNOPSIS + """ <B>DESCRIPTION</B> Prints information about the version of gsutil. <B>OPTIONS</B> -l Prints additional information, such as the version of Python being used, the version of the Boto library, a checksum of the code, the path to gsutil, and the path to gsutil's configuration file. """) class VersionCommand(Command): """Implementation of gsutil version command.""" # Command specification. See base class for documentation. command_spec = Command.CreateCommandSpec( 'version', command_name_aliases=['ver'], usage_synopsis=_SYNOPSIS, min_args=0, max_args=0, supported_sub_args='l', file_url_ok=False, provider_url_ok=False, urls_start_arg=0, ) # Help specification. See help_provider.py for documentation. help_spec = Command.HelpSpec( help_name='version', help_name_aliases=['ver'], help_type='command_help', help_one_line_summary='Print version info about gsutil', help_text=_DETAILED_HELP_TEXT, subcommand_help_text={}, ) def RunCommand(self): """Command entry point for the version command.""" long_form = False if self.sub_opts: for o, _ in self.sub_opts: if o == '-l': long_form = True config_path = GetConfigFilePath() shipped_checksum = gslib.CHECKSUM try: cur_checksum = self._ComputeCodeChecksum() except IOError: cur_checksum = 'MISSING FILES' if shipped_checksum == cur_checksum: checksum_ok_str = 'OK' else: checksum_ok_str = '!= %s' % shipped_checksum sys.stdout.write('gsutil version: %s\n' % gslib.VERSION) if long_form: long_form_output = ( 'checksum: {checksum} ({checksum_ok})\n' 'boto version: {boto_version}\n' 'python version: {python_version}\n' 'OS: {os_version}\n' 'multiprocessing available: {multiprocessing_available}\n' 'using cloud sdk: {cloud_sdk}\n' 'config path: {config_path}\n' 'gsutil path: {gsutil_path}\n' 'compiled crcmod: {compiled_crcmod}\n' 'installed via package manager: {is_package_install}\n' 'editable install: {is_editable_install}\n' ) sys.stdout.write(long_form_output.format( checksum=cur_checksum, checksum_ok=checksum_ok_str, boto_version=boto.__version__, python_version=sys.version.replace('\n', ''), os_version='%s %s' % (platform.system(), platform.release()), multiprocessing_available=( CheckMultiprocessingAvailableAndInit().is_available), cloud_sdk=(os.environ.get('CLOUDSDK_WRAPPER') == '1'), config_path=config_path, gsutil_path=gslib.GSUTIL_PATH, compiled_crcmod=UsingCrcmodExtension(crcmod), is_package_install=gslib.IS_PACKAGE_INSTALL, is_editable_install=gslib.IS_EDITABLE_INSTALL, )) return 0 def _ComputeCodeChecksum(self): """Computes a checksum of gsutil code. This checksum can be used to determine if users locally modified gsutil when requesting support. (It's fine for users to make local mods, but when users ask for support we ask them to run a stock version of gsutil so we can reduce possible variables.) Returns: MD5 checksum of gsutil code. """ if gslib.IS_PACKAGE_INSTALL: return 'PACKAGED_GSUTIL_INSTALLS_DO_NOT_HAVE_CHECKSUMS' m = md5() # Checksum gsutil and all .py files under gslib directory. files_to_checksum = [gslib.GSUTIL_PATH] for root, _, files in os.walk(gslib.GSLIB_DIR): for filepath in files: if filepath.endswith('.py'): files_to_checksum.append(os.path.join(root, filepath)) # Sort to ensure consistent checksum build, no matter how os.walk # orders the list. for filepath in sorted(files_to_checksum): f = open(filepath, 'r') content = f.read() content = re.sub(r'(\r\n|\r|\n)', '\n', content) m.update(content) f.close() return m.hexdigest()