Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(532)

Unified Diff: gslib/commands/update.py

Issue 698893003: Update checked in version of gsutil to version 4.6 (Closed) Base URL: http://dart.googlecode.com/svn/third_party/gsutil/
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « gslib/commands/test.py ('k') | gslib/commands/version.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: gslib/commands/update.py
===================================================================
--- gslib/commands/update.py (revision 33376)
+++ gslib/commands/update.py (working copy)
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
# Copyright 2011 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -11,43 +12,33 @@
# 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 update command for updating gsutil."""
+from __future__ import absolute_import
+
import os
import shutil
import signal
+import stat
import tarfile
import tempfile
import textwrap
import gslib
from gslib.command import Command
-from gslib.command import COMMAND_NAME
-from gslib.command import COMMAND_NAME_ALIASES
-from gslib.command import FILE_URIS_OK
-from gslib.command import MAX_ARGS
-from gslib.command import MIN_ARGS
-from gslib.command import PROVIDER_URIS_OK
-from gslib.command import SUPPORTED_SUB_ARGS
-from gslib.command import URIS_START_ARG
+from gslib.cs_api_map import ApiSelector
from gslib.exception import CommandException
-from gslib.help_provider import HELP_NAME
-from gslib.help_provider import HELP_NAME_ALIASES
-from gslib.help_provider import HELP_ONE_LINE_SUMMARY
-from gslib.help_provider import HELP_TEXT
-from gslib.help_provider import HELP_TYPE
-from gslib.help_provider import HelpType
-from gslib.storage_uri_builder import StorageUriBuilder
-from gslib.util import BOTO_IS_SECURE
+from gslib.util import CERTIFICATE_VALIDATION_ENABLED
from gslib.util import CompareVersions
+from gslib.util import GetBotoConfigFileList
from gslib.util import GSUTIL_PUB_TARBALL
from gslib.util import IS_CYGWIN
from gslib.util import IS_WINDOWS
from gslib.util import LookUpGsutilVersion
-from gslib.util import LookUpGsutilVersion
from gslib.util import RELEASE_NOTES_URL
-_detailed_help_text = ("""
+_DETAILED_HELP_TEXT = ("""
<B>SYNOPSIS</B>
gsutil update [-f] [-n] [uri]
@@ -97,45 +88,35 @@
class UpdateCommand(Command):
"""Implementation of gsutil update command."""
- # Command specification (processed by parent class).
- command_spec = {
- # Name of command.
- COMMAND_NAME: 'update',
- # List of command name aliases.
- COMMAND_NAME_ALIASES: ['refresh'],
- # Min number of args required by this command.
- MIN_ARGS: 0,
- # Max number of args required by this command, or NO_MAX.
- MAX_ARGS: 1,
- # Getopt-style string specifying acceptable sub args.
- SUPPORTED_SUB_ARGS: 'fn',
- # True if file URIs acceptable for this command.
- FILE_URIS_OK: True,
- # True if provider-only URIs acceptable for this command.
- PROVIDER_URIS_OK: False,
- # Index in args of first URI arg.
- URIS_START_ARG: 0,
- }
- help_spec = {
- # Name of command or auxiliary help info for which this help applies.
- HELP_NAME: 'update',
- # List of help name aliases.
- HELP_NAME_ALIASES: ['refresh'],
- # Type of help:
- HELP_TYPE: HelpType.COMMAND_HELP,
- # One line summary of this help.
- HELP_ONE_LINE_SUMMARY: 'Update to the latest gsutil release',
- # The full help text.
- HELP_TEXT: _detailed_help_text,
- }
+ # Command specification. See base class for documentation.
+ command_spec = Command.CreateCommandSpec(
+ 'update',
+ command_name_aliases=['refresh'],
+ min_args=0,
+ max_args=1,
+ supported_sub_args='fn',
+ file_url_ok=True,
+ provider_url_ok=False,
+ urls_start_arg=0,
+ gs_api_support=[ApiSelector.XML, ApiSelector.JSON],
+ gs_default_api=ApiSelector.JSON,
+ )
+ # Help specification. See help_provider.py for documentation.
+ help_spec = Command.HelpSpec(
+ help_name='update',
+ help_name_aliases=['refresh'],
+ help_type='command_help',
+ help_one_line_summary='Update to the latest gsutil release',
+ help_text=_DETAILED_HELP_TEXT,
+ subcommand_help_text={},
+ )
def _DisallowUpdataIfDataInGsutilDir(self):
- """
- Disallows the update command from running if files other than those
- distributed with gsutil are found. This prevents users from losing data if
- they are in the habit of running gsutil from the gsutil directory, and
- leaving data in that directory.
+ """Disallows the update command if files not in the gsutil distro are found.
+ This prevents users from losing data if they are in the habit of running
+ gsutil from the gsutil directory and leaving data in that directory.
+
This will also detect someone attempting to run gsutil update from a git
repo, since the top-level directory will contain git files and dirs (like
.git) that are not distributed with gsutil.
@@ -143,18 +124,17 @@
Raises:
CommandException: if files other than those distributed with gsutil found.
"""
- # Manifest includes recursive-includes of gslib and scripts. Directly add
+ # Manifest includes recursive-includes of gslib. Directly add
# those to the list here so we will skip them in os.listdir() loop without
# having to build deeper handling of the MANIFEST file here. Also include
# 'third_party', which isn't present in manifest but gets added to the
# gsutil distro by the gsutil submodule configuration; and the MANIFEST.in
# and CHANGES.md files.
- manifest_lines = ['gslib', 'scripts', 'third_party', 'MANIFEST.in',
- 'CHANGES.md']
-
+ manifest_lines = ['gslib', 'third_party', 'MANIFEST.in', 'CHANGES.md']
+
try:
with open(os.path.join(gslib.GSUTIL_DIR, 'MANIFEST.in'), 'r') as fp:
- for line in fp.readlines():
+ for line in fp:
if line.startswith('include '):
manifest_lines.append(line.split()[-1])
except IOError:
@@ -166,16 +146,16 @@
# subdirs (like gslib) because that would require deeper parsing of
# MANFFEST.in, and most users who drop data into gsutil dir do so at the top
# level directory.
- for file in os.listdir(gslib.GSUTIL_DIR):
- if file[-4:] == '.pyc':
+ for filename in os.listdir(gslib.GSUTIL_DIR):
+ if filename.endswith('.pyc'):
# Ignore compiled code.
continue
- if file not in manifest_lines:
+ if filename not in manifest_lines:
raise CommandException('\n'.join(textwrap.wrap(
'A file (%s) that is not distributed with gsutil was found in '
'the gsutil directory. The update command cannot run with user '
'data in the gsutil directory.' %
- os.path.join(gslib.GSUTIL_DIR, file))))
+ os.path.join(gslib.GSUTIL_DIR, filename))))
def _ExplainIfSudoNeeded(self, tf, dirs_to_remove):
"""Explains what to do if sudo needed to update gsutil software.
@@ -200,16 +180,26 @@
# Won't fail - this command runs after main startup code that insists on
# having a config file.
- config_files = ' '.join(self.config_file_list)
+ config_file_list = GetBotoConfigFileList()
+ config_files = ' '.join(config_file_list)
self._CleanUpUpdateCommand(tf, dirs_to_remove)
+
+ # Pick current protection of each boto config file for command that restores
+ # protection (rather than fixing at 600) to support use cases like how GCE
+ # installs a service account with an /etc/boto.cfg file protected to 644.
+ chmod_cmds = []
+ for config_file in config_file_list:
+ mode = oct(stat.S_IMODE((os.stat(config_file)[stat.ST_MODE])))
+ chmod_cmds.append('\n\tsudo chmod %s %s' % (mode, config_file))
+
raise CommandException('\n'.join(textwrap.wrap(
'Since it was installed by a different user previously, you will need '
'to update using the following commands. You will be prompted for your '
'password, and the install will run as "root". If you\'re unsure what '
- 'this means please ask your system administrator for help:'))
- + ('\n\tchmod 644 %s\n\tsudo env BOTO_CONFIG=%s gsutil update'
- '\n\tchmod 600 %s') % (config_files, config_files, config_files),
- informational=True)
+ 'this means please ask your system administrator for help:')) + (
+ '\n\tsudo chmod 0644 %s\n\tsudo env BOTO_CONFIG="%s" %s update'
+ '%s') % (config_files, config_files, self.gsutil_path,
+ ' '.join(chmod_cmds)), informational=True)
# This list is checked during gsutil update by doing a lowercased
# slash-left-stripped check. For example "/Dev" would match the "dev" entry.
@@ -223,7 +213,7 @@
]
def _EnsureDirsSafeForUpdate(self, dirs):
- """Throws Exception if any of dirs is known to be unsafe for gsutil update.
+ """Raises Exception if any of dirs is known to be unsafe for gsutil update.
This provides a fail-safe check to ensure we don't try to overwrite
or delete any important directories. (That shouldn't happen given the
@@ -265,21 +255,30 @@
if not IS_WINDOWS:
raise
- # Command entry point.
def RunCommand(self):
+ """Command entry point for the update command."""
if gslib.IS_PACKAGE_INSTALL:
raise CommandException(
- 'Update command is only available for gsutil installed from a '
+ 'The update command is only available for gsutil installed from a '
'tarball. If you installed gsutil via another method, use the same '
'method to update it.')
- is_secure = BOTO_IS_SECURE
- if not is_secure[0]:
+ if os.environ.get('CLOUDSDK_WRAPPER') == '1':
raise CommandException(
- 'Your boto configuration has %s = False. The update command\n'
- 'cannot be run this way, for security reasons.' % is_secure[1])
+ 'The update command is disabled for Cloud SDK installs. Please run '
+ '"gcloud components update" to update it. Note: the Cloud SDK '
+ 'incorporates updates to the underlying tools approximately every 2 '
+ 'weeks, so if you are attempting to update to a recently created '
+ 'release / pre-release of gsutil it may not yet be available via '
+ 'the Cloud SDK.')
+ https_validate_certificates = CERTIFICATE_VALIDATION_ENABLED
+ if not https_validate_certificates:
+ raise CommandException(
+ 'Your boto configuration has https_validate_certificates = False.\n'
+ 'The update command cannot be run this way, for security reasons.')
+
self._DisallowUpdataIfDataInGsutilDir()
force_update = False
@@ -307,12 +306,13 @@
if i > 0:
raise CommandException(
'Invalid update URI. Must name a single .tar.gz file.')
- if result.uri.names_file():
+ storage_url = result.storage_url
+ if storage_url.IsFileUrl() and not storage_url.IsDirectory():
if not force_update:
raise CommandException(
('"update" command does not support "file://" URIs without the '
'-f option.'))
- elif not result.uri.names_object():
+ elif not (storage_url.IsCloudUrl() and storage_url.IsObject()):
raise CommandException(
'Invalid update object URI. Must name a single .tar.gz file.')
else:
@@ -322,9 +322,7 @@
# the tarball and extract the VERSION file. The version lookup will fail
# when running the update system test, because it retrieves the tarball from
# a temp file rather than a cloud URI (files lack the version metadata).
- suri_builder = StorageUriBuilder(self.debug, self.bucket_storage_uri_class)
- tarball_version = LookUpGsutilVersion(
- self.suri_builder.StorageUri(update_from_uri_str))
+ tarball_version = LookUpGsutilVersion(self.gsutil_api, update_from_uri_str)
if tarball_version:
tf = None
else:
@@ -343,8 +341,8 @@
'installed.', informational=True)
if not no_prompt:
- (g, m) = CompareVersions(tarball_version, gslib.VERSION)
- if m:
+ (_, major) = CompareVersions(tarball_version, gslib.VERSION)
+ if major:
print('\n'.join(textwrap.wrap(
'This command will update to the "%s" version of gsutil at %s. '
'NOTE: This a major new version, so it is strongly recommended '
@@ -397,13 +395,25 @@
# users, we can skip this step when running on Windows, which
# avoids the problem that Windows has no find or xargs command.
if not IS_WINDOWS:
- # Make all files and dirs in updated area readable by other
- # and make all directories executable by other.
- os.system('chmod -R o+r ' + new_dir)
- os.system('find ' + new_dir + ' -type d | xargs chmod o+x')
+ # Make all files and dirs in updated area owner-RW and world-R, and make
+ # all directories owner-RWX and world-RX.
+ for dirname, subdirs, filenames in os.walk(new_dir):
+ for filename in filenames:
+ fd = os.open(os.path.join(dirname, filename), os.O_RDONLY)
+ os.fchmod(fd, stat.S_IWRITE | stat.S_IRUSR |
+ stat.S_IRGRP | stat.S_IROTH)
+ os.close(fd)
+ for subdir in subdirs:
+ fd = os.open(os.path.join(dirname, subdir), os.O_RDONLY)
+ os.fchmod(fd, stat.S_IRWXU | stat.S_IXGRP | stat.S_IXOTH |
+ stat.S_IRGRP | stat.S_IROTH)
+ os.close(fd)
- # Make main gsutil script readable and executable by other.
- os.system('chmod o+rx ' + os.path.join(new_dir, 'gsutil'))
+ # Make main gsutil script owner-RWX and world-RX.
+ fd = os.open(os.path.join(new_dir, 'gsutil', 'gsutil'), os.O_RDONLY)
+ os.fchmod(fd, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP |
+ stat.S_IROTH | stat.S_IXOTH)
+ os.close(fd)
# Move old installation aside and new into place.
os.rename(gslib.GSUTIL_DIR, os.path.join(old_dir, 'old'))
« no previous file with comments | « gslib/commands/test.py ('k') | gslib/commands/version.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698