From e82e98b1ff1544acb4b80b8e1b8e42b4f1531346 Mon Sep 17 00:00:00 2001 From: Andrew Eikum Date: Thu, 27 May 2021 11:23:08 -0500 Subject: [PATCH] proton: Migrate old user paths to new paths CW-Bug-Id: 18905 --- proton | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/proton b/proton index 5c490789..9e071e16 100755 --- a/proton +++ b/proton @@ -68,7 +68,38 @@ def makedirs(path): #already exists pass -def try_copy(src, dst, add_write_perm=True): +def merge_user_dir(src, dst): + extant_dirs = [] + for src_dir, dirs, files in os.walk(src): + dst_dir = src_dir.replace(src, dst, 1) + + #as described below, avoid merging game save subdirs, too + child_of_extant_dir = False + for dir_ in extant_dirs: + if dir_ in dst_dir: + child_of_extant_dir = True + break + if child_of_extant_dir: + continue + + #we only want to copy into directories which don't already exist. games + #may not react well to two save directory instances being merged. + if not os.path.exists(dst_dir) or os.path.samefile(dst_dir, dst): + makedirs(dst_dir) + for dir_ in dirs: + src_file = os.path.join(src_dir, dir_) + dst_file = os.path.join(dst_dir, dir_) + if os.path.islink(src_file) and not os.path.exists(dst_file): + try_copy(src_file, dst_file, copy_metadata=True) + for file_ in files: + src_file = os.path.join(src_dir, file_) + dst_file = os.path.join(dst_dir, file_) + if not os.path.exists(dst_file): + try_copy(src_file, dst_file, copy_metadata=True) + else: + extant_dirs += dst_dir + +def try_copy(src, dst, add_write_perm=True, copy_metadata=True): try: if os.path.isdir(dst): dstfile = dst + "/" + os.path.basename(src) @@ -79,7 +110,10 @@ def try_copy(src, dst, add_write_perm=True): if os.path.lexists(dst): os.remove(dst) - shutil.copy(src, dst) + if copy_metadata: + shutil.copy2(src, dst) + else: + shutil.copy(src, dst) if add_write_perm: new_mode = os.lstat(dstfile).st_mode | stat.S_IWUSR | stat.S_IWGRP @@ -416,7 +450,7 @@ class CompatData: if len(rel_dir) > 0: rel_dir = rel_dir + "/" dst_dir = src_dir.replace(g_proton.default_pfx_dir, self.prefix_dir, 1) - if not os.path.exists(dst_dir): + if not os.path.lexists(dst_dir): os.makedirs(dst_dir) tracked_files.write(rel_dir + "\n") for file_ in files: @@ -466,6 +500,31 @@ class CompatData: else: os.symlink(fname, lname) + def migrate_user_paths(self): + #move winxp-style paths to vista+ paths. we can't do this in + #upgrade_pfx because Steam may drop cloud files here at any time. + for (old, new, link) in \ + [ + (self.prefix_dir + "drive_c/users/steamuser/Local Settings/Application Data", + self.prefix_dir + "drive_c/users/steamuser/AppData/Local", + "../AppData/Local"), + (self.prefix_dir + "drive_c/users/steamuser/Application Data", + self.prefix_dir + "drive_c/users/steamuser/AppData/Roaming", + "./AppData/Roaming"), + (self.prefix_dir + "drive_c/users/steamuser/My Documents", + self.prefix_dir + "drive_c/users/steamuser/Documents", + "./Documents"), + ]: + if os.path.lexists(old) and not os.path.islink(old): + merge_user_dir(src=old, dst=new) + os.rename(old, old + " BACKUP") + if not os.path.lexists(old): + makedirs(os.path.dirname(old)) + os.symlink(src=link, dst=old) + elif os.path.islink(old) and not (os.readlink(old) == link): + os.remove(old) + os.symlink(src=link, dst=old) + def setup_prefix(self): with self.prefix_lock: if os.path.exists(self.version_file): @@ -483,6 +542,8 @@ class CompatData: if not os.path.exists(self.prefix_dir + "/user.reg"): self.copy_pfx() + self.migrate_user_paths() + # collect configuration info steamdir = os.environ["STEAM_COMPAT_CLIENT_INSTALL_PATH"]