1 # -*- coding: utf-8 -*-
2 # Copyright 2011 Google Inc. All Rights Reserved.
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
8 # http://www.apache.org/licenses/LICENSE-2.0
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."""
17 from __future__
import absolute_import
19 from hashlib
import md5
28 from gslib
.command
import Command
29 from gslib
.util
import GetConfigFilePath
30 from gslib
.util
import MultiprocessingIsAvailable
31 from gslib
.util
import UsingCrcmodExtension
38 _DETAILED_HELP_TEXT
= ("""
44 Prints information about the version of gsutil.
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
54 class VersionCommand(Command
):
55 """Implementation of gsutil version command."""
57 # Command specification. See base class for documentation.
58 command_spec
= Command
.CreateCommandSpec(
60 command_name_aliases
=['ver'],
61 usage_synopsis
=_SYNOPSIS
,
64 supported_sub_args
='l',
66 provider_url_ok
=False,
69 # Help specification. See help_provider.py for documentation.
70 help_spec
= Command
.HelpSpec(
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
={},
80 """Command entry point for the version command."""
83 for o
, _
in self
.sub_opts
:
87 config_path
= GetConfigFilePath()
89 shipped_checksum
= gslib
.CHECKSUM
91 cur_checksum
= self
._ComputeCodeChecksum
()
93 cur_checksum
= 'MISSING FILES'
94 if shipped_checksum
== cur_checksum
:
95 checksum_ok_str
= 'OK'
97 checksum_ok_str
= '!= %s' % shipped_checksum
99 sys
.stdout
.write('gsutil version: %s\n' % gslib
.VERSION
)
104 'checksum: {checksum} ({checksum_ok})\n'
105 'boto version: {boto_version}\n'
106 'python version: {python_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'
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
,
134 def _ComputeCodeChecksum(self
):
135 """Computes a checksum of gsutil code.
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.)
143 MD5 checksum of gsutil code.
145 if gslib
.IS_PACKAGE_INSTALL
:
146 return 'PACKAGED_GSUTIL_INSTALLS_DO_NOT_HAVE_CHECKSUMS'
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
156 for filepath
in sorted(files_to_checksum
):
157 f
= open(filepath
, 'r')
159 content
= re
.sub(r
'(\r\n|\r|\n)', '\n', content
)