Example #1
0
    def uninstall(self):
        """
        Uninstall Mackup.

        Restore any file where it was before the 1st Mackup backup.

        Algorithm:
            for each file in config
                if mackup/file exists
                    if home/file exists
                        delete home/file
                    copy mackup/file home/file
            delete the mackup folder
            print how to delete mackup
        """
        # For each file used by the application
        for filename in self.files:
            (home_filepath, mackup_filepath) = self.getFilepaths(filename)

            # If the mackup file exists
            if os.path.isfile(mackup_filepath) or os.path.isdir(
                    mackup_filepath):
                # Check if there is a corresponding file in the home folder
                if os.path.exists(home_filepath):
                    if self.verbose:
                        print(
                            colorize_text("Reverting ") +
                            colorize_filename(mackup_filepath) + "\n  " +
                            colorize_text("at ") +
                            colorize_filename(home_filepath) +
                            colorize_text(" ..."))
                    else:
                        print(
                            colorize_text("Reverting ") +
                            colorize_filename(filename) +
                            colorize_text(" ..."))

                    if self.dry_run:
                        continue

                    # If there is, delete it as we are gonna copy the Dropbox
                    # one there
                    utils.delete(home_filepath)

                    # Copy the Dropbox file to the home folder
                    utils.copy(mackup_filepath, home_filepath)
            elif self.verbose:
                print(
                    colorize_text("Doing nothing, ") +
                    colorize_filename(mackup_filepath) +
                    colorize_text(" does not exist"))
Example #2
0
    def backup(self):
        """
        Backup the application config files.

        Algorithm:
            if exists home/file
              if home/file is a real file
                if exists mackup/file
                  are you sure ?
                  if sure
                    rm mackup/file
                    mv home/file mackup/file
                    link mackup/file home/file
                else
                  mv home/file mackup/file
                  link mackup/file home/file
        """
        # For each file used by the application
        for filename in self.files:
            (home_filepath, mackup_filepath) = self.getFilepaths(filename)

            # If the file exists and is not already a link pointing to Mackup
            if (os.path.isfile(home_filepath) or os.path.isdir(home_filepath)
                ) and not (os.path.islink(home_filepath) and
                           (os.path.isfile(mackup_filepath)
                            or os.path.isdir(mackup_filepath)) and
                           os.path.samefile(home_filepath, mackup_filepath)):

                if self.verbose:
                    print((colorize_text("Backing up") + "\n  " +
                           colorize_filename(home_filepath) + "\n  " +
                           colorize_text("to") + "\n  " +
                           colorize_filename(mackup_filepath) +
                           colorize_text(" ...")))
                else:
                    print(
                        (colorize_text("Backing up ") +
                         colorize_filename(filename) + colorize_text(" ...")))

                if self.dry_run:
                    continue

                # Check if we already have a backup
                if os.path.exists(mackup_filepath):

                    # Name it right
                    if os.path.isfile(mackup_filepath):
                        file_type = "file"
                    elif os.path.isdir(mackup_filepath):
                        file_type = "folder"
                    elif os.path.islink(mackup_filepath):
                        file_type = "link"
                    else:
                        raise ValueError(
                            "Unsupported file: {}".format(mackup_filepath))

                    # Ask the user if he really want to replace it
                    if utils.confirm("A {} named {} already exists in the"
                                     " backup.\nAre you sure that you want to"
                                     " replace it ?".format(
                                         file_type, mackup_filepath)):
                        # Delete the file in Mackup
                        utils.delete(mackup_filepath)
                        # Copy the file
                        utils.copy(home_filepath, mackup_filepath)
                        # Delete the file in the home
                        utils.delete(home_filepath)
                        # Link the backuped file to its original place
                        utils.link(mackup_filepath, home_filepath)
                else:
                    # Copy the file
                    utils.copy(home_filepath, mackup_filepath)
                    # Delete the file in the home
                    utils.delete(home_filepath)
                    # Link the backuped file to its original place
                    utils.link(mackup_filepath, home_filepath)
            elif self.verbose:
                if os.path.exists(home_filepath):
                    print(
                        colorize_text("Doing nothing") + "\n  " +
                        colorize_filename(home_filepath) + "\n  " +
                        colorize_text("is already backed up to") + "\n  " +
                        colorize_filename(mackup_filepath))
                elif os.path.islink(home_filepath):
                    print(
                        colorize_text("Doing nothing") + "\n  " +
                        colorize_filename(home_filepath) + "\n  " +
                        colorize_text(
                            "is a broken link, you might want to fix it."))
                else:
                    print(
                        colorize_text("Doing nothing") + "\n  " +
                        colorize_filename(home_filepath) + "\n" +
                        colorize_text("does not exist"))
Example #3
0
def main():
    """Main function."""
    # Get the command line arg
    args = docopt(__doc__, version="Mackup {}".format(VERSION))

    mckp = Mackup()
    app_db = ApplicationsDatabase()

    def printAppHeader(app_name):
        if verbose:
            print("\n" + colorize_header("---") + " " +
                  colorize_header_app_name(app_name) + " " +
                  colorize_header("---"))

    # If we want to answer mackup with "yes" for each question
    if args["--force"]:
        utils.FORCE_YES = True

    # Allow mackup to be run as root
    if args["--root"]:
        utils.CAN_RUN_AS_ROOT = True

    dry_run = args["--dry-run"]

    verbose = args["--verbose"]

    if args["backup"]:
        # Check the env where the command is being run
        mckp.check_for_usable_backup_env()

        # Backup each application
        for app_name in sorted(mckp.get_apps_to_backup()):
            app = ApplicationProfile(mckp, app_db.get_files(app_name), dry_run,
                                     verbose)
            printAppHeader(app_name)
            app.backup()

    elif args["restore"]:
        # Check the env where the command is being run
        mckp.check_for_usable_restore_env()

        # Restore the Mackup config before any other config, as we might need
        # it to know about custom settings
        mackup_app = ApplicationProfile(mckp,
                                        app_db.get_files(MACKUP_APP_NAME),
                                        dry_run, verbose)
        printAppHeader(MACKUP_APP_NAME)
        mackup_app.restore()

        # Initialize again the apps db, as the Mackup config might have changed
        # it
        mckp = Mackup()
        app_db = ApplicationsDatabase()

        # Restore the rest of the app configs, using the restored Mackup config
        app_names = mckp.get_apps_to_backup()
        # Mackup has already been done
        app_names.discard(MACKUP_APP_NAME)

        for app_name in sorted(app_names):
            app = ApplicationProfile(mckp, app_db.get_files(app_name), dry_run,
                                     verbose)
            printAppHeader(app_name)
            app.restore()

    elif args["uninstall"]:
        # Check the env where the command is being run
        mckp.check_for_usable_restore_env()

        if dry_run or (utils.confirm(
                colorize_text(
                    "You are going to uninstall Mackup.\n"
                    "Every configuration file, setting and dotfile"
                    " managed by Mackup will be unlinked and moved back"
                    " to their original place, in your home folder.\n"
                    "Are you sure ?"))):

            # Uninstall the apps except Mackup, which we'll uninstall last, to
            # keep the settings as long as possible
            app_names = mckp.get_apps_to_backup()
            app_names.discard(MACKUP_APP_NAME)

            for app_name in sorted(app_names):
                app = ApplicationProfile(mckp, app_db.get_files(app_name),
                                         dry_run, verbose)
                printAppHeader(app_name)
                app.uninstall()

            # Restore the Mackup config before any other config, as we might
            # need it to know about custom settings
            mackup_app = ApplicationProfile(mckp,
                                            app_db.get_files(MACKUP_APP_NAME),
                                            dry_run, verbose)
            mackup_app.uninstall()

            # Delete the Mackup folder in Dropbox
            # Don't delete this as there might be other Macs that aren't
            # uninstalled yet
            # delete(mckp.mackup_folder)

            print(
                colorize_text(
                    "\n"
                    "All your files have been put back into place. You can now"
                    " safely uninstall Mackup.\n"
                    "\n"
                    "Thanks for using Mackup !"))

    elif args["list"]:
        # Display the list of supported applications
        mckp.check_for_usable_environment()
        output = colorize_text("Supported applications:") + "\n"
        for app_name in sorted(app_db.get_app_names()):
            output += colorize_item_bullet(" - ") + colorize_filename(
                app_name) + "\n"
        output += "\n"
        output += colorize_text(
            "{} applications supported in Mackup v{}".format(
                len(app_db.get_app_names()), VERSION))
        print(output)

    elif args["show"]:
        mckp.check_for_usable_environment()
        app_name = args["<application>"]

        # Make sure the app exists
        if app_name not in app_db.get_app_names():
            sys.exit("Unsupported application: {}".format(app_name))
        print(
            colorize_text("Name: ") + colorize_name(app_db.get_name(app_name)))
        print(colorize_text("Configuration files:"))
        for file in app_db.get_files(app_name):
            print(colorize_item_bullet(" - ") + colorize_filename(file))

    # Delete the tmp folder
    mckp.clean_temp_folder()
Example #4
0
    def restore(self):
        """
        Restore the application config files.

        Algorithm:
            if exists mackup/file
              if exists home/file
                are you sure ?
                if sure
                  rm home/file
                  link mackup/file home/file
              else
                link mackup/file home/file
        """
        # For each file used by the application
        for filename in self.files:
            (home_filepath, mackup_filepath) = self.getFilepaths(filename)

            # If the file exists and is not already pointing to the mackup file
            # and the folder makes sense on the current platform (Don't sync
            # any subfolder of ~/Library on GNU/Linux)
            file_or_dir_exists = os.path.isfile(
                mackup_filepath) or os.path.isdir(mackup_filepath)
            pointing_to_mackup = (os.path.islink(home_filepath)
                                  and os.path.exists(mackup_filepath)
                                  and os.path.samefile(mackup_filepath,
                                                       home_filepath))
            supported = utils.can_file_be_synced_on_current_platform(filename)

            if file_or_dir_exists and not pointing_to_mackup and supported:
                if self.verbose:
                    print(
                        colorize_text("Restoring\n  linking ") +
                        colorize_filename(home_filepath) + "\n  " +
                        colorize_text("to      ") +
                        colorize_filename(mackup_filepath) +
                        colorize_text(" ..."))
                else:
                    print(
                        colorize_text("Restoring ") +
                        colorize_filename(filename) + colorize_text(" ..."))

                if self.dry_run:
                    continue

                # Check if there is already a file in the home folder
                if os.path.exists(home_filepath):
                    # Name it right
                    if os.path.isfile(home_filepath):
                        file_type = "file"
                    elif os.path.isdir(home_filepath):
                        file_type = "folder"
                    elif os.path.islink(home_filepath):
                        file_type = "link"
                    else:
                        raise ValueError(
                            "Unsupported file: {}".format(mackup_filepath))

                    if utils.confirm("You already have a {} named {} in your"
                                     " home.\nDo you want to replace it with"
                                     " your backup ?".format(
                                         file_type, filename)):
                        utils.delete(home_filepath)
                        utils.link(mackup_filepath, home_filepath)
                else:
                    utils.link(mackup_filepath, home_filepath)
            elif self.verbose:
                if os.path.exists(home_filepath):
                    print(
                        colorize_text("Doing nothing") + "\n  " +
                        colorize_filename(mackup_filepath) + "\n  " +
                        colorize_text("already linked by") + "\n  " +
                        colorize_filename(home_filepath))
                elif os.path.islink(home_filepath):
                    print(
                        colorize_text("Doing nothing") + "\n  " +
                        colorize_filename(home_filepath) + "\n  " +
                        colorize_text(
                            "is a broken link, you might want to fix it."))
                else:
                    print(
                        colorize_text("Doing nothing") + "\n  " +
                        colorize_filename(mackup_filepath) + "\n" +
                        colorize_text("does not exist"))
Example #5
0
 def test_colorize_filename(self):
     assert colorize_filename("Blah") == "\x1b[1;34mBlah\x1b[0m"