src/Pure/Tools/sync.scala
author wenzelm
Sat, 08 Apr 2023 19:32:09 +0200
changeset 77792 b81b2c50fc7c
parent 77787 b20ac2c26ea3
child 77795 4c4bd44ff683
permissions -rw-r--r--
use "rsync --secluded-args" by default, discontinue obsolete option -P of sync tools;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
75555
197a5b3a1ea2 promote "isabelle sync" to regular user-space tool, with proper documentation;
wenzelm
parents: 75553
diff changeset
     1
/*  Title:      Pure/Tools/sync.scala
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
     2
    Author:     Makarius
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
     3
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
     4
Synchronize Isabelle + AFP repositories.
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
     5
*/
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
     6
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
     7
package isabelle
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
     8
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
     9
75549
4b21e823d35f clarified names;
wenzelm
parents: 75536
diff changeset
    10
object Sync {
75552
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    11
  /* session images */
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    12
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    13
  def find_images(options: Options, session_images: List[String],
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    14
    dirs: List[Path] = Nil
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    15
  ): List[String] = {
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    16
    if (session_images.isEmpty) Nil
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    17
    else {
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    18
      val store = Sessions.store(options)
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    19
      val sessions_structure = Sessions.load_structure(options, dirs = dirs)
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    20
      sessions_structure.build_requirements(session_images).flatMap { session =>
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    21
        val heap =
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    22
          store.find_heap(session).map(_.expand).map(path =>
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    23
            File.standard_path(path.dir.dir) + "/./" + path.dir.file_name + "/" + path.file_name)
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    24
        val db =
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    25
          store.find_database(session).map(_.expand).map(path =>
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    26
            File.standard_path(path.dir.dir.dir) + "/./" + path.dir.dir.file_name + "/" +
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    27
              path.dir.file_name + "/" + path.file_name)
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    28
        heap.toList ::: db.toList
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    29
      }
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    30
    }
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    31
  }
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    32
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    33
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    34
  /* sync */
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    35
77783
fb61887c069a clarified underlying SSH session of "isabelle hg_sync" and "isabelle sync";
wenzelm
parents: 77518
diff changeset
    36
  def sync(options: Options, context: Rsync.Context, target: Path,
75487
167660a8f99e support thorough check of file content;
wenzelm
parents: 75486
diff changeset
    37
    thorough: Boolean = false,
75553
4dd0f250ec0d more options;
wenzelm
parents: 75552
diff changeset
    38
    purge_heaps: Boolean = false,
75552
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    39
    session_images: List[String] = Nil,
75492
c03c2bf4ef8a preserve jars for quick testing;
wenzelm
parents: 75491
diff changeset
    40
    preserve_jars: Boolean = false,
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    41
    dry_run: Boolean = false,
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    42
    rev: String = "",
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    43
    afp_root: Option[Path] = None,
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    44
    afp_rev: String = ""
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    45
  ): Unit = {
77517
wenzelm
parents: 76617
diff changeset
    46
    val progress = context.progress
wenzelm
parents: 76617
diff changeset
    47
75506
ee51db628e71 clarified signature;
wenzelm
parents: 75499
diff changeset
    48
    val hg = Mercurial.self_repository()
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    49
    val afp_hg = afp_root.map(Mercurial.repository(_))
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    50
75492
c03c2bf4ef8a preserve jars for quick testing;
wenzelm
parents: 75491
diff changeset
    51
    val more_filter = if (preserve_jars) List("include *.jar", "protect *.jar") else Nil
c03c2bf4ef8a preserve jars for quick testing;
wenzelm
parents: 75491
diff changeset
    52
77784
wenzelm
parents: 77783
diff changeset
    53
    def hg_sync(hg: Mercurial.Repository, dest: Path, r: String,
75511
b32fdb67f851 provide .hg_sync meta data;
wenzelm
parents: 75509
diff changeset
    54
      contents: List[File.Content] = Nil, filter: List[String] = Nil
b32fdb67f851 provide .hg_sync meta data;
wenzelm
parents: 75509
diff changeset
    55
    ): Unit = {
77518
fda4da0f80f4 clarified signature: manage "verbose" flag via "progress";
wenzelm
parents: 77517
diff changeset
    56
      hg.sync(context, dest, rev = r, thorough = thorough, dry_run = dry_run,
75525
68162e4f60a7 clarified signature: more explicit type Rsync.Context;
wenzelm
parents: 75524
diff changeset
    57
        contents = contents, filter = filter ::: more_filter)
75511
b32fdb67f851 provide .hg_sync meta data;
wenzelm
parents: 75509
diff changeset
    58
    }
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    59
77518
fda4da0f80f4 clarified signature: manage "verbose" flag via "progress";
wenzelm
parents: 77517
diff changeset
    60
    progress.echo("\n* Isabelle repository:", verbose = true)
75553
4dd0f250ec0d more options;
wenzelm
parents: 75552
diff changeset
    61
    val filter_heaps = if (purge_heaps) Nil else List("protect /heaps", "protect /heaps/**")
77784
wenzelm
parents: 77783
diff changeset
    62
    hg_sync(hg, target, rev,
75824
a2b2e8964e1a tuned signature;
wenzelm
parents: 75555
diff changeset
    63
      contents = List(File.content(Path.explode("etc/ISABELLE_ID"), hg.id(rev = rev))),
75553
4dd0f250ec0d more options;
wenzelm
parents: 75552
diff changeset
    64
      filter = filter_heaps ::: List("protect /AFP"))
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    65
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    66
    for (hg <- afp_hg) {
77518
fda4da0f80f4 clarified signature: manage "verbose" flag via "progress";
wenzelm
parents: 77517
diff changeset
    67
      progress.echo("\n* AFP repository:", verbose = true)
77784
wenzelm
parents: 77783
diff changeset
    68
      hg_sync(hg, target + Path.explode("AFP"), afp_rev)
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    69
    }
75552
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    70
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    71
    val images =
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    72
      find_images(options, session_images,
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    73
        dirs = afp_root.map(_ + Path.explode("thys")).toList)
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    74
    if (images.nonEmpty) {
77518
fda4da0f80f4 clarified signature: manage "verbose" flag via "progress";
wenzelm
parents: 77517
diff changeset
    75
      progress.echo("\n* Session images:", verbose = true)
77783
fb61887c069a clarified underlying SSH session of "isabelle hg_sync" and "isabelle sync";
wenzelm
parents: 77518
diff changeset
    76
      val heaps = context.target(target + Path.explode("heaps")) + "/"
77518
fda4da0f80f4 clarified signature: manage "verbose" flag via "progress";
wenzelm
parents: 77517
diff changeset
    77
      Rsync.exec(context, thorough = thorough, dry_run = dry_run,
76617
d5adc9126ae8 clarified signature;
wenzelm
parents: 76136
diff changeset
    78
        args = List("--relative", "--") ::: images ::: List(heaps)).check
75552
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    79
    }
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    80
  }
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    81
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    82
  val isabelle_tool =
75549
4b21e823d35f clarified names;
wenzelm
parents: 75536
diff changeset
    83
    Isabelle_Tool("sync", "synchronize Isabelle + AFP repositories",
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    84
      Scala_Project.here, { args =>
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    85
        var afp_root: Option[Path] = None
75553
4dd0f250ec0d more options;
wenzelm
parents: 75552
diff changeset
    86
        var purge_heaps = false
75552
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    87
        var session_images = List.empty[String]
75492
c03c2bf4ef8a preserve jars for quick testing;
wenzelm
parents: 75491
diff changeset
    88
        var preserve_jars = false
75487
167660a8f99e support thorough check of file content;
wenzelm
parents: 75486
diff changeset
    89
        var thorough = false
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    90
        var afp_rev = ""
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    91
        var dry_run = false
76136
1bb677cceea4 let rsync re-use ssh connection via control path;
wenzelm
parents: 76134
diff changeset
    92
        var ssh_port = 0
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    93
        var rev = ""
77783
fb61887c069a clarified underlying SSH session of "isabelle hg_sync" and "isabelle sync";
wenzelm
parents: 77518
diff changeset
    94
        var ssh_host = ""
fb61887c069a clarified underlying SSH session of "isabelle hg_sync" and "isabelle sync";
wenzelm
parents: 77518
diff changeset
    95
        var ssh_user = ""
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    96
        var verbose = false
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    97
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    98
        val getopts = Getopts("""
75549
4b21e823d35f clarified names;
wenzelm
parents: 75536
diff changeset
    99
Usage: isabelle sync [OPTIONS] TARGET
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   100
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   101
  Options are:
75497
0a5f7b5da16f clarified options;
wenzelm
parents: 75493
diff changeset
   102
    -A ROOT      include AFP with given root directory (":" for """ + AFP.BASE.implode + """)
75553
4dd0f250ec0d more options;
wenzelm
parents: 75552
diff changeset
   103
    -H           purge heaps directory on target
75552
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
   104
    -I NAME      include session heap image and build database
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
   105
                 (based on accidental local state)
75492
c03c2bf4ef8a preserve jars for quick testing;
wenzelm
parents: 75491
diff changeset
   106
    -J           preserve *.jar files
75493
f775dfb55655 clarified option -T;
wenzelm
parents: 75492
diff changeset
   107
    -T           thorough treatment of file content and directory times
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   108
    -a REV       explicit AFP revision (default: state of working directory)
77783
fb61887c069a clarified underlying SSH session of "isabelle hg_sync" and "isabelle sync";
wenzelm
parents: 77518
diff changeset
   109
    -s HOST      SSH host name for remote target (default: local)
fb61887c069a clarified underlying SSH session of "isabelle hg_sync" and "isabelle sync";
wenzelm
parents: 77518
diff changeset
   110
    -u USER      explicit SSH user name
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   111
    -n           no changes: dry-run
77783
fb61887c069a clarified underlying SSH session of "isabelle hg_sync" and "isabelle sync";
wenzelm
parents: 77518
diff changeset
   112
    -p PORT      explicit SSH port
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   113
    -r REV       explicit revision (default: state of working directory)
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   114
    -v           verbose
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   115
75555
197a5b3a1ea2 promote "isabelle sync" to regular user-space tool, with proper documentation;
wenzelm
parents: 75553
diff changeset
   116
  Synchronize Isabelle + AFP repositories, based on "isabelle hg_sync".
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   117
""",
75497
0a5f7b5da16f clarified options;
wenzelm
parents: 75493
diff changeset
   118
          "A:" -> (arg => afp_root = Some(if (arg == ":") AFP.BASE else Path.explode(arg))),
75553
4dd0f250ec0d more options;
wenzelm
parents: 75552
diff changeset
   119
          "H" -> (_ => purge_heaps = true),
75552
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
   120
          "I:" -> (arg => session_images = session_images ::: List(arg)),
75492
c03c2bf4ef8a preserve jars for quick testing;
wenzelm
parents: 75491
diff changeset
   121
          "J" -> (_ => preserve_jars = true),
75487
167660a8f99e support thorough check of file content;
wenzelm
parents: 75486
diff changeset
   122
          "T" -> (_ => thorough = true),
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   123
          "a:" -> (arg => afp_rev = arg),
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   124
          "n" -> (_ => dry_run = true),
76136
1bb677cceea4 let rsync re-use ssh connection via control path;
wenzelm
parents: 76134
diff changeset
   125
          "p:" -> (arg => ssh_port = Value.Int.parse(arg)),
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   126
          "r:" -> (arg => rev = arg),
77783
fb61887c069a clarified underlying SSH session of "isabelle hg_sync" and "isabelle sync";
wenzelm
parents: 77518
diff changeset
   127
          "s:" -> (arg => ssh_host = arg),
fb61887c069a clarified underlying SSH session of "isabelle hg_sync" and "isabelle sync";
wenzelm
parents: 77518
diff changeset
   128
          "u:" -> (arg => ssh_user = arg),
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   129
          "v" -> (_ => verbose = true))
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   130
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   131
        val more_args = getopts(args)
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   132
        val target =
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   133
          more_args match {
77783
fb61887c069a clarified underlying SSH session of "isabelle hg_sync" and "isabelle sync";
wenzelm
parents: 77518
diff changeset
   134
            case List(target) => Path.explode(target)
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   135
            case _ => getopts.usage()
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   136
          }
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   137
75552
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
   138
        val options = Options.init()
77518
fda4da0f80f4 clarified signature: manage "verbose" flag via "progress";
wenzelm
parents: 77517
diff changeset
   139
        val progress = new Console_Progress(verbose = verbose)
77783
fb61887c069a clarified underlying SSH session of "isabelle hg_sync" and "isabelle sync";
wenzelm
parents: 77518
diff changeset
   140
fb61887c069a clarified underlying SSH session of "isabelle hg_sync" and "isabelle sync";
wenzelm
parents: 77518
diff changeset
   141
        using(SSH.open_system(options, host = ssh_host, port = ssh_port, user = ssh_user)) { ssh =>
77792
b81b2c50fc7c use "rsync --secluded-args" by default, discontinue obsolete option -P of sync tools;
wenzelm
parents: 77787
diff changeset
   142
          val context = Rsync.Context(progress = progress, ssh = ssh)
77783
fb61887c069a clarified underlying SSH session of "isabelle hg_sync" and "isabelle sync";
wenzelm
parents: 77518
diff changeset
   143
          sync(options, context, target, thorough = thorough, purge_heaps = purge_heaps,
fb61887c069a clarified underlying SSH session of "isabelle hg_sync" and "isabelle sync";
wenzelm
parents: 77518
diff changeset
   144
            session_images = session_images, preserve_jars = preserve_jars, dry_run = dry_run,
fb61887c069a clarified underlying SSH session of "isabelle hg_sync" and "isabelle sync";
wenzelm
parents: 77518
diff changeset
   145
            rev = rev, afp_root = afp_root, afp_rev = afp_rev)
fb61887c069a clarified underlying SSH session of "isabelle hg_sync" and "isabelle sync";
wenzelm
parents: 77518
diff changeset
   146
        }
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   147
      }
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   148
    )
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   149
}