| # -*- 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() |