def main(): parser = argparse.ArgumentParser( description= 'Receives output from "shatag -0" and records it in the local database ' ) parser.add_argument( '-d', '--database', metavar='DB', help='path to sqlite database (defaults to $HOME/.shatagdb)') parser.add_argument('-v', '--verbose', action='store_true', help='report additions to the database') parser.add_argument( '-b', '--base', metavar='PATH', help='base path getting processed (for deletion of older entries)', default='/') parser.add_argument('name', metavar='NAME', help='name of storage location') args = parser.parse_args() if args.base[-1] != '/': args.base += '/' store = shatag.Store(url=args.database, name=args.name) pattern = re.compile('([0-9a-f]{64}) (.*)') new_rows = 0 old_rows = store.clear(args.base) for entry in fileLineIter(sys.stdin, inputNewline='\0', outputNewline=''): match = pattern.match(entry) if match is not None: (hash, filename) = match.group(1, 2) if args.verbose: print("{0} {1}\n".format(hash, filename)) new_rows += 1 store.record(args.name, filename, hash) else: print('Error: incorrectly formatted entry\n', file=sys.stderr) if new_rows > 0: store.commit() print('{0} rows added, {1} rows deleted ({2})'.format( new_rows, old_rows, new_rows - old_rows), file=sys.stderr) else: store.rollback() print('No records received, preserving old database.', file=sys.stderr)
def main(): args = parser.parse_args() if args.files == []: if args.tag or args.update: print('shatag: Error: file name(s) required when using -t or -u', file=sys.stderr) else: args.files = filter( lambda x: (args.recursive or os.path.isfile(x)) and not x. startswith('.'), os.listdir('.')) if (args.quiet and (not args.verbose) and not (args.update or args.tag or args.put)): print( 'shatag: Warning: this combination of flags does not do anything.', file=sys.stderr) exit(1) if (args.quiet and args.null): print('shatag: Warning: --null useless when using --quiet', file=sys.stderr) end = args.null and '\0' or '\n' store = None if args.lookup or args.lookup_verbose or args.put: store = shatag.Store(name=args.name, url=args.database) backend = shatag.backend(args.backend) def process(filename): try: if args.recursive: if os.path.isdir(filename) and not os.path.islink(filename): [ process(os.path.join(filename, e)) for e in os.listdir(filename) if not e.startswith('.') ] return else: if not os.path.isfile(filename): print( 'shatag: Warning: {0} is not a file'.format(filename), file=sys.stderr) return file = backend.file(filename) if args.verbose: file.verbose() if args.force and (args.update or args.tag): file.rehash() if args.update: file.update() if args.tag: file.tag() try: if not (args.quiet or args.lookup or args.lookup_verbose): file.fsprint(file.show(canonical=args.canonical), end=end) if args.put: store.put(file) if args.lookup: file.fsprint( store.lookup(file, remotenames=args.remote).pretty()) if args.lookup_verbose: r = store.lookup(file) print("{0}:".format(file.path(canonical=args.canonical))) for (name, path) in (r.local + r.remote): print("\t{0}:{1}".format(name, path)) except shatag.NoChecksum: pass except IOError as e: print('shatag: "{0}": IOError {1}: {2}'.format( filename.encode(), e.errno, e.strerror), file=sys.stderr) if e.errno == errno.EPIPE: raise if e.errno == errno.ENOTSUP: print( 'shatag: "{0}": Operation Unsupported. Did you forget to enable user_xattr ?' .format(filename.encode()), file=sys.stderr) except OSError as e: print('shatag: {0}'.format(e), file=sys.stderr) for filename in args.files: if args.put and args.recursive: store.clear(os.path.abspath(filename)) process(filename) if args.put: store.commit()
def main(): config = shatag.Config() parser = argparse.ArgumentParser( description='Monitors files with inotify and automatically update') parser.add_argument('-u', '--update', action='store_true', help='Only update already tagged files') parser.add_argument('-p', '--put', action='store_true', help='Send new hashes to database') parser.add_argument('-v', '--verbose', action='store_true', help='report missing/invalid checksums') parser.add_argument('-b', '--backend', metavar='BACKEND', help='backend for local tag storage', default=config.backend) parser.add_argument('-r', '--recursive', action='store_true', help='watch recursively') parser.add_argument('-d', '--daemon', action='store_true', help='daemonize') parser.add_argument('paths', metavar='PATH', nargs='+', help='paths to monitor') args = parser.parse_args() backend = shatag.backend(args.backend) store = None if args.put: store = shatag.Store(name=config.name, url=config.database) print("shatagd: updating database {0} with name {1}".format( config.database, store.name), file=sys.stderr) class Handler(pyinotify.ProcessEvent): def process_IN_CLOSE_WRITE(self, evt): try: file = backend.file(evt.pathname) if args.update: file.update() else: file.tag() if args.verbose: print(evt.pathname) if args.put: store.put(file) store.commit() except IOError as e: print('shatagd: "{0}": IOError {1}: {2}'.format( filename, e.errno, e.strerror), file=sys.stderr) except OSError as e: print('shatagd: {0}'.format(e), file=sys.stderr) wm = pyinotify.WatchManager() nf = pyinotify.AsyncNotifier(wm, Handler()) nf.coalesce_events() for path in args.paths: if (args.daemon and path[0] != '/'): print( "Warning: relative path {0} ignored in daemon mode. Use absolute paths." .format(path), file=sys.stderr) else: wm.add_watch(path, pyinotify.IN_CLOSE_WRITE | pyinotify.IN_CREATE, rec=args.recursive, auto_add=args.recursive) if (args.daemon): print("Daemonizing...", file=sys.stderr) try: pid = os.fork() if pid > 0: sys.exit(0) os.chdir("/") os.setsid() os.umask(0) pid = os.fork() if pid > 0: sys.exit(0) except OSError as e: print("OS Error: {0}".format(e), file=sys.stderr) sys.exit(1) asyncore.loop()