예제 #1
0
func (h *Handlers) download(v *vagrantutil.Vagrant, box, filePath string, queue <-chan chan error) {
	h.log().Debug("downloading %q box...", box)

	var listeners []chan error
	done := make(chan error)

	go func() {
		err := vagrantutil.Wait(v.BoxAdd(&vagrantutil.Box{Name: box}))
		if err == vagrantutil.ErrBoxAlreadyExists {
			// Ignore the above error.
			err = nil
		}

		done <- err
	}()

	for {
		select {
		case l := <-queue:
			listeners = append(listeners, l)
		case err := <-done:
			// Remove the box from in progress.
			h.boxMu.Lock()
			delete(h.boxNames, box)
			delete(h.boxPaths, filePath)
			h.boxMu.Unlock()

			// Defensive channel drain: try to collect listeners
			// that may have registered after receiving from done
			// but before taking boxMu lock.
			listeners = append(listeners, drain(queue)...)

			// Notify all listeners.
			for _, l := range listeners {
				l <- err
			}

			h.log().Debug("downloading %q box finished: err=%v", box, err)

			return
		}
	}
}