def find(self, tags): """Return a list of files with all of the given tags. Parameters ---------- tags : list List of tags. List is not changed. Returns ------- list List of absolute paths, to the hard link under the first tag given. """ logger.debug("find(%r)", tags) assert len(tags) > 0 tagpaths = (dpath.pathfromtag(tag, self.root) if dpath.istag(tag) else tag for tag in tags) inodes = (set(os.lstat(x) for x in dpath.listdir(path)) for path in tagpaths) inodes = functools.reduce(set.intersection, inodes) logger.debug("found unique inodes %r", inodes) map = dict((os.lstat(x), x) for x in dpath.listdir( dpath.pathfromtag(tags[0], self.root))) logger.debug("using map %r", map) return [map[x] for x in inodes]
def find(self, tags): """Return a list of files with all of the given tags. Parameters ---------- tags : list List of tags. List is not changed. Returns ------- list List of absolute paths, to the hard link under the first tag given. """ logger.debug("find(%r)", tags) assert len(tags) > 0 tagpaths = (dpath.pathfromtag(tag, self.root) if dpath.istag(tag) else tag for tag in tags) inodes = (set(os.lstat(x) for x in dpath.listdir(path)) for path in tagpaths) inodes = functools.reduce(set.intersection, inodes) logger.debug("found unique inodes %r", inodes) map = dict( (os.lstat(x), x) for x in dpath.listdir(dpath.pathfromtag(tags[0], self.root))) logger.debug("using map %r", map) return [map[x] for x in inodes]
def test_istag(self): self.assertTrue(dpath.istag('//tag')) self.assertTrue(dpath.istag('//tag/madoka')) self.assertFalse(dpath.istag('/tag')) self.assertFalse(dpath.istag('/tag/hi')) self.assertFalse(dpath.istag('tag')) self.assertFalse(dpath.istag('tag/bye'))
def _fix_path(root, path): """Fixes path If path is a tag, return as is. Otherwise rebase path to root. Args: root: A string. Absolute path where FUSE is mounted. path: A string. Path relative to root. """ if dpath.istag(path): return path else: return _rebase_path(root, path)
def tag(self, file, tag): """Tag file with tag. If `file` is already tagged, nothing happens. This includes if the file is hardlinked under another name. Parameters ---------- file : str Path to the file, relative to the working directory. tag : str Tag, relative to the library root, starting with '/'. Raises ------ IsADirectoryError file is an unconverted directory. NotADirectoryError tag is not a directory/tag. """ file = os.path.normpath(file) # get rid of trailing slashes if os.path.isdir(file) and not os.path.islink(file): raise IsADirectoryError( '{} is a directory; convert it first'.format(file)) if dpath.istag(tag): p_dest = dpath.pathfromtag(tag, self.root) else: if not os.path.isdir(tag): raise NotADirectoryError( '{} is not a directory/tag'.format(tag)) p_dest = tag logger.info( 'Checking if %r is already tagged with %r', file, tag) for f in dpath.listdir(p_dest): if os.path.samefile(f, file): return logger.info('Check okay') name = os.path.basename(file) while True: dest = os.path.join(p_dest, dpath.resolve_name(p_dest, name)) logger.debug('linking %r %r', file, dest) try: os.link(file, dest) except FileExistsError: continue else: break
def tag(self, file, tag): """Tag file with tag. If `file` is already tagged, nothing happens. This includes if the file is hardlinked under another name. Parameters ---------- file : str Path to the file, relative to the working directory. tag : str Tag, relative to the library root, starting with '/'. Raises ------ IsADirectoryError file is an unconverted directory. NotADirectoryError tag is not a directory/tag. """ file = os.path.normpath(file) # get rid of trailing slashes if os.path.isdir(file) and not os.path.islink(file): raise IsADirectoryError( '{} is a directory; convert it first'.format(file)) if dpath.istag(tag): p_dest = dpath.pathfromtag(tag, self.root) else: if not os.path.isdir(tag): raise NotADirectoryError( '{} is not a directory/tag'.format(tag)) p_dest = tag logger.info('Checking if %r is already tagged with %r', file, tag) for f in dpath.listdir(p_dest): if os.path.samefile(f, file): return logger.info('Check okay') name = os.path.basename(file) while True: dest = os.path.join(p_dest, dpath.resolve_name(p_dest, name)) logger.debug('linking %r %r', file, dest) try: os.link(file, dest) except FileExistsError: continue else: break
def untag(self, file, tag): """Remove tag from file. If file is not tagged, nothing happens. Remove *all* hard links to the file in the directory corresponding to the given tag. Log a warning when an OSError is caught. Parameters ---------- file : str Path to the file, relative to the working directory. tag : str Tag, relative to the library root, starting with '/'. Raises ------ NotADirectoryError tag is not a directory/tag. """ logger.debug('untag(%r, %r)', file, tag) assert isinstance(file, str) assert isinstance(tag, str) if dpath.istag(tag): p_dest = dpath.pathfromtag(tag, self.root) else: if not os.path.isdir(tag): raise NotADirectoryError( '{} is not a directory/tag'.format(tag)) p_dest = tag inode = os.lstat(file) logger.debug('file inode is %r', inode) for f in dpath.listdir(p_dest): logger.debug('checking %r', f) st = os.lstat(f) logger.debug('inode is %r', st) if os.path.samestat(inode, st): logger.debug('unlinking %r', f) try: os.unlink(f) except OSError as e: logger.warning('Caught OSError: %s', e)
def rmtag(self, tag): if dpath.istag(tag): shutil.rmtree(dpath.pathfromtag(tag, self.root)) else: shutil.rmtree(tag)
def mktag(self, tag): if dpath.istag(tag): os.mkdir(dpath.pathfromtag(tag, self.root)) else: os.mkdir(tag)