Пример #1
0
def sync_gridsome() -> None:
    """
    指定のローカルとリモートディレクトリを同期する
    """

    cfg = configparser.ConfigParser()
    cfg.read("config.ini")

    # ローカルとリモートの設定
    local = FsTarget(cfg["PATH"]["LOCAL"])
    user = cfg["FTPS"]["USER"]
    passwd = cfg["FTPS"]["PASSWORD"]
    remote = FtpTarget(
        cfg["PATH"]["REMOTE"],  # リモートディレクトリパス
        cfg["FTPS"]["SERVER"],  # FTPサーバ
        username=user,
        password=passwd,
        tls=True,  # FTPS有効
    )

    # オプション設定
    # ローカル優先/--deleteオプション有効/指定ディレクトリは同期除外
    # opts = {"resolve": "local", "delete": True, "force": True}
    opts = {"resolve": "local"}

    # 同期の実行
    sync = BiDirSynchronizer(local, remote, opts)
    sync.run()
Пример #2
0
def do_sync():
    from ftpsync.synchronizers import BiDirSynchronizer
    from ftpsync.targets import make_target

    local_target = make_target("~/test_pyftpsync_dl")
    # local_target = make_target("c:/tmp/test_pyftpsync")
    remote_target = make_target("ftp://wwwendt.de/test_pyftpsync", {"ftp_debug": False})
    opts = {"verbose": 6, "dry_run": False, "resolve": "local"}
    s = BiDirSynchronizer(local_target, remote_target, opts)
    s.run()
Пример #3
0
def _sync_test_folders(options):
    """Run bi-dir sync with fresh objects."""
    local = FsTarget(os.path.join(PYFTPSYNC_TEST_FOLDER, "local"))
    remote = FsTarget(os.path.join(PYFTPSYNC_TEST_FOLDER, "remote"))
    opts = {"dry_run": False, "verbose": 3}
    if options:
        opts.update(options)
    
    s = BiDirSynchronizer(local, remote, opts)
    s.run()
    return s.get_stats()
Пример #4
0
def _sync_test_folders(options):
    """Run bi-dir sync with fresh objects."""
    local = FsTarget(os.path.join(PYFTPSYNC_TEST_FOLDER, "local"))
    remote = FsTarget(os.path.join(PYFTPSYNC_TEST_FOLDER, "remote"))
    opts = {"dry_run": False, "verbose": 3}
    if options:
        opts.update(options)

    s = BiDirSynchronizer(local, remote, opts)
    s.run()
    return s.get_stats()
Пример #5
0
def do_sync():
    from ftpsync.synchronizers import BiDirSynchronizer
    from ftpsync.targets import make_target

    local_target = make_target("~/test_pyftpsync_dl")
    # local_target = make_target("c:/tmp/test_pyftpsync")
    remote_target = make_target("ftp://wwwendt.de/test_pyftpsync",
                                {"ftp_debug": False})
    opts = {"verbose": 6, "dry_run": False, "resolve": "local"}
    s = BiDirSynchronizer(local_target, remote_target, opts)
    s.run()
Пример #6
0
def synchronize(user, password):
    print "syncing..."
    try:
        local = FsTarget(DEPLOY_FOLDER)
        remote = FtpTarget(FTP_TARGET, FTP_HOST, user, password, tls=True)
        opts = {"resolve": "skip", "verbose": 1, "dry_run": False}
        s = BiDirSynchronizer(local, remote, opts)
        s.run()
        print "sync complete..."
    except Exception as e:
        print type(e)
        print e.args
        print e
Пример #7
0
def synchronize(user, password):
    print "syncing..."
    try:
        local = FsTarget(DEPLOY_FOLDER)
        remote = FtpTarget(FTP_TARGET, FTP_HOST, user, password, tls=True)
        opts = {"resolve": "skip", "verbose": 1, "dry_run" : False}
        s = BiDirSynchronizer(local, remote, opts)
        s.run()
        print "sync complete..."
    except Exception as e:
        print type(e)
        print e.args
        print e
Пример #8
0
    def test_sync_conflicts(self):
        local = FsTarget(os.path.join(PYFTPSYNC_TEST_FOLDER, "local"))
        remote = FsTarget(os.path.join(PYFTPSYNC_TEST_FOLDER, "remote"))
        opts = {
            "dry_run": False,
            "verbose": self.verbose
        }  # , "resolve": "ask"}

        # Copy local -> remote

        s = BiDirSynchronizer(local, remote, opts)
        s.run()
        stats = s.get_stats()
        self.assertEqual(stats["files_written"], 6)
        self.assertEqual(stats["dirs_created"], 2)

        # Modify local and remote

        # conflict 1: local is newer
        dt = datetime.datetime.utcnow()
        touch_test_file("local/file1.txt", dt)
        dt = datetime.datetime.utcnow() - datetime.timedelta(seconds=10)
        touch_test_file("remote/file1.txt", dt=dt)
        #         path = os.path.join(PYFTPSYNC_TEST_FOLDER, "remote/file1.txt")
        #         stamp = time.time() - 10
        #         os.utime(path, (stamp, stamp))

        # conflict 2: remote is newer
        touch_test_file("remote/file2.txt")
        dt = datetime.datetime.utcnow() - datetime.timedelta(seconds=10)
        touch_test_file("local/file2.txt", dt=dt)

        s = BiDirSynchronizer(local, remote, opts)
        s.run()
        stats = s.get_stats()
        #         pprint(stats)
        self.assertEqual(stats["entries_seen"], 18)
        self.assertEqual(stats["entries_touched"], 0)
        self.assertEqual(stats["bytes_written"], 0)
        self.assertEqual(stats["conflict_files"], 2)
Пример #9
0
    def test_sync_conflicts(self):
        local = FsTarget(os.path.join(PYFTPSYNC_TEST_FOLDER, "local"))
        remote = FsTarget(os.path.join(PYFTPSYNC_TEST_FOLDER, "remote"))
        opts = {"dry_run": False, "verbose": 3}
        
        # Copy local -> remote
        
        s = BiDirSynchronizer(local, remote, opts)
        s.run()
        stats = s.get_stats()
        self.assertEqual(stats["files_written"], 6)
        self.assertEqual(stats["dirs_created"], 2)
        
        # Modify local and remote

        # conflict 1: local is newer 
        dt = datetime.datetime.now()
        _touch_test_file("local/file1.txt", dt)
        dt = datetime.datetime.now() - datetime.timedelta(seconds=10)
        _touch_test_file("remote/file1.txt", dt=dt)
#         path = os.path.join(PYFTPSYNC_TEST_FOLDER, "remote/file1.txt")
#         stamp = time.time() - 10
#         os.utime(path, (stamp, stamp))

        # conflict 2: remote is newer 
        _touch_test_file("remote/file2.txt")
        dt = datetime.datetime.now() - datetime.timedelta(seconds=10)
        _touch_test_file("local/file2.txt", dt=dt)


        s = BiDirSynchronizer(local, remote, opts)
        s.run()
        stats = s.get_stats()
#         pprint(stats)
        self.assertEqual(stats["entries_seen"], 18)
        self.assertEqual(stats["entries_touched"], 0)
        self.assertEqual(stats["bytes_written"], 0)
        self.assertEqual(stats["conflict_files"], 2)
Пример #10
0
    def test_sync_fs_fs(self):
        local = FsTarget(os.path.join(PYFTPSYNC_TEST_FOLDER, "local"))
        remote = FsTarget(os.path.join(PYFTPSYNC_TEST_FOLDER, "remote"))
        opts = {"dry_run": False, "verbose": self.verbose}  # , "resolve": "ask"}
        s = BiDirSynchronizer(local, remote, opts)
        s.run()
        stats = s.get_stats()
        #        pprint(stats)
        self.assertEqual(stats["local_dirs"], 2)
        # currently files are not counted, when inside a *new* folder:
        self.assertEqual(stats["local_files"], 4)
        self.assertEqual(stats["remote_dirs"], 0)
        self.assertEqual(stats["remote_files"], 0)
        self.assertEqual(stats["files_written"], 6)
        self.assertEqual(stats["dirs_created"], 2)
        self.assertEqual(stats["bytes_written"], 16403)
        # file times are preserved
        self.assertEqual(get_test_file_date("local/file1.txt"), STAMP_20140101_120000)
        self.assertEqual(get_test_file_date("remote/file1.txt"), STAMP_20140101_120000)

        # Again: nothing to do
        s = BiDirSynchronizer(local, remote, opts)
        s.run()
        stats = s.get_stats()
        #        pprint(stats)
        self.assertEqual(stats["local_dirs"], 2)
        self.assertEqual(stats["local_files"], 6)
        self.assertEqual(stats["remote_dirs"], 2)
        self.assertEqual(stats["remote_files"], 6)
        self.assertEqual(stats["files_created"], 0)
        self.assertEqual(stats["files_deleted"], 0)
        self.assertEqual(stats["files_written"], 0)
        self.assertEqual(stats["dirs_created"], 0)
        self.assertEqual(stats["bytes_written"], 0)

        # Modify remote and/or remote
        touch_test_file("local/file1.txt")
        touch_test_file("remote/file2.txt")
        # file3.txt will cause a conflict:
        touch_test_file("local/file3.txt")
        dt = datetime.datetime.utcnow() - datetime.timedelta(seconds=10)
        touch_test_file("remote/file3.txt", dt=dt)

        s = BiDirSynchronizer(local, remote, opts)
        s.run()
        stats = s.get_stats()
        #        pprint(stats)
        self.assertEqual(stats["entries_seen"], 18)
        self.assertEqual(stats["entries_touched"], 2)
        self.assertEqual(stats["files_created"], 0)
        self.assertEqual(stats["files_deleted"], 0)
        self.assertEqual(stats["files_written"], 2)
        self.assertEqual(stats["dirs_created"], 0)
        self.assertEqual(stats["download_files_written"], 1)
        self.assertEqual(stats["upload_files_written"], 1)
        self.assertEqual(stats["conflict_files"], 1)
        self.assertEqual(stats["bytes_written"], 6)
Пример #11
0
    def test_sync_fs_fs(self):
        local = FsTarget(os.path.join(PYFTPSYNC_TEST_FOLDER, "local"))
        remote = FsTarget(os.path.join(PYFTPSYNC_TEST_FOLDER, "remote"))
        opts = {"dry_run": False, "verbose": 3}
        s = BiDirSynchronizer(local, remote, opts)
        s.run()
        stats = s.get_stats()
#        pprint(stats)
        self.assertEqual(stats["local_dirs"], 2)
        self.assertEqual(stats["local_files"], 4) # currently files are not counted, when inside a *new* folder
        self.assertEqual(stats["remote_dirs"], 0)
        self.assertEqual(stats["remote_files"], 0)
        self.assertEqual(stats["files_written"], 6)
        self.assertEqual(stats["dirs_created"], 2)
        self.assertEqual(stats["bytes_written"], 16403)
        # file times are preserved
        self.assertEqual(_get_test_file_date("local/file1.txt"), STAMP_20140101_120000)
        self.assertEqual(_get_test_file_date("remote/file1.txt"), STAMP_20140101_120000)
        
        
        # Again: nothing to do
        s = BiDirSynchronizer(local, remote, opts)
        s.run()
        stats = s.get_stats()
#        pprint(stats)
        self.assertEqual(stats["local_dirs"], 2)
        self.assertEqual(stats["local_files"], 6)
        self.assertEqual(stats["remote_dirs"], 2)
        self.assertEqual(stats["remote_files"], 6)
        self.assertEqual(stats["files_created"], 0)
        self.assertEqual(stats["files_deleted"], 0)
        self.assertEqual(stats["files_written"], 0)
        self.assertEqual(stats["dirs_created"], 0)
        self.assertEqual(stats["bytes_written"], 0)

        # Modify remote and/or remote
        _touch_test_file("local/file1.txt")
        _touch_test_file("remote/file2.txt")
        # file3.txt will cause a conflict:
        _touch_test_file("local/file3.txt")
        dt = datetime.datetime.now() - datetime.timedelta(seconds=10)
        _touch_test_file("remote/file3.txt", dt=dt)

        s = BiDirSynchronizer(local, remote, opts)
        s.run()
        stats = s.get_stats()
#        pprint(stats)
        self.assertEqual(stats["entries_seen"], 18)
        self.assertEqual(stats["entries_touched"], 2)
        self.assertEqual(stats["files_created"], 0)
        self.assertEqual(stats["files_deleted"], 0)
        self.assertEqual(stats["files_written"], 2)
        self.assertEqual(stats["dirs_created"], 0)
        self.assertEqual(stats["download_files_written"], 1)
        self.assertEqual(stats["upload_files_written"], 1)
        self.assertEqual(stats["conflict_files"], 1)
        self.assertEqual(stats["bytes_written"], 6)
Пример #12
0
    def test_sync_fs_ftp(self):
        local = FsTarget(os.path.join(PYFTPSYNC_TEST_FOLDER, "local"))
        remote = self.remote

        # Upload all of temp/local to remote

        opts = {"force": False, "delete": True, "verbose": 3}
        s = UploadSynchronizer(local, remote, opts)
        s.run()

        stats = s.get_stats()
        #         pprint(stats)

        self.assertEqual(stats["local_dirs"], 2)
        # currently files are not counted, when inside a *new* folder:
        self.assertEqual(stats["local_files"], 4)
        self.assertEqual(stats["remote_dirs"], 0)
        self.assertEqual(stats["remote_files"], 0)
        self.assertEqual(stats["files_written"], 6)
        self.assertEqual(stats["dirs_created"], 2)
        self.assertEqual(stats["bytes_written"], 16403)

        # Change one file and upload again

        touch_test_file("local/file1.txt")

        opts = {"force": False, "delete": True, "verbose": 3}
        s = UploadSynchronizer(local, remote, opts)
        s.run()
        stats = s.get_stats()
        #         pprint(stats)
        #         assert False

        self.assertEqual(stats["entries_seen"], 18)  # ???
        self.assertEqual(stats["entries_touched"], 1)
        self.assertEqual(stats["files_created"], 0)
        self.assertEqual(stats["files_deleted"], 0)
        self.assertEqual(stats["files_written"], 1)
        self.assertEqual(stats["dirs_created"], 0)
        self.assertEqual(stats["download_files_written"], 0)
        self.assertEqual(stats["upload_files_written"], 1)
        self.assertEqual(stats["conflict_files"], 0)
        self.assertEqual(stats["bytes_written"], 3)

        # Download all from remote to temp/remote

        local = FsTarget(os.path.join(PYFTPSYNC_TEST_FOLDER, "remote"))

        opts = {"force": False, "delete": True, "verbose": 3}
        s = DownloadSynchronizer(local, remote, opts)
        s.run()
        stats = s.get_stats()
        #        pprint(stats)

        self.assertEqual(stats["entries_seen"], 8)
        self.assertEqual(stats["entries_touched"], 8)
        #        self.assertEqual(stats["files_created"], 6)
        self.assertEqual(stats["files_deleted"], 0)
        self.assertEqual(stats["files_written"], 6)
        self.assertEqual(stats["dirs_created"], 2)
        self.assertEqual(stats["download_files_written"], 6)
        self.assertEqual(stats["upload_files_written"], 0)
        self.assertEqual(stats["conflict_files"], 0)
        self.assertEqual(stats["bytes_written"], 16403)

        # Original file times are preserved, even when retrieved from FTP

        self.assertNotEqual(get_test_file_date("local/file1.txt"),
                            STAMP_20140101_120000)
        self.assertEqual(
            get_test_file_date("local/file1.txt"),
            get_test_file_date("local//file1.txt"),
        )

        self.assertEqual(get_test_file_date("local/file2.txt"),
                         STAMP_20140101_120000)
        self.assertEqual(get_test_file_date("remote//file2.txt"),
                         STAMP_20140101_120000)

        # Synchronize temp/local <=> remote : nothing to do

        local = FsTarget(os.path.join(PYFTPSYNC_TEST_FOLDER, "local"))

        opts = {"verbose": 3}
        s = BiDirSynchronizer(local, remote, opts)
        s.run()
        stats = s.get_stats()
        pprint(stats)
        self.assertEqual(stats["entries_touched"], 0)
        self.assertEqual(stats["conflict_files"], 0)
        self.assertEqual(stats["bytes_written"], 0)

        # Synchronize temp/remote <=> remote : nothing to do

        local = FsTarget(os.path.join(PYFTPSYNC_TEST_FOLDER, "remote"))

        opts = {"verbose": 3}
        s = BiDirSynchronizer(local, remote, opts)
        s.run()
        stats = s.get_stats()
        pprint(stats)
        self.assertEqual(stats["entries_touched"], 0)
        self.assertEqual(stats["conflict_files"], 0)
        self.assertEqual(stats["bytes_written"], 0)
Пример #13
0
def run():
    """CLI main entry point."""

    # Use print() instead of logging when running in CLI mode:
    set_pyftpsync_logger(None)

    parser = argparse.ArgumentParser(
        description="Synchronize folders over FTP.",
        epilog="See also https://github.com/mar10/pyftpsync",
        parents=[verbose_parser],
    )

    # Note: we want to allow --version to be combined with --verbose. However
    # on Py2, argparse makes sub-commands mandatory, unless `action="version"` is used.
    if check_cli_verbose(3) > 3:
        version_info = "pyftpsync/{} Python/{} {}".format(
            __version__, PYTHON_VERSION, platform.platform()
        )
    else:
        version_info = "{}".format(__version__)

    parser.add_argument("-V", "--version", action="version", version=version_info)

    subparsers = parser.add_subparsers(help="sub-command help")

    # --- Create the parser for the "upload" command ---------------------------

    sp = subparsers.add_parser(
        "upload",
        parents=[verbose_parser, common_parser, matcher_parser, creds_parser],
        help="copy new and modified files to remote folder",
    )

    sp.add_argument(
        "local",
        metavar="LOCAL",
        default=".",
        help="path to local folder (default: %(default)s)",
    )
    sp.add_argument("remote", metavar="REMOTE", help="path to remote folder")
    sp.add_argument(
        "--force",
        action="store_true",
        help="overwrite remote files, even if the target is newer "
        "(but no conflict was detected)",
    )
    sp.add_argument(
        "--resolve",
        default="ask",
        choices=["local", "skip", "ask"],
        help="conflict resolving strategy (default: '%(default)s')",
    )
    sp.add_argument(
        "--delete",
        action="store_true",
        help="remove remote files if they don't exist locally",
    )
    sp.add_argument(
        "--delete-unmatched",
        action="store_true",
        help="remove remote files if they don't exist locally "
        "or don't match the current filter (implies '--delete' option)",
    )

    sp.set_defaults(command="upload")

    # --- Create the parser for the "download" command -------------------------

    sp = subparsers.add_parser(
        "download",
        parents=[verbose_parser, common_parser, matcher_parser, creds_parser],
        help="copy new and modified files from remote folder to local target",
    )

    sp.add_argument(
        "local",
        metavar="LOCAL",
        default=".",
        help="path to local folder (default: %(default)s)",
    )
    sp.add_argument("remote", metavar="REMOTE", help="path to remote folder")
    sp.add_argument(
        "--force",
        action="store_true",
        help="overwrite local files, even if the target is newer "
        "(but no conflict was detected)",
    )
    sp.add_argument(
        "--resolve",
        default="ask",
        choices=["remote", "skip", "ask"],
        help="conflict resolving strategy (default: '%(default)s')",
    )
    sp.add_argument(
        "--delete",
        action="store_true",
        help="remove local files if they don't exist on remote target",
    )
    sp.add_argument(
        "--delete-unmatched",
        action="store_true",
        help="remove local files if they don't exist on remote target "
        "or don't match the current filter (implies '--delete' option)",
    )

    sp.set_defaults(command="download")

    # --- Create the parser for the "sync" command -----------------------------

    sp = subparsers.add_parser(
        "sync",
        parents=[verbose_parser, common_parser, matcher_parser, creds_parser],
        help="synchronize new and modified files between remote folder and local target",
    )

    sp.add_argument(
        "local",
        metavar="LOCAL",
        default=".",
        help="path to local folder (default: %(default)s)",
    )
    sp.add_argument("remote", metavar="REMOTE", help="path to remote folder")
    sp.add_argument(
        "--resolve",
        default="ask",
        choices=["old", "new", "local", "remote", "skip", "ask"],
        help="conflict resolving strategy (default: '%(default)s')",
    )

    sp.set_defaults(command="sync")

    # --- Create the parser for the "run" command -----------------------------

    add_run_parser(subparsers)

    # --- Create the parser for the "scan" command -----------------------------

    add_scan_parser(subparsers)

    # --- Create the parser for the "tree" command -----------------------------

    add_tree_parser(subparsers)

    # --- Parse command line ---------------------------------------------------

    args = parser.parse_args()

    args.verbose -= args.quiet
    del args.quiet

    # print("verbose", args.verbose)

    ftp_debug = 0
    if args.verbose >= 6:
        ftp_debug = 1

    if args.debug:
        if args.verbose < 4:
            parser.error("'--debug' requires verbose level >= 4")
        DEBUG_FLAGS.update(args.debug)

    # Modify the `args` from the `pyftpsync.yaml` config:
    if getattr(args, "command", None) == "run":
        handle_run_command(parser, args)

    if callable(getattr(args, "command", None)):
        # scan_handler
        try:
            return args.command(parser, args)
        except KeyboardInterrupt:
            print("\nAborted by user.", file=sys.stderr)
            sys.exit(3)

    elif not hasattr(args, "command"):
        parser.error(
            "missing command (choose from 'upload', 'download', 'run', 'sync', 'scan')"
        )

    # Post-process and check arguments
    if hasattr(args, "delete_unmatched") and args.delete_unmatched:
        args.delete = True

    args.local_target = make_target(args.local, {"ftp_debug": ftp_debug})

    if args.remote == ".":
        parser.error("'.' is expected to be the local target (not remote)")
    args.remote_target = make_target(args.remote, {"ftp_debug": ftp_debug})
    if not isinstance(args.local_target, FsTarget) and isinstance(
        args.remote_target, FsTarget
    ):
        parser.error("a file system target is expected to be local")

    # Let the command handler do its thing
    opts = namespace_to_dict(args)
    if args.command == "upload":
        s = UploadSynchronizer(args.local_target, args.remote_target, opts)
    elif args.command == "download":
        s = DownloadSynchronizer(args.local_target, args.remote_target, opts)
    elif args.command == "sync":
        s = BiDirSynchronizer(args.local_target, args.remote_target, opts)
    else:
        parser.error("unknown command '{}'".format(args.command))

    s.is_script = True

    try:
        s.run()
    except KeyboardInterrupt:
        print("\nAborted by user.", file=sys.stderr)
        sys.exit(3)
    finally:
        # Prevent sporadic exceptions in ftplib, when closing in __del__
        s.local.close()
        s.remote.close()

    stats = s.get_stats()
    if args.verbose >= 5:
        pprint(stats)
    elif args.verbose >= 1:
        if args.dry_run:
            print("(DRY-RUN) ", end="")
        print(
            "Wrote {}/{} files in {} directories, skipped: {}.".format(
                stats["files_written"],
                stats["local_files"],
                stats["local_dirs"],
                stats["conflict_files_skipped"],
            ),
            end="",
        )
        if stats["interactive_ask"]:
            print()
        else:
            print(" Elap: {}.".format(stats["elap_str"]))

    return
Пример #14
0
def run():
    """CLI main entry point."""

    # Use print() instead of logging when running in CLI mode:
    set_pyftpsync_logger(None)

    parser = argparse.ArgumentParser(
        description="Synchronize folders over FTP.",
        epilog="See also https://github.com/mar10/pyftpsync")

    parser.add_argument("-V",
                        "--version",
                        action="version",
                        version="{}".format(__version__))

    subparsers = parser.add_subparsers(help="sub-command help")

    # --- Create the parser for the "upload" command ---------------------------

    sp = subparsers.add_parser(
        "upload", help="copy new and modified files to remote folder")

    sp.add_argument("--force",
                    action="store_true",
                    help="overwrite remote files, even if the target is newer "
                    "(but no conflict was detected)")
    sp.add_argument(
        "--resolve",
        default="ask",
        choices=["local", "skip", "ask"],
        help="conflict resolving strategy (default: '%(default)s')")
    sp.add_argument("--delete",
                    action="store_true",
                    help="remove remote files if they don't exist locally")
    sp.add_argument(
        "--delete-unmatched",
        action="store_true",
        help="remove remote files if they don't exist locally "
        "or don't match the current filter (implies '--delete' option)")

    add_common_sub_args(sp)
    sp.set_defaults(command="upload")

    # --- Create the parser for the "download" command -------------------------

    sp = subparsers.add_parser(
        "download",
        help="copy new and modified files from remote folder to local target")

    sp.add_argument("--force",
                    action="store_true",
                    help="overwrite local files, even if the target is newer "
                    "(but no conflict was detected)")
    sp.add_argument(
        "--resolve",
        default="ask",
        choices=["remote", "skip", "ask"],
        help="conflict resolving strategy (default: '%(default)s')")
    sp.add_argument(
        "--delete",
        action="store_true",
        help="remove local files if they don't exist on remote target")
    sp.add_argument(
        "--delete-unmatched",
        action="store_true",
        help="remove local files if they don't exist on remote target "
        "or don't match the current filter (implies '--delete' option)")

    add_common_sub_args(sp)
    sp.set_defaults(command="download")

    # --- Create the parser for the "sync" command -----------------------------

    sp = subparsers.add_parser(
        "sync",
        help=
        "synchronize new and modified files between remote folder and local target"
    )

    sp.add_argument(
        "--resolve",
        default="ask",
        choices=["old", "new", "local", "remote", "skip", "ask"],
        help="conflict resolving strategy (default: '%(default)s')")

    add_common_sub_args(sp)
    sp.set_defaults(command="synchronize")

    # --- Create the parser for the "scan" command -----------------------------

    add_scan_parser(subparsers)

    # --- Parse command line ---------------------------------------------------

    args = parser.parse_args()

    args.verbose -= args.quiet
    del args.quiet

    ftp_debug = 0
    if args.verbose >= 6:
        ftp_debug = 1

    if callable(getattr(args, "command", None)):
        try:
            return getattr(args, "command")(args)
        except KeyboardInterrupt:
            print("\nAborted by user.", file=sys.stderr)
            sys.exit(3)

    elif not hasattr(args, "command"):
        parser.error(
            "missing command (choose from 'upload', 'download', 'sync', 'scan')"
        )

    # Post-process and check arguments
    if hasattr(args, "delete_unmatched") and args.delete_unmatched:
        args.delete = True

    args.local_target = make_target(args.local, {"ftp_debug": ftp_debug})

    if args.remote == ".":
        parser.error("'.' is expected to be the local target (not remote)")
    args.remote_target = make_target(args.remote, {"ftp_debug": ftp_debug})
    if not isinstance(args.local_target, FsTarget) and isinstance(
            args.remote_target, FsTarget):
        parser.error("a file system target is expected to be local")

    # Let the command handler do its thing
    opts = namespace_to_dict(args)
    if args.command == "upload":
        s = UploadSynchronizer(args.local_target, args.remote_target, opts)
    elif args.command == "download":
        s = DownloadSynchronizer(args.local_target, args.remote_target, opts)
    elif args.command == "synchronize":
        s = BiDirSynchronizer(args.local_target, args.remote_target, opts)
    else:
        parser.error("unknown command {}".format(args.command))

    s.is_script = True

    try:
        s.run()
    except KeyboardInterrupt:
        print("\nAborted by user.", file=sys.stderr)
        sys.exit(3)
    finally:
        # Prevent sporadic exceptions in ftplib, when closing in __del__
        s.local.close()
        s.remote.close()

    stats = s.get_stats()
    if args.verbose >= 5:
        pprint(stats)
    elif args.verbose >= 1:
        if args.dry_run:
            print("(DRY-RUN) ", end="")
        print("Wrote {}/{} files in {} directories, skipped: {}.".format(
            stats["files_written"], stats["local_files"], stats["local_dirs"],
            stats["conflict_files_skipped"]),
              end="")
        if stats["interactive_ask"]:
            print()
        else:
            print(" Elap: {}.".format(stats["elap_str"]))

    return
Пример #15
0
# #загружаем недостающие файлы на ftp
# for local_file in local_files - remote_files:
#     server.storbinary('STOR ' + local_file, open(local_file, 'rb'))
#
# #закрываем соединение с сервером
# server.close()

from ftpsync.targets import FsTarget
from ftpsync.ftp_target import FtpTarget
from ftpsync.synchronizers import BiDirSynchronizer

local = FsTarget("/home/garbage/backup/")
user ="******"
passwd = "buuserpwd"
remote = FtpTarget("1C8", "192.168.0.26", user, passwd, tls=True)
opts = {"resolve": "skip", "verbose": 1, "dry_run" : False}
s = BiDirSynchronizer(local, remote, opts)
s.run()












Пример #16
0
def run():
    parser = argparse.ArgumentParser(
        description="Synchronize folders over FTP.",
        epilog="See also https://github.com/mar10/pyftpsync")

    qv_group = parser.add_mutually_exclusive_group()
    qv_group.add_argument(
        "--verbose",
        "-v",
        action="count",
        default=3,
        help="increment verbosity by one (default: %(default)s, range: 0..5)")
    qv_group.add_argument("--quiet",
                          "-q",
                          action="count",
                          default=0,
                          help="decrement verbosity by one")

    parser.add_argument("-V",
                        "--version",
                        action="version",
                        version="%s" % __version__)
    parser.add_argument(
        "--progress",
        "-p",
        action="store_true",
        default=False,
        help="show progress info, even if redirected or verbose < 3")

    subparsers = parser.add_subparsers(help="sub-command help")

    def __add_common_sub_args(parser):
        parser.add_argument(
            "local",
            metavar="LOCAL",
            #                             required=True,
            default=".",
            help="path to local folder (default: %(default)s)")
        parser.add_argument("remote",
                            metavar="REMOTE",
                            help="path to remote folder")
        parser.add_argument(
            "--dry-run",
            action="store_true",
            help="just simulate and log results, but don't change anything")
        # parser.add_argument("-x", "--execute",
        #                     action="store_false", dest="dry_run", default=True,
        #                     help="turn off the dry-run mode (which is ON by default), "
        #                     "that would just print status messages but does "
        #                     "not change anything")
        parser.add_argument("-f",
                            "--include-files",
                            help="wildcard for file names (default: all, "
                            "separate multiple values with ',')")
        parser.add_argument(
            "-o",
            "--omit",
            help=
            "wildcard of files and directories to exclude (applied after --include)"
        )
        parser.add_argument("--store-password",
                            action="store_true",
                            help="save password to keyring if login succeeds")
        parser.add_argument("--no-prompt",
                            action="store_true",
                            help="prevent prompting for missing credentials")
        parser.add_argument("--no-color",
                            action="store_true",
                            help="prevent use of ansi terminal color codes")

    # --- Create the parser for the "upload" command ---------------------------

    upload_parser = subparsers.add_parser(
        "upload", help="copy new and modified files to remote folder")
    __add_common_sub_args(upload_parser)

    upload_parser.add_argument(
        "--force",
        action="store_true",
        help=
        "overwrite remote files, even if the target is newer (but no conflict was detected)"
    )
    upload_parser.add_argument(
        "--resolve",
        default="skip",
        choices=["local", "skip", "ask"],
        help="conflict resolving strategy (default: '%(default)s')")
    upload_parser.add_argument(
        "--delete",
        action="store_true",
        help="remove remote files if they don't exist locally")
    upload_parser.add_argument(
        "--delete-unmatched",
        action="store_true",
        help="remove remote files if they don't exist locally "
        "or don't match the current filter (implies '--delete' option)")

    upload_parser.set_defaults(command="upload")

    # --- Create the parser for the "download" command -------------------------

    download_parser = subparsers.add_parser(
        "download",
        help="copy new and modified files from remote folder to local target")
    __add_common_sub_args(download_parser)

    download_parser.add_argument(
        "--force",
        action="store_true",
        help=
        "overwrite local files, even if the target is newer (but no conflict was detected)"
    )
    download_parser.add_argument(
        "--resolve",
        default="skip",
        choices=["remote", "skip", "ask"],
        help="conflict resolving strategy (default: '%(default)s')")
    download_parser.add_argument(
        "--delete",
        action="store_true",
        help="remove local files if they don't exist on remote target")
    download_parser.add_argument(
        "--delete-unmatched",
        action="store_true",
        help="remove local files if they don't exist on remote target "
        "or don't match the current filter (implies '--delete' option)")

    download_parser.set_defaults(command="download")

    # --- Create the parser for the "sync" command -----------------------------

    sync_parser = subparsers.add_parser(
        "sync",
        help=
        "synchronize new and modified files between remote folder and local target"
    )
    __add_common_sub_args(sync_parser)

    sync_parser.add_argument(
        "--resolve",
        default="ask",
        choices=["old", "new", "local", "remote", "skip", "ask"],
        help="conflict resolving strategy (default: '%(default)s')")

    sync_parser.set_defaults(command="synchronize")

    # --- Create the parser for the "scan" command -----------------------------

    scan_parser = add_scan_parser(subparsers)

    # --- Parse command line ---------------------------------------------------

    args = parser.parse_args()

    args.verbose -= args.quiet
    del args.quiet

    ftp_debug = 0
    if args.verbose >= 5:
        ftp_debug = 1

    if callable(getattr(args, "command", None)):
        return getattr(args, "command")(args)
    elif not hasattr(args, "command"):
        parser.error(
            "missing command (choose from 'upload', 'download', 'sync')")

    # Post-process and check arguments
    if hasattr(args, "delete_unmatched") and args.delete_unmatched:
        args.delete = True

    args.local_target = make_target(args.local, {"ftp_debug": ftp_debug})

    if args.remote == ".":
        parser.error("'.' is expected to be the local target (not remote)")
    args.remote_target = make_target(args.remote, {"ftp_debug": ftp_debug})
    if not isinstance(args.local_target, FsTarget) and isinstance(
            args.remote_target, FsTarget):
        parser.error("a file system target is expected to be local")

    # Let the command handler do its thing
    opts = namespace_to_dict(args)
    if args.command == "upload":
        s = UploadSynchronizer(args.local_target, args.remote_target, opts)
    elif args.command == "download":
        s = DownloadSynchronizer(args.local_target, args.remote_target, opts)
    elif args.command == "synchronize":
        s = BiDirSynchronizer(args.local_target, args.remote_target, opts)
    else:
        parser.error("unknown command %s" % args.command)

    try:
        s.run()
    except KeyboardInterrupt:
        print("\nAborted by user.")
        return
    finally:
        # prevent sporadic exceptions in ftplib, when closing in __del__
        s.local.close()
        s.remote.close()

    stats = s.get_stats()
    if args.verbose >= 4:
        pprint(stats)
    elif args.verbose >= 1:
        if args.dry_run:
            print("(DRY-RUN) ", end="")
        print("Wrote %s/%s files in %s dirs. Elap: %s" %
              (stats["files_written"], stats["local_files"],
               stats["local_dirs"], stats["elap_str"]))

    return