| author | wenzelm |
| Sat, 08 Apr 2023 18:08:20 +0200 | |
| changeset 77788 | c2ce9ac85859 |
| parent 77787 | b20ac2c26ea3 |
| child 77790 | ed68c546746c |
| permissions | -rw-r--r-- |
| 75523 | 1 |
/* Title: Pure/General/rsync.scala |
2 |
Author: Makarius |
|
3 |
||
4 |
Support for rsync: see also https://rsync.samba.org |
|
5 |
*/ |
|
6 |
||
7 |
package isabelle |
|
8 |
||
9 |
||
10 |
object Rsync {
|
|
| 77787 | 11 |
object Context {
|
12 |
def apply( |
|
13 |
progress: Progress = new Progress, |
|
14 |
ssh: SSH.System = SSH.Local, |
|
15 |
archive: Boolean = true, |
|
16 |
protect_args: Boolean = true // requires rsync 3.0.0, or later |
|
|
77788
c2ce9ac85859
use remote copy of locally installed rsync component: for uniform version and options;
wenzelm
parents:
77787
diff
changeset
|
17 |
): Context = {
|
|
c2ce9ac85859
use remote copy of locally installed rsync component: for uniform version and options;
wenzelm
parents:
77787
diff
changeset
|
18 |
val directory = Components.provide(Component_Rsync.home, ssh = ssh, progress = progress) |
|
c2ce9ac85859
use remote copy of locally installed rsync component: for uniform version and options;
wenzelm
parents:
77787
diff
changeset
|
19 |
val remote_program = Component_Rsync.remote_program(directory) |
|
c2ce9ac85859
use remote copy of locally installed rsync component: for uniform version and options;
wenzelm
parents:
77787
diff
changeset
|
20 |
val rsync_path = quote(File.standard_path(remote_program)) |
|
c2ce9ac85859
use remote copy of locally installed rsync component: for uniform version and options;
wenzelm
parents:
77787
diff
changeset
|
21 |
new Context(progress, ssh, rsync_path, archive, protect_args) |
|
c2ce9ac85859
use remote copy of locally installed rsync component: for uniform version and options;
wenzelm
parents:
77787
diff
changeset
|
22 |
} |
| 77787 | 23 |
} |
24 |
||
25 |
final class Context private( |
|
26 |
val progress: Progress, |
|
27 |
val ssh: SSH.System, |
|
|
77788
c2ce9ac85859
use remote copy of locally installed rsync component: for uniform version and options;
wenzelm
parents:
77787
diff
changeset
|
28 |
rsync_path: String, |
| 77787 | 29 |
archive: Boolean, |
|
77788
c2ce9ac85859
use remote copy of locally installed rsync component: for uniform version and options;
wenzelm
parents:
77787
diff
changeset
|
30 |
protect_args: Boolean, |
| 75527 | 31 |
) {
|
|
77788
c2ce9ac85859
use remote copy of locally installed rsync component: for uniform version and options;
wenzelm
parents:
77787
diff
changeset
|
32 |
def no_progress: Context = new Context(new Progress, ssh, rsync_path, archive, protect_args) |
|
c2ce9ac85859
use remote copy of locally installed rsync component: for uniform version and options;
wenzelm
parents:
77787
diff
changeset
|
33 |
def no_archive: Context = new Context(progress, ssh, rsync_path, false, protect_args) |
| 77787 | 34 |
|
|
76136
1bb677cceea4
let rsync re-use ssh connection via control path;
wenzelm
parents:
76131
diff
changeset
|
35 |
def command: String = {
|
|
77783
fb61887c069a
clarified underlying SSH session of "isabelle hg_sync" and "isabelle sync";
wenzelm
parents:
77518
diff
changeset
|
36 |
val ssh_command = ssh.client_command |
|
77788
c2ce9ac85859
use remote copy of locally installed rsync component: for uniform version and options;
wenzelm
parents:
77787
diff
changeset
|
37 |
File.bash_path(Component_Rsync.local_program) + |
|
77783
fb61887c069a
clarified underlying SSH session of "isabelle hg_sync" and "isabelle sync";
wenzelm
parents:
77518
diff
changeset
|
38 |
if_proper(ssh_command, " --rsh=" + Bash.string(ssh_command)) + |
|
77788
c2ce9ac85859
use remote copy of locally installed rsync component: for uniform version and options;
wenzelm
parents:
77787
diff
changeset
|
39 |
" --rsync-path=" + Bash.string(rsync_path) + |
| 75527 | 40 |
(if (archive) " --archive" else "") + |
41 |
(if (protect_args) " --protect-args" else "") |
|
|
76136
1bb677cceea4
let rsync re-use ssh connection via control path;
wenzelm
parents:
76131
diff
changeset
|
42 |
} |
|
77783
fb61887c069a
clarified underlying SSH session of "isabelle hg_sync" and "isabelle sync";
wenzelm
parents:
77518
diff
changeset
|
43 |
|
|
fb61887c069a
clarified underlying SSH session of "isabelle hg_sync" and "isabelle sync";
wenzelm
parents:
77518
diff
changeset
|
44 |
def target(path: Path, direct: Boolean = false): String = {
|
|
fb61887c069a
clarified underlying SSH session of "isabelle hg_sync" and "isabelle sync";
wenzelm
parents:
77518
diff
changeset
|
45 |
val s = ssh.rsync_path(path) |
|
fb61887c069a
clarified underlying SSH session of "isabelle hg_sync" and "isabelle sync";
wenzelm
parents:
77518
diff
changeset
|
46 |
if (direct) Url.direct_path(s) else s |
|
fb61887c069a
clarified underlying SSH session of "isabelle hg_sync" and "isabelle sync";
wenzelm
parents:
77518
diff
changeset
|
47 |
} |
|
75525
68162e4f60a7
clarified signature: more explicit type Rsync.Context;
wenzelm
parents:
75524
diff
changeset
|
48 |
} |
|
68162e4f60a7
clarified signature: more explicit type Rsync.Context;
wenzelm
parents:
75524
diff
changeset
|
49 |
|
| 75526 | 50 |
def exec( |
|
75525
68162e4f60a7
clarified signature: more explicit type Rsync.Context;
wenzelm
parents:
75524
diff
changeset
|
51 |
context: Context, |
| 75523 | 52 |
thorough: Boolean = false, |
53 |
prune_empty_dirs: Boolean = false, |
|
54 |
dry_run: Boolean = false, |
|
55 |
clean: Boolean = false, |
|
56 |
filter: List[String] = Nil, |
|
57 |
args: List[String] = Nil |
|
58 |
): Process_Result = {
|
|
| 77517 | 59 |
val progress = context.progress |
| 75523 | 60 |
val script = |
|
75525
68162e4f60a7
clarified signature: more explicit type Rsync.Context;
wenzelm
parents:
75524
diff
changeset
|
61 |
context.command + |
|
77518
fda4da0f80f4
clarified signature: manage "verbose" flag via "progress";
wenzelm
parents:
77517
diff
changeset
|
62 |
(if (progress.verbose) " --verbose" else "") + |
| 75523 | 63 |
(if (thorough) " --ignore-times" else " --omit-dir-times") + |
64 |
(if (prune_empty_dirs) " --prune-empty-dirs" else "") + |
|
65 |
(if (dry_run) " --dry-run" else "") + |
|
66 |
(if (clean) " --delete-excluded" else "") + |
|
67 |
filter.map(s => " --filter=" + Bash.string(s)).mkString + |
|
| 77369 | 68 |
if_proper(args, " " + Bash.strings(args)) |
| 77517 | 69 |
progress.bash(script, echo = true) |
| 75523 | 70 |
} |
71 |
||
|
77783
fb61887c069a
clarified underlying SSH session of "isabelle hg_sync" and "isabelle sync";
wenzelm
parents:
77518
diff
changeset
|
72 |
def init(context: Context, target: Path, |
| 75523 | 73 |
contents: List[File.Content] = Nil |
74 |
): Unit = |
|
75 |
Isabelle_System.with_tmp_dir("sync") { tmp_dir =>
|
|
76 |
val init_dir = Isabelle_System.make_directory(tmp_dir + Path.explode("init"))
|
|
77 |
contents.foreach(_.write(init_dir)) |
|
| 77787 | 78 |
exec(context.no_archive, |
|
75534
1d937b12204d
more robust: no change of directory attributes of initial test, notably target without .hg_sync meta data;
wenzelm
parents:
75527
diff
changeset
|
79 |
thorough = true, |
|
1d937b12204d
more robust: no change of directory attributes of initial test, notably target without .hg_sync meta data;
wenzelm
parents:
75527
diff
changeset
|
80 |
args = |
|
1d937b12204d
more robust: no change of directory attributes of initial test, notably target without .hg_sync meta data;
wenzelm
parents:
75527
diff
changeset
|
81 |
List(if (contents.nonEmpty) "--archive" else "--dirs", |
|
77783
fb61887c069a
clarified underlying SSH session of "isabelle hg_sync" and "isabelle sync";
wenzelm
parents:
77518
diff
changeset
|
82 |
File.bash_path(init_dir) + "/.", context.target(target))).check |
| 75523 | 83 |
} |
84 |
} |