OLD | NEW |
| (Empty) |
1 # Copyright 2011 Google Inc. All Rights Reserved. | |
2 # | |
3 # Licensed under the Apache License, Version 2.0 (the "License"); | |
4 # you may not use this file except in compliance with the License. | |
5 # You may obtain a copy of the License at | |
6 # | |
7 # http://www.apache.org/licenses/LICENSE-2.0 | |
8 # | |
9 # Unless required by applicable law or agreed to in writing, software | |
10 # distributed under the License is distributed on an "AS IS" BASIS, | |
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 # See the License for the specific language governing permissions and | |
13 # limitations under the License. | |
14 | |
15 import boto | |
16 import os | |
17 import re | |
18 import sys | |
19 | |
20 from boto.pyami.config import BotoConfigLocations | |
21 from gslib.command import Command | |
22 from gslib.command import COMMAND_NAME | |
23 from gslib.command import COMMAND_NAME_ALIASES | |
24 from gslib.command import CONFIG_REQUIRED | |
25 from gslib.command import FILE_URIS_OK | |
26 from gslib.command import MAX_ARGS | |
27 from gslib.command import MIN_ARGS | |
28 from gslib.command import PROVIDER_URIS_OK | |
29 from gslib.command import SUPPORTED_SUB_ARGS | |
30 from gslib.command import URIS_START_ARG | |
31 from gslib.help_provider import HELP_NAME | |
32 from gslib.help_provider import HELP_NAME_ALIASES | |
33 from gslib.help_provider import HELP_ONE_LINE_SUMMARY | |
34 from gslib.help_provider import HELP_TEXT | |
35 from gslib.help_provider import HelpType | |
36 from gslib.help_provider import HELP_TYPE | |
37 from hashlib import md5 | |
38 | |
39 _detailed_help_text = (""" | |
40 <B>SYNOPSIS</B> | |
41 gsutil version | |
42 | |
43 | |
44 <B>DESCRIPTION</B> | |
45 Prints information about the version of gsutil, boto, and Python being | |
46 run on your system. | |
47 """) | |
48 | |
49 | |
50 class VersionCommand(Command): | |
51 """Implementation of gsutil version command.""" | |
52 | |
53 # Command specification (processed by parent class). | |
54 command_spec = { | |
55 # Name of command. | |
56 COMMAND_NAME : 'version', | |
57 # List of command name aliases. | |
58 COMMAND_NAME_ALIASES : ['ver'], | |
59 # Min number of args required by this command. | |
60 MIN_ARGS : 0, | |
61 # Max number of args required by this command, or NO_MAX. | |
62 MAX_ARGS : 0, | |
63 # Getopt-style string specifying acceptable sub args. | |
64 SUPPORTED_SUB_ARGS : '', | |
65 # True if file URIs acceptable for this command. | |
66 FILE_URIS_OK : False, | |
67 # True if provider-only URIs acceptable for this command. | |
68 PROVIDER_URIS_OK : False, | |
69 # Index in args of first URI arg. | |
70 URIS_START_ARG : 0, | |
71 # True if must configure gsutil before running command. | |
72 CONFIG_REQUIRED : False, | |
73 } | |
74 help_spec = { | |
75 # Name of command or auxiliary help info for which this help applies. | |
76 HELP_NAME : 'version', | |
77 # List of help name aliases. | |
78 HELP_NAME_ALIASES : ['ver'], | |
79 # Type of help: | |
80 HELP_TYPE : HelpType.COMMAND_HELP, | |
81 # One line summary of this help. | |
82 HELP_ONE_LINE_SUMMARY : 'Print version info about gsutil', | |
83 # The full help text. | |
84 HELP_TEXT : _detailed_help_text, | |
85 } | |
86 | |
87 # Command entry point. | |
88 def RunCommand(self): | |
89 for path in BotoConfigLocations: | |
90 f = None | |
91 try: | |
92 f = open(path, 'r') | |
93 break | |
94 except IOError: | |
95 pass | |
96 finally: | |
97 if f: | |
98 f.close() | |
99 else: | |
100 path = "no config found" | |
101 | |
102 try: | |
103 f = open(os.path.join(self.gsutil_bin_dir, 'CHECKSUM')) | |
104 shipped_checksum = f.read().strip() | |
105 f.close() | |
106 except IOError: | |
107 shipped_checksum = 'MISSING' | |
108 try: | |
109 cur_checksum = self._ComputeCodeChecksum() | |
110 except IOError: | |
111 cur_checksum = 'MISSING FILES' | |
112 if shipped_checksum == cur_checksum: | |
113 checksum_ok_str = 'OK' | |
114 else: | |
115 checksum_ok_str = '!= %s' % shipped_checksum | |
116 sys.stderr.write( | |
117 'gsutil version %s\nchecksum %s (%s)\n' | |
118 'boto version %s\npython version %s\n' | |
119 'config path: %s\ngsutil path: %s\n' % ( | |
120 self.gsutil_ver, cur_checksum, checksum_ok_str, | |
121 boto.__version__, sys.version, path, os.path.realpath(sys.argv[0]))) | |
122 | |
123 return 0 | |
124 | |
125 def _ComputeCodeChecksum(self): | |
126 """ | |
127 Computes a checksum of gsutil code so we can see if users locally modified | |
128 gsutil when requesting support. (It's fine for users to make local mods, | |
129 but when users ask for support we ask them to run a stock version of | |
130 gsutil so we can reduce possible variables.) | |
131 """ | |
132 m = md5() | |
133 # Checksum gsutil and all .py files under gsutil bin (including bundled | |
134 # libs). Although we will eventually make gsutil allow use of a centrally | |
135 # installed boto (once boto shifts to more frequent releases), in that case | |
136 # the local copies still should not have any user modifications. | |
137 files_to_checksum = [os.path.join(self.gsutil_bin_dir, 'gsutil')] | |
138 for root, sub_folders, files in os.walk(self.gsutil_bin_dir): | |
139 for file in files: | |
140 if file[-3:] == '.py': | |
141 files_to_checksum.append(os.path.join(root, file)) | |
142 # Sort to ensure consistent checksum build, no matter how os.walk | |
143 # orders the list. | |
144 for file in sorted(files_to_checksum): | |
145 f = open(file, 'r') | |
146 content = f.read() | |
147 content = re.sub(r'(\r\n|\r|\n)', '\n', content) | |
148 m.update(content) | |
149 f.close() | |
150 return m.hexdigest() | |
OLD | NEW |