OLD | NEW |
(Empty) | |
| 1 # -*- coding: utf-8 -*- |
| 2 # Copyright 2011 Google Inc. All Rights Reserved. |
| 3 # |
| 4 # Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 # you may not use this file except in compliance with the License. |
| 6 # You may obtain a copy of the License at |
| 7 # |
| 8 # http://www.apache.org/licenses/LICENSE-2.0 |
| 9 # |
| 10 # Unless required by applicable law or agreed to in writing, software |
| 11 # distributed under the License is distributed on an "AS IS" BASIS, |
| 12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 # See the License for the specific language governing permissions and |
| 14 # limitations under the License. |
| 15 """Implementation of gsutil version command.""" |
| 16 |
| 17 from __future__ import absolute_import |
| 18 |
| 19 from hashlib import md5 |
| 20 import os |
| 21 import platform |
| 22 import re |
| 23 import sys |
| 24 |
| 25 import boto |
| 26 import crcmod |
| 27 import gslib |
| 28 from gslib.command import Command |
| 29 from gslib.util import GetConfigFilePath |
| 30 from gslib.util import MultiprocessingIsAvailable |
| 31 from gslib.util import UsingCrcmodExtension |
| 32 |
| 33 |
| 34 _SYNOPSIS = """ |
| 35 gsutil version |
| 36 """ |
| 37 |
| 38 _DETAILED_HELP_TEXT = (""" |
| 39 <B>SYNOPSIS</B> |
| 40 """ + _SYNOPSIS + """ |
| 41 |
| 42 |
| 43 <B>DESCRIPTION</B> |
| 44 Prints information about the version of gsutil. |
| 45 |
| 46 <B>OPTIONS</B> |
| 47 -l Prints additional information, such as the version of Python |
| 48 being used, the version of the Boto library, a checksum of the |
| 49 code, the path to gsutil, and the path to gsutil's configuration |
| 50 file. |
| 51 """) |
| 52 |
| 53 |
| 54 class VersionCommand(Command): |
| 55 """Implementation of gsutil version command.""" |
| 56 |
| 57 # Command specification. See base class for documentation. |
| 58 command_spec = Command.CreateCommandSpec( |
| 59 'version', |
| 60 command_name_aliases=['ver'], |
| 61 usage_synopsis=_SYNOPSIS, |
| 62 min_args=0, |
| 63 max_args=0, |
| 64 supported_sub_args='l', |
| 65 file_url_ok=False, |
| 66 provider_url_ok=False, |
| 67 urls_start_arg=0, |
| 68 ) |
| 69 # Help specification. See help_provider.py for documentation. |
| 70 help_spec = Command.HelpSpec( |
| 71 help_name='version', |
| 72 help_name_aliases=['ver'], |
| 73 help_type='command_help', |
| 74 help_one_line_summary='Print version info about gsutil', |
| 75 help_text=_DETAILED_HELP_TEXT, |
| 76 subcommand_help_text={}, |
| 77 ) |
| 78 |
| 79 def RunCommand(self): |
| 80 """Command entry point for the version command.""" |
| 81 long_form = False |
| 82 if self.sub_opts: |
| 83 for o, _ in self.sub_opts: |
| 84 if o == '-l': |
| 85 long_form = True |
| 86 |
| 87 config_path = GetConfigFilePath() |
| 88 |
| 89 shipped_checksum = gslib.CHECKSUM |
| 90 try: |
| 91 cur_checksum = self._ComputeCodeChecksum() |
| 92 except IOError: |
| 93 cur_checksum = 'MISSING FILES' |
| 94 if shipped_checksum == cur_checksum: |
| 95 checksum_ok_str = 'OK' |
| 96 else: |
| 97 checksum_ok_str = '!= %s' % shipped_checksum |
| 98 |
| 99 sys.stdout.write('gsutil version: %s\n' % gslib.VERSION) |
| 100 |
| 101 if long_form: |
| 102 |
| 103 long_form_output = ( |
| 104 'checksum: {checksum} ({checksum_ok})\n' |
| 105 'boto version: {boto_version}\n' |
| 106 'python version: {python_version}\n' |
| 107 'OS: {os_version}\n' |
| 108 'multiprocessing available: {multiprocessing_available}\n' |
| 109 'using cloud sdk: {cloud_sdk}\n' |
| 110 'config path: {config_path}\n' |
| 111 'gsutil path: {gsutil_path}\n' |
| 112 'compiled crcmod: {compiled_crcmod}\n' |
| 113 'installed via package manager: {is_package_install}\n' |
| 114 'editable install: {is_editable_install}\n' |
| 115 ) |
| 116 |
| 117 sys.stdout.write(long_form_output.format( |
| 118 checksum=cur_checksum, |
| 119 checksum_ok=checksum_ok_str, |
| 120 boto_version=boto.__version__, |
| 121 python_version=sys.version.replace('\n', ''), |
| 122 os_version='%s %s' % (platform.system(), platform.release()), |
| 123 multiprocessing_available=MultiprocessingIsAvailable()[0], |
| 124 cloud_sdk=(os.environ.get('CLOUDSDK_WRAPPER') == '1'), |
| 125 config_path=config_path, |
| 126 gsutil_path=gslib.GSUTIL_PATH, |
| 127 compiled_crcmod=UsingCrcmodExtension(crcmod), |
| 128 is_package_install=gslib.IS_PACKAGE_INSTALL, |
| 129 is_editable_install=gslib.IS_EDITABLE_INSTALL, |
| 130 )) |
| 131 |
| 132 return 0 |
| 133 |
| 134 def _ComputeCodeChecksum(self): |
| 135 """Computes a checksum of gsutil code. |
| 136 |
| 137 This checksum can be used to determine if users locally modified |
| 138 gsutil when requesting support. (It's fine for users to make local mods, |
| 139 but when users ask for support we ask them to run a stock version of |
| 140 gsutil so we can reduce possible variables.) |
| 141 |
| 142 Returns: |
| 143 MD5 checksum of gsutil code. |
| 144 """ |
| 145 if gslib.IS_PACKAGE_INSTALL: |
| 146 return 'PACKAGED_GSUTIL_INSTALLS_DO_NOT_HAVE_CHECKSUMS' |
| 147 m = md5() |
| 148 # Checksum gsutil and all .py files under gslib directory. |
| 149 files_to_checksum = [gslib.GSUTIL_PATH] |
| 150 for root, _, files in os.walk(gslib.GSLIB_DIR): |
| 151 for filepath in files: |
| 152 if filepath.endswith('.py'): |
| 153 files_to_checksum.append(os.path.join(root, filepath)) |
| 154 # Sort to ensure consistent checksum build, no matter how os.walk |
| 155 # orders the list. |
| 156 for filepath in sorted(files_to_checksum): |
| 157 f = open(filepath, 'r') |
| 158 content = f.read() |
| 159 content = re.sub(r'(\r\n|\r|\n)', '\n', content) |
| 160 m.update(content) |
| 161 f.close() |
| 162 return m.hexdigest() |
OLD | NEW |