src/Pure/Tools/sync.scala
author wenzelm
Fri, 12 Aug 2022 16:01:52 +0200
changeset 75824 a2b2e8964e1a
parent 75555 197a5b3a1ea2
child 76131 8b695e59db3f
permissions -rw-r--r--
tuned signature;
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
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    36
  def sync(options: Options, context: Rsync.Context, target: String,
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    37
    verbose: Boolean = false,
75487
167660a8f99e support thorough check of file content;
wenzelm
parents: 75486
diff changeset
    38
    thorough: Boolean = false,
75553
4dd0f250ec0d more options;
wenzelm
parents: 75552
diff changeset
    39
    purge_heaps: Boolean = false,
75552
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    40
    session_images: List[String] = Nil,
75492
c03c2bf4ef8a preserve jars for quick testing;
wenzelm
parents: 75491
diff changeset
    41
    preserve_jars: Boolean = false,
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    42
    dry_run: Boolean = false,
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    43
    rev: String = "",
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    44
    afp_root: Option[Path] = None,
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    45
    afp_rev: String = ""
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    46
  ): Unit = {
75506
ee51db628e71 clarified signature;
wenzelm
parents: 75499
diff changeset
    47
    val hg = Mercurial.self_repository()
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    48
    val afp_hg = afp_root.map(Mercurial.repository(_))
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    49
75492
c03c2bf4ef8a preserve jars for quick testing;
wenzelm
parents: 75491
diff changeset
    50
    val more_filter = if (preserve_jars) List("include *.jar", "protect *.jar") else Nil
c03c2bf4ef8a preserve jars for quick testing;
wenzelm
parents: 75491
diff changeset
    51
75511
b32fdb67f851 provide .hg_sync meta data;
wenzelm
parents: 75509
diff changeset
    52
    def sync(hg: Mercurial.Repository, dest: String, r: String,
b32fdb67f851 provide .hg_sync meta data;
wenzelm
parents: 75509
diff changeset
    53
      contents: List[File.Content] = Nil, filter: List[String] = Nil
b32fdb67f851 provide .hg_sync meta data;
wenzelm
parents: 75509
diff changeset
    54
    ): Unit = {
75525
68162e4f60a7 clarified signature: more explicit type Rsync.Context;
wenzelm
parents: 75524
diff changeset
    55
      hg.sync(context, dest, rev = r, verbose = verbose, thorough = thorough, dry_run = dry_run,
68162e4f60a7 clarified signature: more explicit type Rsync.Context;
wenzelm
parents: 75524
diff changeset
    56
        contents = contents, filter = filter ::: more_filter)
75511
b32fdb67f851 provide .hg_sync meta data;
wenzelm
parents: 75509
diff changeset
    57
    }
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    58
75525
68162e4f60a7 clarified signature: more explicit type Rsync.Context;
wenzelm
parents: 75524
diff changeset
    59
    context.progress.echo_if(verbose, "\n* Isabelle repository:")
75553
4dd0f250ec0d more options;
wenzelm
parents: 75552
diff changeset
    60
    val filter_heaps = if (purge_heaps) Nil else List("protect /heaps", "protect /heaps/**")
75511
b32fdb67f851 provide .hg_sync meta data;
wenzelm
parents: 75509
diff changeset
    61
    sync(hg, target, rev,
75824
a2b2e8964e1a tuned signature;
wenzelm
parents: 75555
diff changeset
    62
      contents = List(File.content(Path.explode("etc/ISABELLE_ID"), hg.id(rev = rev))),
75553
4dd0f250ec0d more options;
wenzelm
parents: 75552
diff changeset
    63
      filter = filter_heaps ::: List("protect /AFP"))
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    64
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    65
    for (hg <- afp_hg) {
75525
68162e4f60a7 clarified signature: more explicit type Rsync.Context;
wenzelm
parents: 75524
diff changeset
    66
      context.progress.echo_if(verbose, "\n* AFP repository:")
75524
ff8012edac89 clarified signature;
wenzelm
parents: 75523
diff changeset
    67
      sync(hg, Rsync.append(target, "AFP"), afp_rev)
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    68
    }
75552
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    69
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    70
    val images =
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    71
      find_images(options, session_images,
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    72
        dirs = afp_root.map(_ + Path.explode("thys")).toList)
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    73
    if (images.nonEmpty) {
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    74
      context.progress.echo_if(verbose, "\n* Session images:")
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    75
      Rsync.exec(context, verbose = verbose, thorough = thorough, dry_run = dry_run,
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    76
        args = List("--relative", "--") ::: images ::: List(Rsync.append(target, "heaps/"))).check
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    77
    }
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    78
  }
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    79
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    80
  val isabelle_tool =
75549
4b21e823d35f clarified names;
wenzelm
parents: 75536
diff changeset
    81
    Isabelle_Tool("sync", "synchronize Isabelle + AFP repositories",
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    82
      Scala_Project.here, { args =>
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    83
        var afp_root: Option[Path] = None
75553
4dd0f250ec0d more options;
wenzelm
parents: 75552
diff changeset
    84
        var purge_heaps = false
75552
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
    85
        var session_images = List.empty[String]
75492
c03c2bf4ef8a preserve jars for quick testing;
wenzelm
parents: 75491
diff changeset
    86
        var preserve_jars = false
75536
7cdeed5dc96d more robust treatment of rsync on macOS (see also 96fb1f9a4042);
wenzelm
parents: 75525
diff changeset
    87
        var protect_args = false
75487
167660a8f99e support thorough check of file content;
wenzelm
parents: 75486
diff changeset
    88
        var thorough = false
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    89
        var afp_rev = ""
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    90
        var dry_run = false
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    91
        var rev = ""
75499
c635368021b6 support explicit SSH port;
wenzelm
parents: 75497
diff changeset
    92
        var port = SSH.default_port
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    93
        var verbose = false
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    94
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    95
        val getopts = Getopts("""
75549
4b21e823d35f clarified names;
wenzelm
parents: 75536
diff changeset
    96
Usage: isabelle sync [OPTIONS] TARGET
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    97
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
    98
  Options are:
75497
0a5f7b5da16f clarified options;
wenzelm
parents: 75493
diff changeset
    99
    -A ROOT      include AFP with given root directory (":" for """ + AFP.BASE.implode + """)
75553
4dd0f250ec0d more options;
wenzelm
parents: 75552
diff changeset
   100
    -H           purge heaps directory on target
75552
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
   101
    -I NAME      include session heap image and build database
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
   102
                 (based on accidental local state)
75492
c03c2bf4ef8a preserve jars for quick testing;
wenzelm
parents: 75491
diff changeset
   103
    -J           preserve *.jar files
75555
197a5b3a1ea2 promote "isabelle sync" to regular user-space tool, with proper documentation;
wenzelm
parents: 75553
diff changeset
   104
    -S           robust (but less portable) treatment of spaces in
197a5b3a1ea2 promote "isabelle sync" to regular user-space tool, with proper documentation;
wenzelm
parents: 75553
diff changeset
   105
                 file and directory names on the target
75493
f775dfb55655 clarified option -T;
wenzelm
parents: 75492
diff changeset
   106
    -T           thorough treatment of file content and directory times
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   107
    -a REV       explicit AFP revision (default: state of working directory)
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   108
    -n           no changes: dry-run
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   109
    -r REV       explicit revision (default: state of working directory)
75499
c635368021b6 support explicit SSH port;
wenzelm
parents: 75497
diff changeset
   110
    -p PORT      explicit SSH port (default: """ + SSH.default_port + """)
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   111
    -v           verbose
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   112
75555
197a5b3a1ea2 promote "isabelle sync" to regular user-space tool, with proper documentation;
wenzelm
parents: 75553
diff changeset
   113
  Synchronize Isabelle + AFP repositories, based on "isabelle hg_sync".
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   114
""",
75497
0a5f7b5da16f clarified options;
wenzelm
parents: 75493
diff changeset
   115
          "A:" -> (arg => afp_root = Some(if (arg == ":") AFP.BASE else Path.explode(arg))),
75553
4dd0f250ec0d more options;
wenzelm
parents: 75552
diff changeset
   116
          "H" -> (_ => purge_heaps = true),
75552
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
   117
          "I:" -> (arg => session_images = session_images ::: List(arg)),
75492
c03c2bf4ef8a preserve jars for quick testing;
wenzelm
parents: 75491
diff changeset
   118
          "J" -> (_ => preserve_jars = true),
75536
7cdeed5dc96d more robust treatment of rsync on macOS (see also 96fb1f9a4042);
wenzelm
parents: 75525
diff changeset
   119
          "S" -> (_ => protect_args = true),
75487
167660a8f99e support thorough check of file content;
wenzelm
parents: 75486
diff changeset
   120
          "T" -> (_ => thorough = true),
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   121
          "a:" -> (arg => afp_rev = arg),
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   122
          "n" -> (_ => dry_run = true),
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   123
          "r:" -> (arg => rev = arg),
75499
c635368021b6 support explicit SSH port;
wenzelm
parents: 75497
diff changeset
   124
          "p:" -> (arg => port = Value.Int.parse(arg)),
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   125
          "v" -> (_ => verbose = true))
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   126
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   127
        val more_args = getopts(args)
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   128
        val target =
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   129
          more_args match {
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   130
            case List(target) => target
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   131
            case _ => getopts.usage()
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   132
          }
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   133
75552
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
   134
        val options = Options.init()
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   135
        val progress = new Console_Progress
75536
7cdeed5dc96d more robust treatment of rsync on macOS (see also 96fb1f9a4042);
wenzelm
parents: 75525
diff changeset
   136
        val context = Rsync.Context(progress, port = port, protect_args = protect_args)
75552
4aa3da02fd4d sync session images, based on accidental local state;
wenzelm
parents: 75549
diff changeset
   137
        sync(options, context, target, verbose = verbose, thorough = thorough,
75553
4dd0f250ec0d more options;
wenzelm
parents: 75552
diff changeset
   138
          purge_heaps = purge_heaps, session_images = session_images, preserve_jars = preserve_jars,
4dd0f250ec0d more options;
wenzelm
parents: 75552
diff changeset
   139
          dry_run = dry_run, rev = rev, afp_root = afp_root, afp_rev = afp_rev)
75481
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   140
      }
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   141
    )
029cd4e1a2c7 support to synchronize Isabelle + AFP repositories;
wenzelm
parents:
diff changeset
   142
}