diff --git a/persoconf/commands/check.py b/persoconf/commands/check.py new file mode 100644 index 0000000..5c70431 --- /dev/null +++ b/persoconf/commands/check.py @@ -0,0 +1,154 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import os.path +import filecmp + +# -------------------------------------- +def init(parser): + """Initialize check subcommand""" + + parser.add_argument( "app" , + type=str , + nargs="?" , + help="The app to check" ) + + parser.add_argument( "files" , + type=str , + nargs="*" , + default=[] , + help="The files to check ; default to all " \ + "added files" ) + + parser.add_argument( "-d", "--diff" , + type=str , + help="Print the diff between the saved and the new " \ + "file/directory" ) + + +# -------------------------------------- +def run(args, persoconf, logger): + + logger.debug("Starting 'check' command") + + # app == None => check all apps + apps_to_check = {} + if args.app is None: + apps_to_check = persoconf.list_apps(logger=logger) + + else: + try: + appmeta = Metafile( + json_path = os.path.join( persoconf.path, + args.app, + persoconf.metafile ) + ) + + apps_to_check[appmeta.name] = appmeta + + except FileNotFoundError: + logger.error( "Metafile %s does not exist for app %s" + % (persoconf.metafile, args.app) ) + exit(1) + + except MalformedMetafileError: + logger.error( "Malformed metafile %s in app %s" + % (persoconf.metafile, args.app) ) + exit(1) + + + for app in apps_to_check: + + logger.info( "App %s:" % app ) + + if args.files != []: + + dstdic = apps_to_check[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 + # name if that fails. + for f in args.files: + + # 1) It's probably a confname + if f in apps_to_check[app].files: + + persoconf_backup_path = os.path.join( persoconf.path, + app, + f ) + + original_file_path = apps_to_check[app].files[f]["dest"] + + _compare_and_log( original_file_path, + persoconf_backup_path, + logger ) + + # 2) If not, it must be a real filename + else: + + absf = contractuser(os.path.abspath(os.path.expanduser(f))) + if absf in dstdic: + + + persoconf_backup_path = os.path.join( persoconf.path, + app, + dstdic[absf] ) + + original_file_path = absf + + _compare_and_log( original_file_path, + persoconf_backup_path, + logger ) + + + # 3) Otherwise, no idea what it is + else: + logger.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 + else: + + for f in apps_to_check[app].files: + + persoconf_backup_path = os.path.join( persoconf.path, + app, + f ) + + original_file_path = apps_to_check[app].files[f]["dest"] + + _compare_and_log( original_file_path, + persoconf_backup_path, + logger ) + + +# -------------------------------------- +def _compare_and_log(original_file_path, persoconf_backup_path, logger): + """Compare a file with its persoconf backup and log the result (at info + level if the files are matching, warning level if they are not).""" + + resolved_ofp = os.path.expanduser(original_file_path) + resolved_pbp = os.path.expanduser(persoconf_backup_path) + + is_dir = os.path.isdir( resolved_ofp ) + + if filecmp.cmp(resolved_ofp, resolved_pbp) : + if is_dir: + logger.info( "No modification on %s/" + % original_file_path ) + else: + logger.info( "No modification on %s" + % original_file_path ) + + else: + if is_dir: + logger.warning( "Dir %s/ was modified" + % original_file_path ) + else: + logger.warning( "File %s was modified" + % original_file_path ) + diff --git a/persoconf/main.py b/persoconf/main.py index f2b2f64..5b07637 100755 --- a/persoconf/main.py +++ b/persoconf/main.py @@ -16,7 +16,7 @@ from persoconf import Persoconf, FileInsteadOfDirError, \ PersoconfRootDoesNotExistError import commands.list, commands.package, commands.update, commands.add, \ - commands.delete + commands.delete, commands.check @@ -71,6 +71,12 @@ parser_add = subparsers.add_parser( "add" , "to an existing app" ) commands.add.init(parser_add) +# Check +parser_check = subparsers.add_parser( "check" , + help="Checks if the backuped and the " \ + "original file are different." ) +commands.check.init(parser_check) + # Delete parser_del = subparsers.add_parser( "delete" , help="Delete an app from the persoconf " \ @@ -159,6 +165,11 @@ if args.command == "delete": if args.command == "add": commands.add.run(args, persoconf, log) +# CHECK COMMAND +######################################## +if args.command == "check": + commands.check.run(args, persoconf, log) + # UPDATE COMMAND ######################################## if args.command == "update":