src/Pure/General/rsync.scala
author nipkow
Wed, 13 Nov 2024 23:11:06 +0100
changeset 81442 6097eaaee6ee
parent 80234 cce5670be9f9
permissions -rw-r--r--
merged

/*  Title:      Pure/General/rsync.scala
    Author:     Makarius

Support for rsync, based on Isabelle component.
*/

package isabelle


object Rsync {
  object Context {
    def apply(
      progress: Progress = new Progress,
      ssh: SSH.System = SSH.Local,
      chmod: String = "",
      chown: String = "",
      archive: Boolean = true,
      stats: Boolean = true
    ): Context = {
      val directory = Components.provide(Component_Rsync.home, ssh = ssh, progress = progress)
      new Context(directory, progress, chmod, chown, archive, stats)
    }
  }

  final class Context private(
    directory: Components.Directory,
    val progress: Progress,
    chmod: String,
    chown: String,
    archive: Boolean,
    stats: Boolean
  ) {
    override def toString: String = directory.toString

    def ssh: SSH.System = directory.ssh

    def command: String = {
      val program = Component_Rsync.remote_program(directory)
      val ssh_command = ssh.client_command
      File.bash_path(Component_Rsync.local_program) + " --secluded-args" +
        if_proper(ssh_command, " --rsh=" + Bash.string(ssh_command)) +
        " --rsync-path=" + Bash.string(quote(File.standard_path(program))) +
        if_proper(chmod, " --chmod=" + Bash.string(chmod)) +
        if_proper(chown, " --chown=" + Bash.string(chown)) +
        if_proper(archive, " --archive") +
        if_proper(stats, " --stats")
    }

    def target(path: Path, direct: Boolean = false): String =
      Url.dir_path(ssh.rsync_path(path), direct = direct)
  }

  def exec(
    context: Context,
    thorough: Boolean = false,
    prune_empty_dirs: Boolean = false,
    dry_run: Boolean = false,
    clean: Boolean = false,
    filter: List[String] = Nil,
    args: List[String] = Nil
  ): Process_Result = {
    val progress = context.progress
    val script =
      context.command +
        if_proper(progress.verbose, " --verbose") +
        (if (thorough) " --ignore-times" else " --omit-dir-times") +
        if_proper(prune_empty_dirs, " --prune-empty-dirs") +
        if_proper(dry_run, " --dry-run") +
        if_proper(clean, " --delete-excluded") +
        filter.map(s => " --filter=" + Bash.string(s)).mkString +
        if_proper(args, " " + Bash.strings(args))
    progress.bash(script, echo = true)
  }
}