diff --git a/persoconf/main.py b/persoconf/main.py index 25002f8..546bf25 100755 --- a/persoconf/main.py +++ b/persoconf/main.py @@ -175,6 +175,43 @@ def copy_file_or_directory(logger, path_dst, path_src, overwrite=True): # The End. return True + +# ====================================== +def delete_file_or_dir(path, logger=None): + + # Set logger to '/dev/null' if it's not set + if logger is None: + logger = logging.getLogger("/dev/null") + logger.addHandler(logging.NullHandler()) + + # Try it as a dir first + try: + logger.info("Removing directory %s" % path) + shutil.rmtree(path) + + except FileNotFoundError: + logger.warning("File %s seems to be already deleted" % path) + return False + except PermissionError: + logger.warning("Cannot remove dir %s, you will have to do it manually" + % path) + return False + + # If not, try it as a file + except NotADirectoryError: + try: + logger.info("Removing file %s" % path) + os.remove(path) + + except PermissionError: + logger.warning( "Cannot remove file %s, you'll have to do it " \ + "manually" + % path ) + return False + + return True + + # ARGPARSE @@ -282,12 +319,17 @@ parser_del.add_argument( "app" , help="The app to delete, or the app to delete a " \ "conf file from" ) -parser_del.add_argument( "conf" , - nargs="?" , +parser_del.add_argument( "files" , + nargs="*" , type=str , - help="The conf file or directory to delete from " \ + help="The conf files or directories to delete from " \ "the app" ) +parser_del.add_argument( "--force-yes", "-y" , + action="store_true" , + help="Don't ask silly questions" ) + + # Parse arguments args = parser.parse_args() @@ -361,6 +403,98 @@ if args.command == "list": for app in persoconf.list_apps(logger=log): print(app) +# DELETE COMMAND +######################################## +if args.command == "delete": + + # Does this app really exists ? + try: + appmeta = Metafile( json_path = persoconf.path + +"/"+ args.app + +"/"+ persoconf.metafile ) + except FileNotFoundError: + log.error( "App %s does not seem to exist" % args.app ) + exit(1) + except MalformedMetafileError: + log.error( "Failed to load metafile from app %s" % args.app ) + exit(1) + + # Does the user want to remove files or the entire app ? + if args.files == []: + # Delete the entire app + + if ( args.force_yes + or yes_no_question("Really delete app '%s'?" % appmeta.name ) + ): + + shutil.rmtree( persoconf.path +"/"+ appmeta.name ) + log.warning("App %s was deleted" % appmeta.name) + + else: + log.warning("Nothing was deleted") + + exit(0) + + else: + # Delete all required files (or directories) + if ( not args.force_yes + and not yes_no_question( "Delete all files from following list: " \ + "%s from app %s?" + % (str(args.files),appmeta.name)) + ): + log.warning("Nothing was deleted") + exit(0) + + # The filenames can be confnames or real files names. For each we'll + # assume first that it's a confname, then that it's a file name if that + # fails. + dstdic = appmeta.get_files_dst2src() # Get that here for optimization + for f in args.files: + + # 1) It's probably a confname + if f in appmeta.files: + if delete_file_or_dir( logger = log , + path = persoconf.path + +"/"+ appmeta.name + +"/"+ f ): + # File deleted, let's delete the entry in Metafile + appmeta.del_file(f) + appmeta.save() + + else: + log.warning( "Something wrong occured while deleting " \ + "file %s" + % f ) + continue + + # 2) If not, it must be a real filename + else: + absf = contractuser(os.path.abspath(os.path.expanduser(f))) + if absf in dstdic: + if delete_file_or_dir( logger = log , + path = persoconf.path + +"/"+ appmeta.name + +"/"+ dstdir[absf] ): + # File deleted, let's delete the entry in Metafile + appmeta.del_file(dstdir[absf]) + appmeta.save() + + else: + log.warning( "Something wrong occured while " \ + "deleting file %s" + % f ) + continue + + + # 3) Otherwise, no idea what it is + else: + log.warning( "Cannot find file %s in app %s data; " \ + "ignoring it" + % (f, appmeta.name) ) + continue + + + # ADD COMMAND ######################################## if args.command == "add": @@ -475,7 +609,8 @@ if args.command == "update": if args.files != []: - dstdic = apps_to_update[app].get_files_dst2src() + dstdic = apps_to_update[app].get_files_dst2src() # Get that here + # for optimization # The filenames can be confnames or real files names. For each # we'll assume first that it's a confname, then that it's a file @@ -500,6 +635,7 @@ if args.command == "update": "Failed to update %s from %s ; ignoring" % ( f, apps_to_update[app].files[f]["dest"]) ) + continue # 2) If not, it must be a real filename else: @@ -521,12 +657,14 @@ if args.command == "update": log.warning( "Failed to update %s from %s ; " \ "ignoring" % (dstdic[absf], absf) ) + continue # 3) Otherwise, no idea what it is else: log.warning( "Cannot find file %s in app data; " \ "ignoring it" % f ) + continue # If they were no 'file' args, it means we need to update all files in # the app diff --git a/persoconf/metafile.py b/persoconf/metafile.py index 268e9f7..57955fe 100644 --- a/persoconf/metafile.py +++ b/persoconf/metafile.py @@ -56,6 +56,9 @@ class Metafile(): def add_file(self, name, dest): self.files[name] = { "dest": dest } + def del_file(self, name): + del self.files[name] + # Exceptions