Class: PmgmtLib::SyncFiles

Inherits:
Object
  • Object
show all
Defined in:
lib/syncfiles.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(common) ⇒ SyncFiles

Returns a new instance of SyncFiles.



7
8
9
# File 'lib/syncfiles.rb', line 7

def initialize(common)
  @c = common
end

Instance Attribute Details

#cObject (readonly)

Returns the value of attribute c.



5
6
7
# File 'lib/syncfiles.rb', line 5

def c
  @c
end

Instance Method Details

#foreach_static_fileObject



126
127
128
129
130
131
132
133
# File 'lib/syncfiles.rb', line 126

def foreach_static_file()
  env = c.load_env
  Dir.foreach(env.static_file_src) do |entry|
    unless [".", ".."].include?(entry)
      yield env.static_file_src, entry
    end
  end
end

#get_dest_path(src, dst) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
# File 'lib/syncfiles.rb', line 53

def get_dest_path(src, dst)
  if dst.nil?
    dst = src
  end
  dst = dst.split(/\//).reverse.drop(1).reverse.join("/")
  if not dst.empty?
    dst = "/w/#{dst}"
  else
    dst = "/w"
  end
end

#get_src_volume_mountObject



26
27
28
29
30
31
32
# File 'lib/syncfiles.rb', line 26

def get_src_volume_mount()
  if is_fswatch_installed
    %W{-v #{src_vol_name}:/w}
  else
    %W{-v #{ENV["PWD"]}:/w}
  end
end

#get_volume_mountsObject



34
35
36
37
38
39
40
41
# File 'lib/syncfiles.rb', line 34

def get_volume_mounts()
  env = c.load_env
  if env.static_file_dest
    get_src_volume_mount + %W{-v #{output_vol_name}:/w/#{env.static_file_dest}}
  else
    get_src_volume_mount
  end
end

#is_fswatch_installedObject



11
12
13
14
# File 'lib/syncfiles.rb', line 11

def is_fswatch_installed()
  status = c.run %W{which fswatch}
  return status.success?
end


108
109
110
111
# File 'lib/syncfiles.rb', line 108

def link_static_file(src, dst)
  cmd = %W{docker run --rm -w /w} + get_volume_mounts + %W{alpine ln -snf /w/#{src} /w/#{dst}}
  c.run_inline cmd
end


113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/syncfiles.rb', line 113

def link_static_files()
  env = c.load_env
  threads = []
  foreach_static_file do |path, entry|
    threads << Thread.new do
      link_static_file "#{path}/#{entry}", "#{env.static_file_dest}/#{entry}"
    end
  end
  threads.each do |t|
    t.join
  end
end

#log_file_nameObject



43
44
45
# File 'lib/syncfiles.rb', line 43

def log_file_name()
  ".rsync.log"
end

#log_message(s) ⇒ Object



47
48
49
50
51
# File 'lib/syncfiles.rb', line 47

def log_message(s)
  File.open(log_file_name, "a") do |file|
    file.write s
  end
end

#maybe_start_file_syncingObject



180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/syncfiles.rb', line 180

def maybe_start_file_syncing()
  system_name, _ = Open3.capture2("uname")
  system_name.chomp!
  env = c.load_env
  if env.static_file_src
    c.status "Linking static files..."
    link_static_files
  end
  fswatch_installed = is_fswatch_installed
  if system_name == "Darwin" and not fswatch_installed
    c.error "fswatch is not installed."
    STDERR.puts "File syncing will be extremely slow due to a performance problem in docker.\n" \
      "Installing fswatch is highly recommended. Try:\n\n$ brew install fswatch\n\n"
  end
  if fswatch_installed
    c.status "Starting rsync container..."
    at_exit { stop_rsync_container }
    start_rsync_container
    c.status "Performing initial file sync..."
    perform_initial_sync
    start_watching_sync
    c.status "Watching source files. See log at #{log_file_name}."
  end
end

#output_vol_nameObject



21
22
23
24
# File 'lib/syncfiles.rb', line 21

def output_vol_name()
  env = c.load_env
  "#{env.namespace}-out"
end

#perform_initial_syncObject



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/syncfiles.rb', line 145

def perform_initial_sync()
  env = c.load_env
  env.source_file_paths.each do |src_path|
    # Copying using tar ensures the destination directories will be created.
    c.pipe(
      %W{env COPYFILE_DISABLE=1 tar -c #{src_path}},
      %W{docker cp - #{env.namespace}-rsync:/w}
    )
    rsync_path src_path, nil, false
  end
  if env.static_file_src
    c.pipe(
      %W{env COPYFILE_DISABLE=1 tar -c #{env.static_file_src}},
      %W{docker cp - #{env.namespace}-rsync:/w}
    )
    rsync_path env.static_file_src, nil, false
  end
end

#rsync_path(src, dst, log) ⇒ Object



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/syncfiles.rb', line 85

def rsync_path(src, dst, log)
  env = c.load_env
  dst = get_dest_path(src, dst)
  rsync_remote_shell = "docker exec -i"
  cmd = %W{
    rsync --blocking-io -azlv --delete -e #{rsync_remote_shell}
      #{src}
      #{env.namespace}-rsync:#{dst}
  }
  if log
    Open3.popen3(*cmd) do |i, o, e, t|
      i.close
      if not t.value.success?
        c.error e.read
        exit t.value.exitstatus
      end
      log_message o.read
    end
  else
    c.run_inline cmd
  end
end

#src_vol_nameObject



16
17
18
19
# File 'lib/syncfiles.rb', line 16

def src_vol_name()
  env = c.load_env
  "#{env.namespace}-src"
end

#start_rsync_containerObject



65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/syncfiles.rb', line 65

def start_rsync_container()
  env = c.load_env
  c.docker.requires_docker
  c.docker.ensure_image("tjamet/rsync")
  cmd = %W{
    docker run -d
      --name #{env.namespace}-rsync
      -v #{src_vol_name}:/w
  }
  if env.static_file_dest
    cmd += %W{-v #{output_vol_name}:/w/#{env.static_file_dest}}
  end
  c.run_inline cmd + %W{-e DAEMON=docker tjamet/rsync}
end

#start_watching_syncObject



164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/syncfiles.rb', line 164

def start_watching_sync()
  env = c.load_env
  File.open(log_file_name, "w") {} # Create and truncate if exists.
  paths_to_watch = env.source_file_paths
  if env.static_file_src
    paths_to_watch += [env.static_file_src]
  end
  paths_to_watch.each do |src_path|
    thread = Thread.new { watch_path src_path, nil }
    at_exit {
      Process.kill("HUP", thread["pid"])
      thread.join
    }
  end
end

#stop_rsync_containerObject



80
81
82
83
# File 'lib/syncfiles.rb', line 80

def stop_rsync_container()
  env = c.load_env
  c.run_inline %W{docker rm -f #{env.namespace}-rsync}
end

#watch_path(src, dst) ⇒ Object



135
136
137
138
139
140
141
142
143
# File 'lib/syncfiles.rb', line 135

def watch_path(src, dst)
  Open3.popen3(*%W{fswatch -o #{src}}) do |stdin, stdout, stderr, thread|
    Thread.current["pid"] = thread.pid
    stdin.close
    stdout.each_line do |_|
      rsync_path src, dst, true
    end
  end
end