Class: Zimt::PBXProj

Inherits:
Object
  • Object
show all
Defined in:
lib/zimt/pbxproj.rb

Constant Summary collapse

FILE_FORMATS =
{ '.png' => 'image.png',
'.plist' => 'text.plist.xml' }

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(file) ⇒ PBXProj

Returns a new instance of PBXProj.



57
58
59
60
61
# File 'lib/zimt/pbxproj.rb', line 57

def initialize(file)
  @filename = file
  @content = File.readlines(file)
  self.parse
end

Instance Attribute Details

#contentObject (readonly)

Returns the value of attribute content.



54
55
56
# File 'lib/zimt/pbxproj.rb', line 54

def content
  @content
end

#hashObject (readonly)

Returns the value of attribute hash.



54
55
56
# File 'lib/zimt/pbxproj.rb', line 54

def hash
  @hash
end

#objectsObject (readonly)

Returns the value of attribute objects.



54
55
56
# File 'lib/zimt/pbxproj.rb', line 54

def objects
  @objects
end

#positionObject

Returns the value of attribute position.



55
56
57
# File 'lib/zimt/pbxproj.rb', line 55

def position
  @position
end

#rootObject (readonly)

Returns the value of attribute root.



54
55
56
# File 'lib/zimt/pbxproj.rb', line 54

def root
  @root
end

Class Method Details

.plutil(file) ⇒ Object



3
4
5
# File 'lib/zimt/pbxproj.rb', line 3

def self.plutil(file)
  `plutil -convert json -o - #{file}`
end

Instance Method Details

#add_buildfile(file, fileref, filetype) ⇒ Object

/* Begin PBXBuildFile section */ C53D93B21406F98300F4CDDE /* Hans.m in Sources */ = {isa = PBXBuildFile; fileRef = C53D93B11406F98300F4CDDE /* Hans.m */; }; /* End PBXBuildFile section */



217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/zimt/pbxproj.rb', line 217

def add_buildfile(file, fileref, filetype)
  newgroup = self.uuid
  # Find position for Zimt reference in PBXGRoup section
  @position = 0
  scan_to "/* Begin PBXBuildFile section */"
  begin_position = @position
  scan_to "/* End PBXBuildFile section */"
  end_position = @position

  @position = begin_position
  while @position < end_position
    line = self.content[@position]
    groupname = line.split(' ')[0]
    if groupname > newgroup
      break
    end
    @position += 1
  end

  # Add Zimt Group
  self.content.insert(@position,
                      "\t\t#{newgroup} /* #{file} in #{filetype} */ = {isa = PBXBuildFile; fileRef = #{fileref} /* #{file} */; };\n")

  self.save!
  self.parse
  return newgroup
end

#add_buildfileref_to_build_phase(file, buildfileref, phase_name) ⇒ Object

/* Begin PBXSourcesBuildPhase section */ 8D11072C0486CEB800E47090 /* Sources */ = { files = ( C53D93B21406F98300F4CDDE /* Hans.m in Sources */, ); C56D96C81385E71800070608 /* Sources */ = { /* End PBXSourcesBuildPhase section */



252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
# File 'lib/zimt/pbxproj.rb', line 252

def add_buildfileref_to_build_phase(file, buildfileref, phase_name)
  @position = 0
  scan_to "/* Begin PBX#{phase_name}BuildPhase section */"
  begin_position = @position
  scan_to "/* End PBX#{phase_name}BuildPhase section */"
  end_position = @position

  @position = begin_position
  while @position < end_position
    line = self.content[@position]
    if (line.end_with? " = {\n")
      old_position = @position
      scan_to("			);\n")
      self.content.insert(@position,
                          "				#{buildfileref} /* #{file} in #{phase_name} */,\n")
      @position = old_position + 1 # offset for added line
      break
    end
    @position += 1
  end

  self.save!
  self.parse
end

#add_file(file, file_type) ⇒ Object

/* Begin PBXFileReference section */ C5D0CB021406C3AA002E631F /* Hans.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Hans.h; sourceTree = “<group>”; }; /* End PBXFileReference section */



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/zimt/pbxproj.rb', line 155

def add_file(file, file_type)
  @position = 0
  # Add file to Zimt group
  zimt_group_id = self.zimt_group.pbxid
  scan_to "\t\t#{zimt_group_id}"
  scan_to "\t\t\t);"
  newgroup = self.uuid
  self.content.insert(@position, "\t\t\t\t#{newgroup} /* #{file} */,\n")

  # Find position for Zimt reference in PBXGRoup section
  @position = 0
  scan_to "/* Begin PBXFileReference section */"
  begin_position = @position
  scan_to "/* End PBXFileReference section */"
  end_position = @position

  @position = begin_position
  while @position < end_position
    line = self.content[@position]
    groupname = line.split(' ')[0]
    if groupname > newgroup
      break
    end
    @position += 1
  end

  # Escape filename
  if not file.match /^[A-Za-z0-9.]+$/
    escaped_file = "\"#{file}\""
  else
    escaped_file = file
  end

  # Add Zimt Group
  self.content.insert(@position,
                      "\t\t#{newgroup} /* #{file} */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = #{file_type}; path = #{escaped_file}; sourceTree = \"<group>\"; };\n")

  self.save!
  self.parse
  return newgroup
end

#add_h_file(file) ⇒ Object



197
198
199
# File 'lib/zimt/pbxproj.rb', line 197

def add_h_file(file)
  add_file(file, "sourcecode.c.h")
end

#add_m_file(file) ⇒ Object



201
202
203
204
205
# File 'lib/zimt/pbxproj.rb', line 201

def add_m_file(file)
  fileref = self.add_file(file, "sourcecode.c.objc")
  buildfileref = self.add_buildfile(file, fileref, "Sources")
  add_buildfileref_to_build_phase(file, buildfileref, "Sources")
end

#add_resource_file(file) ⇒ Object



207
208
209
210
211
212
# File 'lib/zimt/pbxproj.rb', line 207

def add_resource_file(file)
  file_type = FILE_FORMATS[Pathname.new(file).extname.downcase] || 'text'
  fileref = self.add_file(file, file_type)
  buildfileref = self.add_buildfile(file, fileref, "Resources")
  add_buildfileref_to_build_phase(file, buildfileref, "Resources")
end

#add_zimt_groupObject

C5FE9B6F13BA7537004CCA66 = { isa = PBXGroup; children = ( C5FE9B8413BA7537004CCA66 /* Sources */, C7826AD313D9137D00661EEC /* Resources */, C5FE9B7D13BA7537004CCA66 /* Frameworks */, C5FE9B7B13BA7537004CCA66 /* Products */, C5E20A8613F4507D00C5DDF3 /* Zimt */, ); sourceTree = “<group>”; };



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
148
149
150
# File 'lib/zimt/pbxproj.rb', line 111

def add_zimt_group
  # Add Zimt reference to mainGroup
  groupid = self.root.mainGroup.pbxid
  scan_to "\t\t#{groupid}"
  scan_to "\t\t\t);"
  newgroup = self.uuid
  self.content.insert(@position, "\t\t\t\t#{newgroup} /* Zimt */,\n")

  # Find position for Zimt reference in PBXGRoup section
  @position = 0
  scan_to "/* Begin PBXGroup section */"
  begin_position = @position
  scan_to "/* End PBXGroup section */"
  end_position = @position

  @position = begin_position
  while @position < end_position
    line = self.content[@position]
    if (line.end_with? " = {\n")
      groupname = line.split(' ')[0]
      if groupname > newgroup
        break
      end
    end
    @position += 1
  end

  # Add Zimt Group
  self.content.insert(@position,
                      "\t\t#{newgroup} /* Zimt */ = {\n",
                      "\t\t\tisa = PBXGroup;\n",
                      "\t\t\tchildren = (\n",
                      "\t\t\t);\n",
                      "\t\t\tpath = Zimt;\n",
                      "\t\t\tsourceTree = \"<group>\";\n",
                      "\t\t};\n")

  self.save!
  self.parse
end

#current_lineObject



291
292
293
294
# File 'lib/zimt/pbxproj.rb', line 291

def current_line
  @position ||= 0
  self.content[@position]
end

#ensure_license_fileObject



84
85
86
87
88
89
90
91
# File 'lib/zimt/pbxproj.rb', line 84

def ensure_license_file
  self.ensure_zimt_group
  FileUtils.mkdir "Zimt" if not File.exists? "Zimt"
  if self.license_file.first.nil?
    self.add_resource_file('3rdPartyLicenses.txt')
    FileUtils.touch('Zimt/3rdPartyLicenses.txt')
  end
end

#ensure_zimt_groupObject



93
94
95
96
97
98
# File 'lib/zimt/pbxproj.rb', line 93

def ensure_zimt_group
  zimt_group = self.zimt_group
  if zimt_group.nil?
    self.add_zimt_group
  end
end

#license_fileObject



79
80
81
82
# File 'lib/zimt/pbxproj.rb', line 79

def license_file
  return unless self.zimt_group
  self.zimt_group.children.select { |g| g.path == '3rdPartyLicenses.txt' }
end

#parseObject



63
64
65
66
67
# File 'lib/zimt/pbxproj.rb', line 63

def parse
  @hash = JSON.parse(PBXProj.plutil(@filename)).freeze
  @objects = @hash['objects']
  @root = PBXHash.new(self, @hash['rootObject'], @objects[@hash['rootObject']])
end

#randhex(length = 1) ⇒ Object



7
8
9
10
11
12
13
# File 'lib/zimt/pbxproj.rb', line 7

def randhex(length=1)
  @buffer = ""
  length.times do
    @buffer << rand(16).to_s(16).upcase
  end
  @buffer
end

#save!Object



69
70
71
72
73
# File 'lib/zimt/pbxproj.rb', line 69

def save!
  File.open(@filename, "w") { |f|
    f.write(self.content.join(''))
  }
end

#scan_to(what) ⇒ Object



277
278
279
280
281
282
283
284
285
286
287
288
289
# File 'lib/zimt/pbxproj.rb', line 277

def scan_to(what)
  @position ||= 0
  while true
    line = self.content[@position]
    if line.nil?
      raise "#{what} not found"
    end
    if line.start_with? what
      return
    end
    @position += 1
  end
end

#uuidObject

Documentation on PBXObjectId by @tjw lists.apple.com/archives/projectbuilder-users/2003/Jan/msg00263.html

ObjectId gets generated in the following format: ---------------------------------------------------------------------- | RANDOM | SEQ | TIME | PID | IP (2) | | byte byte | byte byte | byte byte byte byte | byte byte | byte byte | ---------------------------------------------------------------------- RANDOM = 2 bytes of random number for distribution SEQ = Unsigned short sequence counter that starts randomly. TIME = Seconds since epoch (1/1/1970) PID = Process ID

This is only two bytes even though most pids are longs.
Here you would take the lower 2 bytes.

IP = IP Address of the machine (subnet.hostId)



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/zimt/pbxproj.rb', line 34

def uuid
  # TODO
  @prefix ||= randhex(4)
  @suffix ||= randhex(16)
  @count ||= randhex(4).to_i(16)
  @count += 1
  if @count.to_s(16).length > 4
    @count = randhex(4).to_i(16)
  end
  uuid = "#{@prefix}#{@count.to_s(16).upcase}#{@suffix}"
  if uuid.length != 24
    puts "uuid length wrong: #{uuid}"
    puts @prefix
    puts @suffix
    puts @count
    exit
  end
  uuid
end

#zimt_groupObject



75
76
77
# File 'lib/zimt/pbxproj.rb', line 75

def zimt_group
  self.root.mainGroup.children.select{ |g| g.path == 'Zimt' }.first
end