blob: f1c65febf1b28e039bd1b839761d15a1301d8c1b [file] [log] [blame]
# Copyright 2023 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
from __future__ import annotations
import functools
import os
import shutil
from typing import Optional
from crossbench import path as pth
from crossbench.plt.base import Platform
class WinPlatform(Platform):
# TODO: support remote platforms
SEARCH_PATHS = (
pth.LocalPath("."),
pth.LocalPath(os.path.expandvars("%ProgramFiles%")),
pth.LocalPath(os.path.expandvars("%ProgramFiles(x86)%")),
pth.LocalPath(os.path.expandvars("%APPDATA%")),
pth.LocalPath(os.path.expandvars("%LOCALAPPDATA%")),
)
@property
def is_win(self) -> bool:
return True
@property
def name(self) -> str:
return "win"
@property
def device(self) -> str:
# TODO: implement
return ""
@functools.cached_property
def version(self) -> str: #pylint: disable=invalid-overridden-method
return self.sh_stdout("cmd", "/c", "ver").strip()
@functools.cached_property
def cpu(self) -> str: #pylint: disable=invalid-overridden-method
return self.sh_stdout("wmic", "cpu", "get",
"name").strip().splitlines()[2].strip()
def search_binary(self,
app_or_bin: pth.RemotePathLike) -> Optional[pth.RemotePath]:
assert self.is_local, "Unsupported operation on remote platform"
app_or_bin_path: pth.RemotePath = self.path(app_or_bin)
if not app_or_bin_path.parts:
raise ValueError("Got empty path")
if app_or_bin_path.suffix != ".exe":
raise ValueError("Expected executable path with '.exe' suffix, "
f"but got: '{app_or_bin_path.name}'")
if result_path := self.which(app_or_bin):
assert self.exists(result_path), f"{result_path} does not exist."
return result_path
for path in self.SEARCH_PATHS:
# Recreate Path object for easier pyfakefs testing
result_path = self.path(path) / app_or_bin
if self.exists(result_path):
return result_path
return None
def app_version(self, app_or_bin: pth.RemotePathLike) -> str:
app_or_bin = self.path(app_or_bin)
assert self.exists(app_or_bin), f"Binary {app_or_bin} does not exist."
return self.sh_stdout(
"powershell", "-command",
f"(Get-Item '{app_or_bin}').VersionInfo.ProductVersion")
def symlink_or_copy(self, src: pth.RemotePathLike,
dst: pth.RemotePathLike) -> pth.RemotePath:
"""Windows does not support symlinking without admin support.
Copy files on windows but symlink everywhere else (see base Platform)."""
assert self.is_local, "Unsupported operation on remote platform"
dst_path = self.path(dst)
shutil.copy(self.path(src), dst_path)
return dst_path