| author | wenzelm | 
| Fri, 08 Jul 2022 22:29:26 +0200 | |
| changeset 75660 | 45d3497c0baa | 
| parent 75555 | 197a5b3a1ea2 | 
| child 75824 | a2b2e8964e1a | 
| permissions | -rw-r--r-- | 
| 75555 
197a5b3a1ea2
promote "isabelle sync" to regular user-space tool, with proper documentation;
 wenzelm parents: 
75553diff
changeset | 1 | /* Title: Pure/Tools/sync.scala | 
| 75481 | 2 | Author: Makarius | 
| 3 | ||
| 4 | Synchronize Isabelle + AFP repositories. | |
| 5 | */ | |
| 6 | ||
| 7 | package isabelle | |
| 8 | ||
| 9 | ||
| 75549 | 10 | object Sync {
 | 
| 75552 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 11 | /* session images */ | 
| 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 12 | |
| 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 13 | def find_images(options: Options, session_images: List[String], | 
| 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 14 | dirs: List[Path] = Nil | 
| 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 15 |   ): List[String] = {
 | 
| 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 16 | if (session_images.isEmpty) Nil | 
| 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 17 |     else {
 | 
| 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 18 | val store = Sessions.store(options) | 
| 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 19 | val sessions_structure = Sessions.load_structure(options, dirs = dirs) | 
| 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 20 |       sessions_structure.build_requirements(session_images).flatMap { session =>
 | 
| 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 21 | val heap = | 
| 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 22 | store.find_heap(session).map(_.expand).map(path => | 
| 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
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: 
75549diff
changeset | 24 | val db = | 
| 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 25 | store.find_database(session).map(_.expand).map(path => | 
| 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
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: 
75549diff
changeset | 27 | path.dir.file_name + "/" + path.file_name) | 
| 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 28 | heap.toList ::: db.toList | 
| 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 29 | } | 
| 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 30 | } | 
| 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 31 | } | 
| 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 32 | |
| 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 33 | |
| 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 34 | /* sync */ | 
| 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 35 | |
| 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 36 | def sync(options: Options, context: Rsync.Context, target: String, | 
| 75481 | 37 | verbose: Boolean = false, | 
| 75487 | 38 | thorough: Boolean = false, | 
| 75553 | 39 | purge_heaps: Boolean = false, | 
| 75552 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 40 | session_images: List[String] = Nil, | 
| 75492 | 41 | preserve_jars: Boolean = false, | 
| 75481 | 42 | dry_run: Boolean = false, | 
| 43 | rev: String = "", | |
| 44 | afp_root: Option[Path] = None, | |
| 45 | afp_rev: String = "" | |
| 46 |   ): Unit = {
 | |
| 75506 | 47 | val hg = Mercurial.self_repository() | 
| 75481 | 48 | val afp_hg = afp_root.map(Mercurial.repository(_)) | 
| 49 | ||
| 75492 | 50 |     val more_filter = if (preserve_jars) List("include *.jar", "protect *.jar") else Nil
 | 
| 51 | ||
| 75511 | 52 | def sync(hg: Mercurial.Repository, dest: String, r: String, | 
| 53 | contents: List[File.Content] = Nil, filter: List[String] = Nil | |
| 54 |     ): Unit = {
 | |
| 75525 
68162e4f60a7
clarified signature: more explicit type Rsync.Context;
 wenzelm parents: 
75524diff
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: 
75524diff
changeset | 56 | contents = contents, filter = filter ::: more_filter) | 
| 75511 | 57 | } | 
| 75481 | 58 | |
| 75525 
68162e4f60a7
clarified signature: more explicit type Rsync.Context;
 wenzelm parents: 
75524diff
changeset | 59 | context.progress.echo_if(verbose, "\n* Isabelle repository:") | 
| 75553 | 60 |     val filter_heaps = if (purge_heaps) Nil else List("protect /heaps", "protect /heaps/**")
 | 
| 75511 | 61 | sync(hg, target, rev, | 
| 62 |       contents = List(File.Content(Path.explode("etc/ISABELLE_ID"), hg.id(rev = rev))),
 | |
| 75553 | 63 |       filter = filter_heaps ::: List("protect /AFP"))
 | 
| 75481 | 64 | |
| 65 |     for (hg <- afp_hg) {
 | |
| 75525 
68162e4f60a7
clarified signature: more explicit type Rsync.Context;
 wenzelm parents: 
75524diff
changeset | 66 | context.progress.echo_if(verbose, "\n* AFP repository:") | 
| 75524 | 67 | sync(hg, Rsync.append(target, "AFP"), afp_rev) | 
| 75481 | 68 | } | 
| 75552 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 69 | |
| 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 70 | val images = | 
| 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 71 | find_images(options, session_images, | 
| 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 72 |         dirs = afp_root.map(_ + Path.explode("thys")).toList)
 | 
| 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 73 |     if (images.nonEmpty) {
 | 
| 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 74 | context.progress.echo_if(verbose, "\n* Session images:") | 
| 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 75 | Rsync.exec(context, verbose = verbose, thorough = thorough, dry_run = dry_run, | 
| 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 76 |         args = List("--relative", "--") ::: images ::: List(Rsync.append(target, "heaps/"))).check
 | 
| 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 77 | } | 
| 75481 | 78 | } | 
| 79 | ||
| 80 | val isabelle_tool = | |
| 75549 | 81 |     Isabelle_Tool("sync", "synchronize Isabelle + AFP repositories",
 | 
| 75481 | 82 |       Scala_Project.here, { args =>
 | 
| 83 | var afp_root: Option[Path] = None | |
| 75553 | 84 | var purge_heaps = false | 
| 75552 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 85 | var session_images = List.empty[String] | 
| 75492 | 86 | var preserve_jars = false | 
| 75536 
7cdeed5dc96d
more robust treatment of rsync on macOS (see also 96fb1f9a4042);
 wenzelm parents: 
75525diff
changeset | 87 | var protect_args = false | 
| 75487 | 88 | var thorough = false | 
| 75481 | 89 | var afp_rev = "" | 
| 90 | var dry_run = false | |
| 91 | var rev = "" | |
| 75499 | 92 | var port = SSH.default_port | 
| 75481 | 93 | var verbose = false | 
| 94 | ||
| 95 |         val getopts = Getopts("""
 | |
| 75549 | 96 | Usage: isabelle sync [OPTIONS] TARGET | 
| 75481 | 97 | |
| 98 | Options are: | |
| 75497 | 99 |     -A ROOT      include AFP with given root directory (":" for """ + AFP.BASE.implode + """)
 | 
| 75553 | 100 | -H purge heaps directory on target | 
| 75552 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 101 | -I NAME include session heap image and build database | 
| 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 102 | (based on accidental local state) | 
| 75492 | 103 | -J preserve *.jar files | 
| 75555 
197a5b3a1ea2
promote "isabelle sync" to regular user-space tool, with proper documentation;
 wenzelm parents: 
75553diff
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: 
75553diff
changeset | 105 | file and directory names on the target | 
| 75493 | 106 | -T thorough treatment of file content and directory times | 
| 75481 | 107 | -a REV explicit AFP revision (default: state of working directory) | 
| 108 | -n no changes: dry-run | |
| 109 | -r REV explicit revision (default: state of working directory) | |
| 75499 | 110 | -p PORT explicit SSH port (default: """ + SSH.default_port + """) | 
| 75481 | 111 | -v verbose | 
| 112 | ||
| 75555 
197a5b3a1ea2
promote "isabelle sync" to regular user-space tool, with proper documentation;
 wenzelm parents: 
75553diff
changeset | 113 | Synchronize Isabelle + AFP repositories, based on "isabelle hg_sync". | 
| 75481 | 114 | """, | 
| 75497 | 115 | "A:" -> (arg => afp_root = Some(if (arg == ":") AFP.BASE else Path.explode(arg))), | 
| 75553 | 116 | "H" -> (_ => purge_heaps = true), | 
| 75552 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 117 | "I:" -> (arg => session_images = session_images ::: List(arg)), | 
| 75492 | 118 | "J" -> (_ => preserve_jars = true), | 
| 75536 
7cdeed5dc96d
more robust treatment of rsync on macOS (see also 96fb1f9a4042);
 wenzelm parents: 
75525diff
changeset | 119 | "S" -> (_ => protect_args = true), | 
| 75487 | 120 | "T" -> (_ => thorough = true), | 
| 75481 | 121 | "a:" -> (arg => afp_rev = arg), | 
| 122 | "n" -> (_ => dry_run = true), | |
| 123 | "r:" -> (arg => rev = arg), | |
| 75499 | 124 | "p:" -> (arg => port = Value.Int.parse(arg)), | 
| 75481 | 125 | "v" -> (_ => verbose = true)) | 
| 126 | ||
| 127 | val more_args = getopts(args) | |
| 128 | val target = | |
| 129 |           more_args match {
 | |
| 130 | case List(target) => target | |
| 131 | case _ => getopts.usage() | |
| 132 | } | |
| 133 | ||
| 75552 
4aa3da02fd4d
sync session images, based on accidental local state;
 wenzelm parents: 
75549diff
changeset | 134 | val options = Options.init() | 
| 75481 | 135 | val progress = new Console_Progress | 
| 75536 
7cdeed5dc96d
more robust treatment of rsync on macOS (see also 96fb1f9a4042);
 wenzelm parents: 
75525diff
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: 
75549diff
changeset | 137 | sync(options, context, target, verbose = verbose, thorough = thorough, | 
| 75553 | 138 | purge_heaps = purge_heaps, session_images = session_images, preserve_jars = preserve_jars, | 
| 139 | dry_run = dry_run, rev = rev, afp_root = afp_root, afp_rev = afp_rev) | |
| 75481 | 140 | } | 
| 141 | ) | |
| 142 | } |