Class: Vagrant::Action::Builtin::SyncedFolders

Inherits:
Object
  • Object
show all
Includes:
MixinSyncedFolders
Defined in:
lib/vagrant/action/builtin/synced_folders.rb

Overview

This middleware will setup the synced folders for the machine using the appropriate synced folder plugin.

Instance Method Summary collapse

Methods included from MixinSyncedFolders

#default_synced_folder_type, #impl_opts, #plugins, #save_synced_folders, #synced_folders, #synced_folders_diff

Methods included from Util::ScopedHashOverride

#scoped_hash_override

Constructor Details

#initialize(app, env) ⇒ SyncedFolders

Returns a new instance of SyncedFolders.


15
16
17
18
# File 'lib/vagrant/action/builtin/synced_folders.rb', line 15

def initialize(app, env)
  @app    = app
  @logger = Log4r::Logger.new("vagrant::action::builtin::synced_folders")
end

Instance Method Details

#call(env) ⇒ Object


20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/vagrant/action/builtin/synced_folders.rb', line 20

def call(env)
  opts = {
    cached: !!env[:synced_folders_cached],
    config: env[:synced_folders_config],
  }

  @logger.info("SyncedFolders loading from cache: #{opts[:cached]}")
  folders = synced_folders(env[:machine], **opts)
  original_folders = folders

  folders.each do |impl_name, fs|
    @logger.info("Synced Folder Implementation: #{impl_name}")

    fs.each do |id, data|
      # Log every implementation and their paths
      @logger.info("  - #{id}: #{data[:hostpath]} => #{data[:guestpath]}")
    end
  end

  # Go through each folder and make sure to create it if
  # it does not exist on host
  folders.each do |_, fs|
    fs.each do |id, data|
      next if data[:hostpath_exact]

      data[:hostpath] = File.expand_path(
        data[:hostpath], env[:root_path])

      # Expand the symlink if this is a path that exists
      if File.file?(data[:hostpath])
        data[:hostpath] = File.realpath(data[:hostpath])
      end

      # Create the hostpath if it doesn't exist and we've been told to
      if !File.directory?(data[:hostpath]) && data[:create]
        @logger.info("Creating shared folder host directory: #{data[:hostpath]}")
        begin
          Pathname.new(data[:hostpath]).mkpath
        rescue Errno::EACCES
          raise Vagrant::Errors::SharedFolderCreateFailed,
            path: data[:hostpath]
        end
      end

      if File.directory?(data[:hostpath])
        data[:hostpath] = File.realpath(data[:hostpath])
        data[:hostpath] = Util::Platform.fs_real_path(data[:hostpath]).to_s
      end
    end
  end

  # Build up the instances of the synced folders. We do this once
  # so that they can store state.
  folders = folders.map do |impl_name, fs|
    instance = plugins[impl_name.to_sym][0].new
    [instance, impl_name, fs]
  end

  # Go through each folder and prepare the folders
  folders.each do |impl, impl_name, fs|
    if !env[:synced_folders_disable]
      @logger.info("Invoking synced folder prepare for: #{impl_name}")
      impl.prepare(env[:machine], fs, impl_opts(impl_name, env))
    end
  end

  # Continue, we need the VM to be booted.
  @app.call(env)

  # Once booted, setup the folder contents
  folders.each do |impl, impl_name, fs|
    if !env[:synced_folders_disable]
      @logger.info("Invoking synced folder enable: #{impl_name}")
      impl.enable(env[:machine], fs, impl_opts(impl_name, env))
      next
    end

    # We're disabling synced folders
    to_disable = {}
    fs.each do |id, data|
      next if !env[:synced_folders_disable].include?(id)
      to_disable[id] = data
    end

    @logger.info("Invoking synced folder disable: #{impl_name}")
    to_disable.each do |id, _|
      @logger.info("  - Disabling: #{id}")
    end
    impl.disable(env[:machine], to_disable, impl_opts(impl_name, env))
  end

  # If we disabled folders, we have to delete some from the
  # save, so we load the entire cached thing, and delete them.
  if env[:synced_folders_disable]
    all = synced_folders(env[:machine], cached: true)
    all.each do |impl, fs|
      fs.keys.each do |id|
        if env[:synced_folders_disable].include?(id)
          fs.delete(id)
        end
      end
    end

    save_synced_folders(env[:machine], all)
  else
    save_opts = { merge: true }
    save_opts[:vagrantfile] = true if !opts[:config]

    # Save the synced folders
    save_synced_folders(env[:machine], original_folders, **save_opts)
  end

  # Persist the mounts by adding them to fstab (only if the guest is available)
  begin
    persist_mount = env[:machine].guest.capability?(:persist_mount_shared_folder)
  rescue Errors::MachineGuestNotReady
    persist_mount = false
  end
  if persist_mount
    # Persist the mounts by adding them to fstab
    if env[:machine].config.vm.allow_fstab_modification
      fstab_folders = original_folders
    else
      fstab_folders = nil
    end
    env[:machine].guest.capability(:persist_mount_shared_folder, fstab_folders)
  end
end