module VagrantCloud class Box < Data::Mutable autoload :Provider, "vagrant_cloud/box/provider" autoload :Version, "vagrant_cloud/box/version" attr_reader :organization attr_required :name attr_optional :created_at, :updated_at, :tag, :short_description, :description_html, :description_markdown, :private, :downloads, :current_version, :versions, :description, :username attr_mutable :short_description, :description, :private, :versions # Create a new instance # # @return [Box] def initialize(organization:, **opts) @organization = organization @versions_loaded = false opts[:username] = organization.username super(opts) if opts[:versions] && !opts[:versions].empty? self.versions= Array(opts[:versions]).map do |version| Box::Version.load(box: self, **version) end end if opts[:current_version] clean(data: {current_version: Box::Version. load(box: self, **opts[:current_version])}) end clean! end # Delete this box # # @return [nil] # @note This will delete the box, and all versions def delete if exist? organization.account.client.box_delete( username: username, name: name ) b = organization.boxes.dup b.delete(self) organization.clean(data: {boxes: b}) end nil end # Add a new version of this box # # @param [String] version Version number # @return [Version] def add_version(version) if versions.any? { |v| v.version == version } raise Error::BoxError::VersionExistsError, "Version #{version} already exists for box #{tag}" end v = Version.new(box: self, version: version) clean(data: {versions: versions + [v]}) v end # Check if this instance is dirty # # @param [Boolean] deep Check nested instances # @return [Boolean] instance is dirty def dirty?(key=nil, deep: false) if key super(key) else d = super() || !exist? if deep && !d d = Array(plain_versions).any? { |v| v.dirty?(deep: true) } end d end end # @return [Boolean] box exists remotely def exist? !!created_at end # @return [Array] # @note This is used to allow versions information to be loaded # only when requested def versions_on_demand if !@versions_loaded if exist? r = self.organization.account.client.box_get(username: username, name: name) v = Array(r[:versions]).map do |version| Box::Version.load(box: self, **version) end clean(data: {versions: v + Array(plain_versions)}) else clean(data: {versions: []}) end @versions_loaded = true end plain_versions end alias_method :plain_versions, :versions alias_method :versions, :versions_on_demand # Save the box if any changes have been made # # @return [self] def save save_box if dirty? save_versions if dirty?(deep: true) self end protected # Save the box # # @return [self] def save_box req_args = { username: username, name: name, short_description: short_description, description: description, is_private: self.private } if exist? result = organization.account.client.box_update(**req_args) else result = organization.account.client.box_create(**req_args) end clean(data: result, ignores: [:current_version, :versions]) self end # Save the versions if any require saving # # @return [self] def save_versions versions.map(&:save) self end end end