|
12 | 12 | # See the License for the specific language governing permissions and |
13 | 13 | # limitations under the License. |
14 | 14 |
|
| 15 | +import json |
15 | 16 | import logging |
16 | 17 | import os |
| 18 | +import platform |
17 | 19 | import subprocess |
| 20 | +import sys |
| 21 | +import time |
18 | 22 |
|
19 | 23 | import click |
| 24 | +import semantic_version |
20 | 25 |
|
21 | 26 | from pioinstaller import exception, home, util |
22 | 27 |
|
23 | 28 | log = logging.getLogger(__name__) |
24 | 29 |
|
25 | 30 | PIO_CORE_DEVELOP_URL = "https://github.com/platformio/platformio/archive/develop.zip" |
| 31 | +UPDATE_INTERVAL = 60 * 60 * 24 * 3 # 3 days |
26 | 32 |
|
27 | 33 |
|
28 | 34 | def get_core_dir(): |
@@ -112,3 +118,119 @@ def install_platformio_core(shutdown_piohome=True, develop=False, ignore_pythons |
112 | 118 | fg="cyan", |
113 | 119 | ) |
114 | 120 | return True |
| 121 | + |
| 122 | + |
| 123 | +def check(dev=False, auto_upgrade=False, version_requirements=None): |
| 124 | + |
| 125 | + # pylint: disable=bad-option-value, import-outside-toplevel, unused-import, import-error, unused-variable, cyclic-import |
| 126 | + from pioinstaller import penv |
| 127 | + |
| 128 | + platformio_exe = os.path.join( |
| 129 | + penv.get_penv_bin_dir(), "platformio.exe" if util.IS_WINDOWS else "platformio", |
| 130 | + ) |
| 131 | + if not os.path.isfile(platformio_exe): |
| 132 | + raise exception.InvalidPlatformIOCore( |
| 133 | + "PlatformIO executable not found in `%s`" % penv.get_penv_bin_dir() |
| 134 | + ) |
| 135 | + |
| 136 | + if not os.path.isfile(os.path.join(penv.get_penv_dir(), "state.json")): |
| 137 | + raise exception.InvalidPlatformIOCore( |
| 138 | + "Could not found state.json file in `%s`" |
| 139 | + % os.path.join(penv.get_penv_dir(), "state.json") |
| 140 | + ) |
| 141 | + |
| 142 | + try: |
| 143 | + # pylint: disable=bad-option-value, import-outside-toplevel, unused-import, import-error, unused-variable, cyclic-import |
| 144 | + import platformio |
| 145 | + except ImportError: |
| 146 | + raise exception.InvalidPlatformIOCore("Could not import PlatformIO module") |
| 147 | + |
| 148 | + pio_version = get_pio_version(platformio) |
| 149 | + if version_requirements: |
| 150 | + try: |
| 151 | + if pio_version in semantic_version.Spec(version_requirements): |
| 152 | + raise exception.InvalidPlatformIOCore( |
| 153 | + "PlatformIO Core version %s does not match version requirements %s." |
| 154 | + % (str(pio_version), version_requirements) |
| 155 | + ) |
| 156 | + except ValueError: |
| 157 | + click.secho( |
| 158 | + "Invalid version requirements format: %s. " |
| 159 | + "More about Semantic Versioning: https://semver.org/" |
| 160 | + % version_requirements |
| 161 | + ) |
| 162 | + |
| 163 | + state = None |
| 164 | + |
| 165 | + with open(os.path.join(penv.get_penv_dir(), "state.json")) as fp: |
| 166 | + state = json.load(fp) |
| 167 | + if state.get("platform") != platform.platform(): |
| 168 | + raise exception.InvalidPlatformIOCore( |
| 169 | + "PlatformIO installed using another platform `%s`. Your platform: %s" |
| 170 | + % (state.get("platform"), platform.platform()) |
| 171 | + ) |
| 172 | + |
| 173 | + try: |
| 174 | + subprocess.check_output([platformio_exe, "--version"], stderr=subprocess.STDOUT) |
| 175 | + except subprocess.CalledProcessError as e: |
| 176 | + error = e.output.decode() |
| 177 | + raise exception.InvalidPlatformIOCore( |
| 178 | + "Could not run `%s --version`.\nError: %s" % (platformio, str(error)) |
| 179 | + ) |
| 180 | + |
| 181 | + result = {"platformio_exe": platformio_exe, "version": str(pio_version)} |
| 182 | + |
| 183 | + if not auto_upgrade: |
| 184 | + return result |
| 185 | + |
| 186 | + time_now = int(round(time.time())) |
| 187 | + |
| 188 | + last_piocore_version_check = state.get("last_piocore_version_check") |
| 189 | + |
| 190 | + if ( |
| 191 | + last_piocore_version_check |
| 192 | + and (time_now - int(last_piocore_version_check)) < UPDATE_INTERVAL |
| 193 | + ): |
| 194 | + return result |
| 195 | + |
| 196 | + with open(os.path.join(penv.get_penv_dir(), "state.json"), "w") as fp: |
| 197 | + state["last_piocore_version_check"] = time_now |
| 198 | + json.dump(state, fp) |
| 199 | + |
| 200 | + if not last_piocore_version_check: |
| 201 | + return result |
| 202 | + |
| 203 | + dev = dev or pio_version.prerelease |
| 204 | + upgrade_core(platformio_exe, dev) |
| 205 | + |
| 206 | + result["pio_version"] = get_pio_version(platformio) |
| 207 | + return result |
| 208 | + |
| 209 | + |
| 210 | +def get_pio_version(platformio): |
| 211 | + try: |
| 212 | + if sys.version_info[0] == 3: |
| 213 | + # pylint: disable=bad-option-value, import-outside-toplevel, unused-import, import-error, unused-variable, cyclic-import |
| 214 | + import importlib |
| 215 | + |
| 216 | + importlib.reload(platformio) # pylint:disable=no-member |
| 217 | + else: |
| 218 | + reload(platformio) |
| 219 | + return semantic_version.Version(util.pepver_to_semver(platformio.__version__)) |
| 220 | + except: # pylint:disable=bare-except |
| 221 | + return platformio.__version__ |
| 222 | + |
| 223 | + |
| 224 | +def upgrade_core(platformio_exe, dev=False): |
| 225 | + command = [platformio_exe, "upgrade"] |
| 226 | + if dev: |
| 227 | + command.append("--dev") |
| 228 | + try: |
| 229 | + subprocess.check_output( |
| 230 | + command, stderr=subprocess.PIPE, |
| 231 | + ) |
| 232 | + return True |
| 233 | + except Exception as e: # pylint:disable=broad-except |
| 234 | + raise exception.PIOInstallerException( |
| 235 | + "Could not upgrade PlatformIO Core: %s" % str(e) |
| 236 | + ) |
0 commit comments