def get_file_map(self, dest_root, ignore): merge_map = {} kwargs = {'follow_nonexisting': True, 'ignore': ignore} for src, dest in traverse_tree(self._root, dest_root, **kwargs): if not os.path.isdir(src): merge_map[src] = dest return merge_map
def merge(self, dest_root, link=os.symlink, **kwargs): """Link all files in src into dest, creating directories if necessary. If ignore_conflicts is True, do not break when the target exists but rather return a list of files that could not be linked. Note that files blocking directories will still cause an error. """ kwargs['order'] = 'pre' ignore_conflicts = kwargs.get("ignore_conflicts", False) existing = [] for src, dest in traverse_tree(self._root, dest_root, **kwargs): if os.path.isdir(src): if not os.path.exists(dest): mkdirp(dest) continue if not os.path.isdir(dest): raise ValueError("File blocks directory: %s" % dest) # mark empty directories so they aren't removed on unmerge. if not os.listdir(dest): marker = os.path.join(dest, empty_file_name) touch(marker) else: if os.path.exists(dest): if ignore_conflicts: existing.append(src) else: raise AssertionError("File already exists: %s" % dest) else: link(src, dest) if ignore_conflicts: return existing
def unmerge(self, dest_root, **kwargs): """Unlink all files in dest that exist in src. Unlinks directories in dest if they are empty. """ kwargs['order'] = 'post' for src, dest in traverse_tree(self._root, dest_root, **kwargs): if os.path.isdir(src): # Skip non-existing links. if not os.path.exists(dest): continue if not os.path.isdir(dest): raise ValueError("File blocks directory: %s" % dest) # remove directory if it is empty. if not os.listdir(dest): shutil.rmtree(dest, ignore_errors=True) # remove empty dir marker if present. marker = os.path.join(dest, empty_file_name) if os.path.exists(marker): os.remove(marker) elif os.path.exists(dest): if not os.path.islink(dest): raise ValueError("%s is not a link tree!" % dest) # remove if dest is a hardlink/symlink to src; this will only # be false if two packages are merged into a prefix and have a # conflicting file if filecmp.cmp(src, dest, shallow=True): os.remove(dest)
def find_dir_conflicts(self, dest_root, ignore): conflicts = [] kwargs = {'follow_nonexisting': False, 'ignore': ignore} for src, dest in traverse_tree(self._root, dest_root, **kwargs): if os.path.isdir(src): if os.path.exists(dest) and not os.path.isdir(dest): conflicts.append("File blocks directory: %s" % dest) elif os.path.exists(dest) and os.path.isdir(dest): conflicts.append("Directory blocks directory: %s" % dest) return conflicts
def find_conflict(self, dest_root, **kwargs): """Returns the first file in dest that conflicts with src""" kwargs['follow_nonexisting'] = False for src, dest in traverse_tree(self._root, dest_root, **kwargs): if os.path.isdir(src): if os.path.exists(dest) and not os.path.isdir(dest): return dest elif os.path.exists(dest): return dest return None
def merge_directories(self, dest_root, ignore): for src, dest in traverse_tree(self._root, dest_root, ignore=ignore): if os.path.isdir(src): if not os.path.exists(dest): mkdirp(dest) continue if not os.path.isdir(dest): raise ValueError("File blocks directory: %s" % dest) # mark empty directories so they aren't removed on unmerge. if not os.listdir(dest): marker = os.path.join(dest, empty_file_name) touch(marker)
def unmerge_directories(self, dest_root, ignore): for src, dest in traverse_tree( self._root, dest_root, ignore=ignore, order='post'): if os.path.isdir(src): if not os.path.exists(dest): continue elif not os.path.isdir(dest): raise ValueError("File blocks directory: %s" % dest) # remove directory if it is empty. if not os.listdir(dest): shutil.rmtree(dest, ignore_errors=True) # remove empty dir marker if present. marker = os.path.join(dest, empty_file_name) if os.path.exists(marker): os.remove(marker)