OLD | NEW |
| (Empty) |
1 # Copyright 2015 The Chromium Authors. All rights reserved. | |
2 # Use of this source code is governed by a BSD-style license that can be | |
3 # found in the LICENSE file. | |
4 | |
5 import errno | |
6 import os | |
7 import stat | |
8 | |
9 from catapult_base import cloud_storage | |
10 | |
11 from catapult_base.dependency_manager import exceptions | |
12 | |
13 class CloudStorageInfo(object): | |
14 def __init__(self, cs_bucket, cs_hash, download_path, cs_remote_path, | |
15 version_in_cs=None, archive_info=None): | |
16 """ Container for the information needed to download a dependency from | |
17 cloud storage. | |
18 | |
19 Args: | |
20 cs_bucket: The cloud storage bucket the dependency is located in. | |
21 cs_hash: The hash of the file stored in cloud storage. | |
22 download_path: Where the file should be downloaded to. | |
23 cs_remote_path: Where the file is stored in the cloud storage bucket. | |
24 version_in_cs: The version of the file stored in cloud storage. | |
25 archive_info: An instance of ArchiveInfo if this dependency is an | |
26 archive. Else None. | |
27 """ | |
28 self._download_path = download_path | |
29 self._cs_remote_path = cs_remote_path | |
30 self._cs_bucket = cs_bucket | |
31 self._cs_hash = cs_hash | |
32 self._version_in_cs = version_in_cs | |
33 self._archive_info = archive_info | |
34 if not self._has_minimum_data: | |
35 raise ValueError( | |
36 'Not enough information specified to initialize a cloud storage info.' | |
37 ' %s' % self) | |
38 | |
39 def DependencyExistsInCloudStorage(self): | |
40 return cloud_storage.Exists(self._cs_bucket, self._cs_remote_path) | |
41 | |
42 def GetRemotePath(self): | |
43 """Gets the path to a downloaded version of the dependency. | |
44 | |
45 May not download the file if it has already been downloaded. | |
46 Will unzip the downloaded file if a non-empty archive_info was passed in at | |
47 init. | |
48 | |
49 Returns: A path to an executable that was stored in cloud_storage, or None | |
50 if not found. | |
51 | |
52 Raises: | |
53 CredentialsError: If cloud_storage credentials aren't configured. | |
54 PermissionError: If cloud_storage credentials are configured, but not | |
55 with an account that has permission to download the needed file. | |
56 NotFoundError: If the needed file does not exist where expected in | |
57 cloud_storage or the downloaded zip file. | |
58 ServerError: If an internal server error is hit while downloading the | |
59 needed file. | |
60 CloudStorageError: If another error occured while downloading the remote | |
61 path. | |
62 FileNotFoundError: If the download was otherwise unsuccessful. | |
63 """ | |
64 if not self._has_minimum_data: | |
65 return None | |
66 | |
67 download_dir = os.path.dirname(self._download_path) | |
68 if not os.path.exists(download_dir): | |
69 try: | |
70 os.makedirs(download_dir) | |
71 except OSError as e: | |
72 # The logic above is racy, and os.makedirs will raise an OSError if | |
73 # the directory exists. | |
74 if e.errno != errno.EEXIST: | |
75 raise | |
76 | |
77 dependency_path = self._download_path | |
78 cloud_storage.GetIfHashChanged( | |
79 self._cs_remote_path, self._download_path, self._cs_bucket, | |
80 self._cs_hash) | |
81 if not os.path.exists(dependency_path): | |
82 raise exceptions.FileNotFoundError(dependency_path) | |
83 | |
84 if self.has_archive_info: | |
85 dependency_path = self._archive_info.GetUnzippedPath() | |
86 else: | |
87 mode = os.stat(dependency_path).st_mode | |
88 os.chmod(dependency_path, mode | stat.S_IXUSR) | |
89 return os.path.abspath(dependency_path) | |
90 | |
91 @property | |
92 def version_in_cs(self): | |
93 return self._version_in_cs | |
94 | |
95 @property | |
96 def _has_minimum_data(self): | |
97 return all([self._cs_bucket, self._cs_remote_path, self._download_path, | |
98 self._cs_hash]) | |
99 | |
100 | |
101 @property | |
102 def has_archive_info(self): | |
103 return bool(self._archive_info) | |
104 | |
105 def __repr__(self): | |
106 return ( | |
107 'CloudStorageInfo(download_path=%s, cs_remote_path=%s, cs_bucket=%s, ' | |
108 'cs_hash=%s, version_in_cs=%s, archive_info=%s)' % ( | |
109 self._download_path, self._cs_remote_path, self._cs_bucket, | |
110 self._cs_hash, self._version_in_cs, self._archive_info)) | |
OLD | NEW |