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 |