|  | @@ -0,0 +1,103 @@
 | 
											
												
													
														|  | 
 |  | +#!/usr/bin/python3
 | 
											
												
													
														|  | 
 |  | +# TODO: change the default file list to only apply to listing, not copying/erasing/creating/appending/zapping
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +VERSION = "0.1"
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +import os, sys, argparse
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +def file_copy(f,target,target_is_dir,force):
 | 
											
												
													
														|  | 
 |  | +  print(f"call file_copy with args={target},{target_is_dir} and {force}")
 | 
											
												
													
														|  | 
 |  | +  dest = target if not target_is_dir else target+'/'+os.path.basename(f)
 | 
											
												
													
														|  | 
 |  | +  if os.path.exists(dest) and not force:
 | 
											
												
													
														|  | 
 |  | +    go = input("The copy target <<" + dest + ">> exists. Overwrite? (y or n) ")
 | 
											
												
													
														|  | 
 |  | +    if go != 'y' and go != 'Y':
 | 
											
												
													
														|  | 
 |  | +      return
 | 
											
												
													
														|  | 
 |  | +  print(f"copy from {f} to {dest}")
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +def file_zap(f,all_flag):
 | 
											
												
													
														|  | 
 |  | +  print(f"zapping the comment history of {f}")
 | 
											
												
													
														|  | 
 |  | +  if all_flag:
 | 
											
												
													
														|  | 
 |  | +    print("zapping the entire database")
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +def file_erase(f, extra):
 | 
											
												
													
														|  | 
 |  | +  print(f"erase the comment on file {f}")
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +def main(args):
 | 
											
												
													
														|  | 
 |  | +  parser = argparse.ArgumentParser(description="Display or add comments to files",
 | 
											
												
													
														|  | 
 |  | +    epilog="Some options conflict. Use only one of: -l -c -a -H -e -z -Z and one of -d -x")
 | 
											
												
													
														|  | 
 |  | +  parser.add_argument('-V',"--version", action="version",version=f"dncli ver:{VERSION}")
 | 
											
												
													
														|  | 
 |  | +  parser.add_argument('-v',"--verbose", action='store_true',help="verbose, almost debugging; do not use in scripts")
 | 
											
												
													
														|  | 
 |  | +  parser.add_argument('-j',"--json",    action="store_true",help="output in JSON format")
 | 
											
												
													
														|  | 
 |  | +  parser.add_argument('-l',"--listall", action="store_true",help="list all files, including those without comments")
 | 
											
												
													
														|  | 
 |  | +  parser.add_argument('-d',"--db",      action="store_true",help="list comments from database")
 | 
											
												
													
														|  | 
 |  | +  parser.add_argument('-x',"--xattr",   action="store_true",help="list comments from xattr")
 | 
											
												
													
														|  | 
 |  | +  parser.add_argument('-n',"--minimal", action="store_true",help="output only comments; useful in scripting")
 | 
											
												
													
														|  | 
 |  | +  parser.add_argument('-H',"--history", action="store_true",help="output the history of comments for a file")
 | 
											
												
													
														|  | 
 |  | +  parser.add_argument('-c',"--create",  metavar="comment",  help="add a comment to a file")
 | 
											
												
													
														|  | 
 |  | +  parser.add_argument('-a',"--append",  metavar="comment",  help="append to a comment on a file, separator=';'")
 | 
											
												
													
														|  | 
 |  | +  parser.add_argument('-C',"--copy",    action="store_true",help="copy a file with its comments")
 | 
											
												
													
														|  | 
 |  | +  parser.add_argument('-y',"--cp_force",action="store_true",help="copy over existing files")
 | 
											
												
													
														|  | 
 |  | +  parser.add_argument('-e',"--erase",   action="store_true",help="erase the comment on a file")
 | 
											
												
													
														|  | 
 |  | +  parser.add_argument('-z',"--zap",     action="store_true",help="clear the comment history on a file")
 | 
											
												
													
														|  | 
 |  | +  parser.add_argument('-Z',"--zapall",   action="store_true",help="clear the comment history in the entire database")
 | 
											
												
													
														|  | 
 |  | +  parser.add_argument('file_list',nargs='*',help="file(s) for comments; default is all files in ./")
 | 
											
												
													
														|  | 
 |  | +  args = parser.parse_args()
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +  # default is to display all files that have comments
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +  # major modes are: display (-l -H), add-comment (-a -c -e), clear-history(-z -Z), copy (-C)
 | 
											
												
													
														|  | 
 |  | +  # determine the major mode, then apply an appropriate function over the file_list
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +  #====== 1) build the file list =============
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +  files = args.file_list
 | 
											
												
													
														|  | 
 |  | +  if not files:
 | 
											
												
													
														|  | 
 |  | +    files = os.listdir(".")
 | 
											
												
													
														|  | 
 |  | +  # if the user gave me a single dir...expand it
 | 
											
												
													
														|  | 
 |  | +  elif len(files)==1 and os.path.isdir(files[0]):
 | 
											
												
													
														|  | 
 |  | +    files = os.listdir(files[0])
 | 
											
												
													
														|  | 
 |  | +  print("got the files:", files)
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +  #======= 2) build the function
 | 
											
												
													
														|  | 
 |  | +  if args.create or args.append:
 | 
											
												
													
														|  | 
 |  | +    print(f"create/append: {args.create} . {args.append}")
 | 
											
												
													
														|  | 
 |  | +  elif args.erase:
 | 
											
												
													
														|  | 
 |  | +    print(f"erase command")
 | 
											
												
													
														|  | 
 |  | +    func = file_erase
 | 
											
												
													
														|  | 
 |  | +    loop_args = (0,)
 | 
											
												
													
														|  | 
 |  | +  elif args.zap or args.zapall:
 | 
											
												
													
														|  | 
 |  | +    print(f"got a zap command {args.zap} . {args.zapall}")
 | 
											
												
													
														|  | 
 |  | +    func = file_zap
 | 
											
												
													
														|  | 
 |  | +    loop_args = (args.zapall,)
 | 
											
												
													
														|  | 
 |  | +    if args.zapall:
 | 
											
												
													
														|  | 
 |  | +      files = (1,)
 | 
											
												
													
														|  | 
 |  | +  elif args.copy:
 | 
											
												
													
														|  | 
 |  | +    print(f"got a copy command to {args.copy}")
 | 
											
												
													
														|  | 
 |  | +    # the last item on the file list is the target
 | 
											
												
													
														|  | 
 |  | +    n_files = len(files)
 | 
											
												
													
														|  | 
 |  | +    if n_files < 2:
 | 
											
												
													
														|  | 
 |  | +      print(f"the copy command requires at least two arguments, the last one is the destination")
 | 
											
												
													
														|  | 
 |  | +      sys.exit(1)
 | 
											
												
													
														|  | 
 |  | +    target = files[-1]
 | 
											
												
													
														|  | 
 |  | +    target_is_directory = os.path.isdir(target)
 | 
											
												
													
														|  | 
 |  | +    files = files[:-1]
 | 
											
												
													
														|  | 
 |  | +    print(f"copy from {files} to {target}")
 | 
											
												
													
														|  | 
 |  | +    if n_files > 2 and not target_is_directory:
 | 
											
												
													
														|  | 
 |  | +      print(f"multiple copy files must go to a target directory")
 | 
											
												
													
														|  | 
 |  | +      sys.exit(3)
 | 
											
												
													
														|  | 
 |  | +    func = file_copy
 | 
											
												
													
														|  | 
 |  | +    loop_args = (target, target_is_directory, args.cp_force)
 | 
											
												
													
														|  | 
 |  | +  else:
 | 
											
												
													
														|  | 
 |  | +    print(f"display command with option: {args.listall}")
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +  #====== 3) loop on the list, execute the function =============
 | 
											
												
													
														|  | 
 |  | +  for f in files:
 | 
											
												
													
														|  | 
 |  | +    func(f,*loop_args)
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +if __name__ == "__main__":
 | 
											
												
													
														|  | 
 |  | +  main(sys.argv)
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +
 |