Handle steampipe quirks in deploy builds

This commit is contained in:
Andrew Eikum 2021-03-26 16:04:41 -05:00 committed by Arkadiusz Hiler
parent 3d5022de71
commit de63ea5341
3 changed files with 145 additions and 2 deletions

View file

@ -1084,10 +1084,14 @@ all-dist:
## make deploy ## make deploy
## ##
STEAMPIPE_FIXUPS_PY := $(SRCDIR)/steampipe_fixups.py
.PHONY: deploy .PHONY: deploy
deploy: all deploy: all
mkdir -p $(DEPLOY_DIR) && \ mkdir -p $(DEPLOY_DIR) && \
rsync --delete --exclude compatibilitytool.vdf -arx $(DST_BASE)/ $(DEPLOY_DIR) rsync --delete --exclude compatibilitytool.vdf -arx $(DST_BASE)/ $(DEPLOY_DIR)
cp -a $(STEAMPIPE_FIXUPS_PY) $(DEPLOY_DIR)
python3 $(STEAMPIPE_FIXUPS_PY) process $(DEPLOY_DIR)
## ##

27
proton
View file

@ -435,6 +435,28 @@ class Proton:
if file_exists(old_dist_dir, follow_symlinks=True): if file_exists(old_dist_dir, follow_symlinks=True):
shutil.rmtree(old_dist_dir) shutil.rmtree(old_dist_dir)
def do_steampipe_fixups(self):
fixups_json = self.path("steampipe_fixups.json")
fixups_mtime = self.path("files/steampipe_fixups_mtime")
if file_exists(fixups_json, follow_symlinks=True):
with self.dist_lock:
import steampipe_fixups
current_fixup_mtime = None
if file_exists(fixups_mtime, follow_symlinks=True):
with open(fixups_mtime, "r") as f:
current_fixup_mtime = f.readline().strip()
new_fixup_mtime = getmtimestr(fixups_json)
if current_fixup_mtime != new_fixup_mtime:
result_code = steampipe_fixups.do_restore(self.base_dir, fixups_json)
if result_code == 0:
with open(fixups_mtime, "w") as f:
f.write(new_fixup_mtime + "\n")
def missing_default_prefix(self): def missing_default_prefix(self):
'''Check if the default prefix dir is missing. Returns true if missing, false if present''' '''Check if the default prefix dir is missing. Returns true if missing, false if present'''
return not os.path.isdir(self.default_pfx_dir) return not os.path.isdir(self.default_pfx_dir)
@ -769,10 +791,10 @@ class CompatData:
self.migrate_user_paths() self.migrate_user_paths()
if not os.path.lexists(self.prefix_dir + "/dosdevices/c:"): if not file_exists(self.prefix_dir + "/dosdevices/c:", follow_symlinks=False):
os.symlink("../drive_c", self.prefix_dir + "/dosdevices/c:") os.symlink("../drive_c", self.prefix_dir + "/dosdevices/c:")
if not os.path.lexists(self.prefix_dir + "/dosdevices/z:"): if not file_exists(self.prefix_dir + "/dosdevices/z:", follow_symlinks=False):
os.symlink("/", self.prefix_dir + "/dosdevices/z:") os.symlink("/", self.prefix_dir + "/dosdevices/z:")
# collect configuration info # collect configuration info
@ -1548,6 +1570,7 @@ if __name__ == "__main__":
g_proton = Proton(os.path.dirname(sys.argv[0])) g_proton = Proton(os.path.dirname(sys.argv[0]))
g_proton.cleanup_legacy_dist() g_proton.cleanup_legacy_dist()
g_proton.do_steampipe_fixups()
g_compatdata = CompatData(os.environ["STEAM_COMPAT_DATA_PATH"]) g_compatdata = CompatData(os.environ["STEAM_COMPAT_DATA_PATH"])

116
steampipe_fixups.py Executable file
View file

@ -0,0 +1,116 @@
#!/usr/bin/env python3
#Steampipe doesn't support certain unix-y things which may be required by
#native Linux applications. This file will process a directory of Linux files
#and store the file properties into a manifest file. After a round trip through
#Steampipe, the original file properties can be restored using this same
#script.
import json
import os
import secrets
import stat
DEFAULT_MANIFEST_NAME = "steampipe_fixups.json"
def usage():
print("Usage:")
print("\t" + sys.argv[0] + "\tprepare\t<path to directory to process>\t[manifest output file]")
print("\t\tProcess the given path and output the manifest file to the given path, or <path/" + DEFAULT_MANIFEST_NAME + "> if unspecified.")
print("")
print("\t" + sys.argv[0] + "\trestore\t<path to directory to process>\t[manifest file]")
print("\t\tRestore the given path using the manifest file, or <path/" + DEFAULT_MANIFEST_NAME + "> if unspecified.")
empty_dirs = []
no_write_paths = []
def canonicalize(path, prefix):
return path.replace(prefix, "", 1).lstrip('/')
def process_dir(path):
for root, subdirs, files in os.walk(path):
if len(subdirs) == 0 and len(files) == 0:
empty_dirs.append(canonicalize(root, path))
for file_ in files:
this_file = os.path.join(root, file_)
stat_result = os.lstat(this_file)
if (stat_result.st_mode & stat.S_IWUSR) == 0:
no_write_paths.append(canonicalize(this_file, path))
return 0
def write_manifest(manifest):
out = open(manifest, "w")
json.dump(
{
"id": str(secrets.randbits(32)), #we need steampipe to update this file for every build
"empty_dirs": empty_dirs,
"no_write_paths": no_write_paths,
},
out,
indent = 4,
sort_keys = True
)
return 0
def do_process(path, manifest):
if os.path.exists(manifest):
os.remove(manifest)
ret = process_dir(path)
if ret != 0:
return ret
#output should be deterministic
empty_dirs.sort()
no_write_paths.sort()
ret = write_manifest(manifest)
if ret != 0:
return ret
return 0
def do_restore(path, manifest):
loaded = json.load(open(manifest, "r"))
empty_dirs = loaded["empty_dirs"]
no_write_paths = loaded["no_write_paths"]
for empty_dir in empty_dirs:
try:
os.makedirs(os.path.join(path, empty_dir))
except OSError:
#already exists
pass
for file_ in no_write_paths:
this_file = os.path.join(path, file_)
stat_result = os.lstat(this_file)
os.chmod(this_file,
stat_result.st_mode & ~(stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH))
return 0
if __name__ == '__main__':
import sys
if len(sys.argv) < 3 or len(sys.argv) > 4:
usage()
sys.exit(1)
verb = sys.argv[1]
path = sys.argv[2]
if len(sys.argv) >= 4:
manifest = sys.argv[3]
else:
manifest = os.path.join(path, DEFAULT_MANIFEST_NAME)
if verb == "process":
sys.exit(do_process(path, manifest))
if verb == "restore":
sys.exit(do_restore(path, manifest))
usage()
sys.exit(1)