Class: Wip::SyncSettings

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

Overview

Validated access to the sync: block, which mirrors the host source tree into a named volume instead of bind-mounting it live.

A bind-mounted app directory is shared into the container's VM over virtiofs, so every stat/open a boot-time directory scan makes is a round trip. Mirroring the tree into a named volume (native storage inside the VM) and re-running the mirror on demand keeps the edit-on-the-host workflow while leaving the running app on fast disk.

Constant Summary collapse

DEFAULT_MOUNT =
'/host-src'
DEFAULT_TARGET =
'/app'
DEFAULT_BINARY =
'rsync'
DEFAULT_INTERVAL =
2
BASE_OPTIONS =

Minimal set for a fast local-to-local mirror: -r walks the tree, -l keeps symlinks as symlinks, -t preserves mtimes so re-syncs can quick- check (size+mtime) instead of re-transferring unchanged files, and --whole-file skips the delta-transfer checksum pass that only pays off over a slow network. Owner/group/perm preservation (-o -g -p, part of -a) is left out since both sides are the same user; add them back via sync.options if a project needs them.

%w[-r -l -t --whole-file].freeze
VOLUME_MODES =

Trailing mount options wslc/docker accept after the container path.

%w[ro rw z Z cached delegated consistent].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(raw, base: nil, workdir: nil, container: nil) ⇒ SyncSettings

Returns a new instance of SyncSettings.

Raises:



32
33
34
35
36
37
38
39
# File 'lib/wip/sync_settings.rb', line 32

def initialize(raw, base: nil, workdir: nil, container: nil)
  raise ConfigError, 'sync must be a mapping' unless raw.is_a?(Hash)

  @base = base
  assign_paths(raw, workdir: workdir, container: container)
  assign_mirror(raw)
  validate!
end

Instance Attribute Details

#binaryObject (readonly)

Returns the value of attribute binary.



30
31
32
# File 'lib/wip/sync_settings.rb', line 30

def binary
  @binary
end

#excludeObject (readonly)

Returns the value of attribute exclude.



30
31
32
# File 'lib/wip/sync_settings.rb', line 30

def exclude
  @exclude
end

#extra_optionsObject (readonly)

Returns the value of attribute extra_options.



30
31
32
# File 'lib/wip/sync_settings.rb', line 30

def extra_options
  @extra_options
end

#intervalObject (readonly)

Returns the value of attribute interval.



30
31
32
# File 'lib/wip/sync_settings.rb', line 30

def interval
  @interval
end

#mountObject (readonly)

Returns the value of attribute mount.



30
31
32
# File 'lib/wip/sync_settings.rb', line 30

def mount
  @mount
end

#targetObject (readonly)

Returns the value of attribute target.



30
31
32
# File 'lib/wip/sync_settings.rb', line 30

def target
  @target
end

#volumeObject (readonly)

Returns the value of attribute volume.



30
31
32
# File 'lib/wip/sync_settings.rb', line 30

def volume
  @volume
end

Instance Method Details

#delete?Boolean

Returns:

  • (Boolean)


41
# File 'lib/wip/sync_settings.rb', line 41

def delete? = !!@delete

#mirror_commandObject

Trailing slashes matter to rsync: they copy the contents of the mount into the target rather than nesting it one directory deeper.



61
62
63
64
65
66
67
# File 'lib/wip/sync_settings.rb', line 61

def mirror_command
  command = [binary, *BASE_OPTIONS]
  command << '--delete' if delete?
  command.concat(exclude.map { |pattern| "--exclude=#{pattern}" })
  command.concat(extra_options)
  command.push("#{mount.chomp('/')}/", "#{target.chomp('/')}/")
end

#replaces?(spec) ⇒ Boolean

True for a configured volume that sync replaces, so .:/app in defaults.volumes quietly becomes the read-only mount plus the volume.

Returns:

  • (Boolean)


55
56
57
# File 'lib/wip/sync_settings.rb', line 55

def replaces?(spec)
  [target.chomp('/'), mount.chomp('/')].include?(container_path(spec))
end

#sourceObject

Expanded against the wip.yml directory so the mirror covers the same tree no matter which subdirectory wip was invoked from.



45
46
47
# File 'lib/wip/sync_settings.rb', line 45

def source
  @source ||= @base ? Pathname(@base).join(@raw_source).expand_path.to_s : @raw_source
end

#to_hObject



69
70
71
72
73
# File 'lib/wip/sync_settings.rb', line 69

def to_h
  { 'source' => source, 'target' => target, 'mount' => mount, 'volume' => volume,
    'delete' => delete?, 'exclude' => exclude, 'command' => binary, 'options' => extra_options,
    'interval' => interval }
end

#volume_specsObject

What -v specs the main container needs: the source read-only, and the named volume where the app actually runs.



51
# File 'lib/wip/sync_settings.rb', line 51

def volume_specs = ["#{source}:#{mount}:ro", "#{volume}:#{target}"]