Class: Xcodeproj::Workspace

Inherits:
Object
  • Object
show all
Defined in:
lib/xcodeproj/workspace.rb,
lib/xcodeproj/workspace/reference.rb,
lib/xcodeproj/workspace/file_reference.rb,
lib/xcodeproj/workspace/group_reference.rb

Overview

Provides support for generating, reading and serializing Xcode Workspace documents.

Defined Under Namespace

Classes: FileReference, GroupReference, Reference

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(document, *file_references) ⇒ Workspace

Note:

The document parameter is passed to the << operator if it is not a valid REXML::Document. It is optional, but may also be passed as nil

Returns a new instance of Workspace.



43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/xcodeproj/workspace.rb', line 43

def initialize(document, *file_references)
  @schemes = {}
  if document.nil?
    @document = REXML::Document.new(root_xml(''))
  elsif document.is_a?(REXML::Document)
    @document = document
  else
    @document = REXML::Document.new(root_xml(''))
    self << document
  end
  file_references.each { |ref| self << ref }
end

Instance Attribute Details

#documentREXML::Document (readonly)



12
13
14
# File 'lib/xcodeproj/workspace.rb', line 12

def document
  @document
end

#schemesHash<String => String> (readonly)



16
17
18
# File 'lib/xcodeproj/workspace.rb', line 16

def schemes
  @schemes
end

Class Method Details

.from_s(xml, workspace_path = '') ⇒ Workspace

Returns a workspace generated by reading the contents of the given XML representation.



82
83
84
85
86
87
# File 'lib/xcodeproj/workspace.rb', line 82

def self.from_s(xml, workspace_path = '')
  document = REXML::Document.new(xml)
  instance = new(document)
  instance.load_schemes(workspace_path)
  instance
end

.new_from_xcworkspace(path) ⇒ Workspace

Returns a workspace generated by reading the contents of the given path.



65
66
67
68
69
70
# File 'lib/xcodeproj/workspace.rb', line 65

def self.new_from_xcworkspace(path)
  from_s(File.read(File.join(path, 'contents.xcworkspacedata')),
         File.expand_path(path))
rescue Errno::ENOENT
  new(nil)
end

Instance Method Details

#<<(path_or_reference) ⇒ void

This method returns an undefined value.

Adds a new path to the list of the of projects contained in the workspace.

Raises:

  • (ArgumentError)

    Raised if the input is neither a String nor a FileReference



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/xcodeproj/workspace.rb', line 98

def <<(path_or_reference)
  return unless @document && @document.respond_to?(:root)

  case path_or_reference
  when String
    project_file_reference = Xcodeproj::Workspace::FileReference.new(path_or_reference)
  when Xcodeproj::Workspace::FileReference
    project_file_reference = path_or_reference
    projpath = nil
  else
    raise ArgumentError, "Input to the << operator must be a file path or FileReference, got #{path_or_reference.inspect}"
  end
  unless file_references.any? { |ref| project_file_reference.eql? ref }
    @document.root.add_element(project_file_reference.to_node)
  end
  load_schemes_from_project File.expand_path(projpath || project_file_reference.path)
end

#add_group(name) {|Xcodeproj::Workspace::GroupReference, REXML::Element| ... } ⇒ Xcodeproj::Workspace::GroupReference

Adds a new group container to the workspace workspace.

Yields:



128
129
130
131
132
133
134
# File 'lib/xcodeproj/workspace.rb', line 128

def add_group(name)
  return nil unless @document
  group = Xcodeproj::Workspace::GroupReference.new(name)
  elem = @document.root.add_element(group.to_node)
  yield group, elem if block_given?
  group
end

#file_referencesArray<FileReference>



21
22
23
24
25
26
# File 'lib/xcodeproj/workspace.rb', line 21

def file_references
  return [] unless @document
  @document.get_elements('/Workspace//FileRef').map do |node|
    FileReference.from_node(node)
  end
end

#group_referencesArray<GroupReference>



30
31
32
33
34
35
# File 'lib/xcodeproj/workspace.rb', line 30

def group_references
  return [] unless @document
  @document.get_elements('/Workspace//Group').map do |node|
    GroupReference.from_node(node)
  end
end

#include?(file_reference) ⇒ Boolean

Checks if the workspace contains the project with the given file reference.



144
145
146
# File 'lib/xcodeproj/workspace.rb', line 144

def include?(file_reference)
  file_references.include?(file_reference)
end

#load_schemes(workspace_dir_path) ⇒ void

This method returns an undefined value.

Load all schemes from all projects in workspace or in the workspace container itself



196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/xcodeproj/workspace.rb', line 196

def load_schemes(workspace_dir_path)
  # Normalizes path to directory of workspace needed for file_reference.absolute_path
  workspaces_dir = workspace_dir_path
  if File.extname(workspace_dir_path) == '.xcworkspace'
    workspaces_dir = File.expand_path('..', workspaces_dir)
  end

  file_references.each do |file_reference|
    project_full_path = file_reference.absolute_path(workspaces_dir)
    load_schemes_from_project(project_full_path)
  end

  # Load schemes that are in the workspace container.
  workspace_abs_path = File.absolute_path(workspace_dir_path)
  Dir[File.join(workspace_dir_path, 'xcshareddata', 'xcschemes', '*.xcscheme')].each do |scheme|
    scheme_name = File.basename(scheme, '.xcscheme')
    @schemes[scheme_name] = workspace_abs_path
  end
end

#save_as(path) ⇒ void

This method returns an undefined value.

Saves the workspace at the given ‘xcworkspace` path.



180
181
182
183
184
185
# File 'lib/xcodeproj/workspace.rb', line 180

def save_as(path)
  FileUtils.mkdir_p(path)
  File.open(File.join(path, 'contents.xcworkspacedata'), 'w') do |out|
    out << to_s
  end
end

#to_sString



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/xcodeproj/workspace.rb', line 150

def to_s
  contents = ''
  stack = []
  @document.root.each_recursive do |elem|
    until stack.empty?
      last = stack.last
      break if last == elem.parent
      contents += xcworkspace_element_end_xml(stack.length, last)
      stack.pop
    end

    stack << elem
    contents += xcworkspace_element_start_xml(stack.length, elem)
  end

  until stack.empty?
    contents += xcworkspace_element_end_xml(stack.length, stack.last)
    stack.pop
  end

  root_xml(contents)
end