Class: Zimt::PBXProj

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

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(file) ⇒ PBXProj

Returns a new instance of PBXProj.



50
51
52
53
54
# File 'lib/zimt/pbxproj.rb', line 50

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

Instance Attribute Details

#contentObject (readonly)

Returns the value of attribute content.



47
48
49
# File 'lib/zimt/pbxproj.rb', line 47

def content
  @content
end

#hashObject (readonly)

Returns the value of attribute hash.



47
48
49
# File 'lib/zimt/pbxproj.rb', line 47

def hash
  @hash
end

#objectsObject (readonly)

Returns the value of attribute objects.



47
48
49
# File 'lib/zimt/pbxproj.rb', line 47

def objects
  @objects
end

#positionObject

Returns the value of attribute position.



48
49
50
# File 'lib/zimt/pbxproj.rb', line 48

def position
  @position
end

#rootObject (readonly)

Returns the value of attribute root.



47
48
49
# File 'lib/zimt/pbxproj.rb', line 47

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) ⇒ Object

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



182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
# File 'lib/zimt/pbxproj.rb', line 182

def add_buildfile(file, fileref)
  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 Sources */ = {isa = PBXBuildFile; fileRef = #{fileref} /* #{file} */; };\n")

  self.save!
  self.parse
  return newgroup
end

#add_buildfileref_to_build_phase(file, buildfileref) ⇒ Object

/* Begin PBXSourcesBuildPhase section */ 8D11072C0486CEB800E47090 /* Sources */ = { files = ( C53D93B21406F98300F4CDDE /* Hans.m in Sources */, ); C56D96C81385E71800070608 /* Sources */ = { /* End PBXSourcesBuildPhase 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
# File 'lib/zimt/pbxproj.rb', line 217

def add_buildfileref_to_build_phase(file, buildfileref)
  @position = 0
  scan_to "/* Begin PBXSourcesBuildPhase section */"
  begin_position = @position
  scan_to "/* End PBXSourcesBuildPhase 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 Sources */,\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 */



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/zimt/pbxproj.rb', line 134

def add_file(file, file_type)
  zimt_group_id = self.zimt_group.pbxid
  # Add file to Zimt group
  groupid = self.root.mainGroup.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

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

  self.save!
  self.parse
  return newgroup
end

#add_h_file(file) ⇒ Object



169
170
171
# File 'lib/zimt/pbxproj.rb', line 169

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

#add_m_file(file) ⇒ Object



173
174
175
176
177
# File 'lib/zimt/pbxproj.rb', line 173

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

#add_zimt_groupObject

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



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
# File 'lib/zimt/pbxproj.rb', line 90

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



256
257
258
259
# File 'lib/zimt/pbxproj.rb', line 256

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

#ensure_zimt_groupObject



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

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

#parseObject



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

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



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

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

#scan_to(what) ⇒ Object



242
243
244
245
246
247
248
249
250
251
252
253
254
# File 'lib/zimt/pbxproj.rb', line 242

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)



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/zimt/pbxproj.rb', line 30

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

#zimt_groupObject



68
69
70
# File 'lib/zimt/pbxproj.rb', line 68

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