def _differs(self, data1, data2, start=0, stop=None): with open(self._path("file1"), "wb") as f: f.write(data1.encode("ascii")) with open(self._path("file2"), "wb") as f: f.write(data2.encode("ascii")) return files_differ(self._path("file1"), self._path("file2"), start, stop)
def _unpack_bootstrap_env(self, target, trn): """Unpack the bootstrap env from the given target directory.""" vdir = os.path.basename(target) # Move new bootrapping environment into main app dir. # Be sure to move dependencies before executables. bootstrap = os.path.join(target, ESKY_CONTROL_DIR, "bootstrap") for nm in self._version_manifest(vdir): bssrc = os.path.join(bootstrap, nm) bsdst = os.path.join(self.appdir, nm) if os.path.exists(bssrc): # On windows we can't atomically replace files. # If they differ in a "safe" way we put them aside # to overwrite at a later time. if sys.platform == "win32" and os.path.exists(bsdst): if not files_differ(bssrc, bsdst): trn.remove(bssrc) elif esky.winres.is_safe_to_overwrite(bssrc, bsdst): ovrdir = os.path.join(target, ESKY_CONTROL_DIR) ovrdir = os.path.join(ovrdir, "overwrite") if not os.path.exists(ovrdir): os.mkdir(ovrdir) trn.move(bssrc, os.path.join(ovrdir, nm)) else: trn.move(bssrc, bsdst) else: trn.move(bssrc, bsdst) if os.path.isdir(os.path.dirname(bssrc)): if not os.listdir(os.path.dirname(bssrc)): trn.remove(os.path.dirname(bssrc)) # Remove the bootstrap dir; the new version is now installed trn.remove(bootstrap)
def copy(self,source,target): source = self._check_path(source) target = self._check_path(target) if os.path.isdir(source): if os.path.isdir(target): s_names = os.listdir(source) for nm in s_names: self.copy(os.path.join(source,nm), os.path.join(target,nm)) for nm in os.listdir(target): if nm not in s_names: self._remove(os.path.join(target,nm)) else: self._copy(source,target) else: if os.path.isdir(target) or files_differ(source,target): self._copy(source,target)
def copy(self,source,target): source = self._check_path(source) target = self._check_path(target) if os.path.isdir(source): if os.path.isdir(target): s_names = os.listdir(source) for nm in s_names: self.copy(os.path.join(source,nm), os.path.join(target,nm)) for nm in os.listdir(target): if nm not in s_names: self.remove(os.path.join(target,nm)) else: self.pending.append(("_copy",source,target)) else: if os.path.isdir(target) or files_differ(source,target): self.pending.append(("_copy",source,target))
def is_safe_to_overwrite(source,target): """Check whether it is safe to overwrite target exe with source exe. This function checks whether two exe files 'source' and 'target' differ only in the contents of certain non-critical resource segments. If so, then overwriting the target file with the contents of the source file should be safe even in the face of system crashes or power outages; the worst outcome would be a corrupted resource such as an icon. """ if not source.endswith(".exe") or not target.endswith(".exe"): return False # Check if they're the same size s_sz = os.stat(source).st_size t_sz = os.stat(target).st_size if s_sz != t_sz: return False # Find each safe resource, and confirm that either (1) it's in the same # location in both executables, or (2) it's missing in both executables. # TODO: do this by enumerating resources safe_res = ((RT_VERSION,1),(RT_ICON,1),(RT_ICON,2)) locs = [] for (rtype,rid) in safe_res: try: s_loc = find_resource(source,rtype,rid) except WindowsError: s_loc = None try: t_loc = find_resource(target,rtype,rid) except WindowsError: t_loc = None if s_loc != t_loc: return False if s_loc is not None: locs.append(s_loc) # Confirm that no other portions of the file have changed if locs: locs.extend(((0,0),(s_sz,s_sz))) locs.sort() for (_,start),(stop,_) in pairwise(locs): if files_differ(source,target,start,stop): return False # Looks safe to me! return True
def move(self,source,target): source = self._check_path(source) target = self._check_path(target) if os.path.isdir(source): if os.path.isdir(target): s_names = os.listdir(source) for nm in s_names: self.move(os.path.join(source,nm), os.path.join(target,nm)) for nm in os.listdir(target): if nm not in s_names: self.remove(os.path.join(target,nm)) self.remove(source) else: self.pending.append(("_move",source,target)) else: if os.path.isdir(target) or files_differ(source,target): self.pending.append(("_move",source,target)) else: self.pending.append(("_remove",source))
def is_safe_to_overwrite(source,target): """Check whether it is safe to overwrite target exe with source exe. This function checks whether two exe files 'source' and 'target' differ only in the contents of certain non-critical resource segments. If so, then overwriting the target file with the contents of the source file should be safe even in the face of system crashes or power outages; the worst outcome would be a corrupted resource such as an icon. """ if not source.endswith(".exe") or not target.endswith(".exe"): return False # Check if they're the same size s_sz = os.stat(source).st_size t_sz = os.stat(target).st_size if s_sz != t_sz: return False # Find each safe resource, and confirm that either (1) it's in the same # location in both executables, or (2) it's missing in both executables. locs = [] for (rtype,rid,rlang) in COMMON_SAFE_RESOURCES: try: s_loc = find_resource(source,rtype,rid,rlang) except WindowsError: s_loc = None try: t_loc = find_resource(target,rtype,rid,rlang) except WindowsError: t_loc = None if s_loc != t_loc: return False if s_loc is not None: locs.append(s_loc) # Confirm that no other portions of the file have changed if locs: locs.extend(((0,0),(s_sz,s_sz))) locs.sort() for (_,start),(stop,_) in pairwise(locs): if files_differ(source,target,start,stop): return False # Looks safe to me! return True