xcodeproj 0.0.2 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2011 Eloy Durán <eloy.de.enige@gmail.com>
1
+ Copyright (c) 2012 Eloy Durán <eloy.de.enige@gmail.com>
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # Xcodeproj
2
2
 
3
- Xcodeproj lets you create and modify Xcode projects from [MacRuby][macruby].
3
+ [![Build Status](https://secure.travis-ci.org/CocoaPods/Xcodeproj.png)](https://secure.travis-ci.org/CocoaPods/Xcodeproj)
4
+
5
+ Xcodeproj lets you create and modify Xcode projects from [Ruby][ruby].
4
6
  Script boring management tasks or build Xcode-friendly libraries. Also includes
5
7
  support for Xcode workspaces (.xcworkspace) and configuration files (.xcconfig).
6
8
 
@@ -10,16 +12,10 @@ static library from scratch, for both iOS and OSX.
10
12
 
11
13
  ## Installing Xcodeproj
12
14
 
13
- You’ll need MacRuby. xcodeproj itself installs through RubyGems, the Ruby
14
- package manager. Download and install [version 0.10][macruby-dl] and then
15
- perform the following command:
16
-
17
- $ sudo macgem install xcodeproj
18
-
19
- The load time can be improved a bit by compiling the Ruby source files:
15
+ Xcodeproj itself installs through RubyGems, the Ruby package manager. Install it
16
+ by performing the following command:
20
17
 
21
- $ sudo macgem install rubygems-compile
22
- $ sudo macgem compile xcodeproj
18
+ $ sudo gem install xcodeproj
23
19
 
24
20
 
25
21
  ## Colaborate
@@ -35,9 +31,11 @@ If you're really oldschool and you want to discuss Xcodeproj development you
35
31
  can join #cocoapods on irc.freenode.net.
36
32
 
37
33
 
38
- ## Contributors
34
+ ## Authors
39
35
 
40
36
  * [Nolan Waite](https://github.com/nolanw)
37
+ * [Luke Redpath](https://github.com/lukeredpath)
38
+ * [Eloy Durán](https://github.com/alloy)
41
39
 
42
40
 
43
41
  ## LICENSE
@@ -49,8 +47,7 @@ Included in this package is the [inflector part of ActiveSupport][activesupport]
49
47
  which is also available under the MIT license.
50
48
 
51
49
  [twitter]: http://twitter.com/CocoaPodsOrg
52
- [macruby]: http://www.macruby.org
53
- [macruby-dl]: http://www.macruby.org/files
50
+ [ruby]: http://www.ruby-lang.org/en/
54
51
  [xcodeproj]: https://github.com/cocoapods/xcodeproj
55
52
  [tickets]: https://github.com/cocoapods/xcodeproj/issues
56
53
  [license]: xcodeproj/blob/master/LICENSE
@@ -0,0 +1,42 @@
1
+ require 'mkmf'
2
+
3
+ # backport from 1.9.x
4
+ unless defined?(have_framework) == "method"
5
+ def have_framework(fw, &b)
6
+ checking_for fw do
7
+ src = cpp_include("#{fw}/#{fw}.h") << "\n" "int main(void){return 0;}"
8
+ if try_link(src, opt = "-ObjC -framework #{fw}", &b)
9
+ $defs.push(format("-DHAVE_FRAMEWORK_%s", fw.tr_cpp))
10
+ $LDFLAGS << " " << opt
11
+ true
12
+ else
13
+ false
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ # Ensure that we can actually set the -std flag
20
+ $CFLAGS = $CFLAGS.sub('$(cflags) ', '')
21
+ $CFLAGS += ' ' + ENV['CFLAGS'] if ENV['CFLAGS']
22
+
23
+ checking_for "-std=c99 option to compiler" do
24
+ $CFLAGS += " -std=c99" if try_compile '', '-std=c99'
25
+ end
26
+
27
+ unless have_framework('CoreFoundation')
28
+ if have_library('CoreFoundation')
29
+ # this is needed for opencflite, assume it's on linux
30
+ $defs << '-DTARGET_OS_LINUX'
31
+ else
32
+ $stderr.puts "CoreFoundation is needed to build the Xcodeproj C extension."
33
+ exit -1
34
+ end
35
+ end
36
+
37
+ have_header 'CoreFoundation/CoreFoundation.h'
38
+ have_header 'CoreFoundation/CFStream.h'
39
+ have_header 'CoreFoundation/CFPropertyList.h'
40
+
41
+ create_header
42
+ create_makefile 'xcodeproj_ext'
@@ -0,0 +1,201 @@
1
+ // TODO
2
+ // * free memory when raising
3
+
4
+ #include "extconf.h"
5
+
6
+ #include "ruby.h"
7
+ #include "ruby/st.h"
8
+ #include "CoreFoundation/CoreFoundation.h"
9
+ #include "CoreFoundation/CFStream.h"
10
+ #include "CoreFoundation/CFPropertyList.h"
11
+
12
+ VALUE Xcodeproj = Qnil;
13
+
14
+
15
+ static VALUE
16
+ cfstr_to_str(const void *cfstr) {
17
+ long len = (long)CFStringGetLength(cfstr);
18
+ char *buf = (char *)malloc(len+1);
19
+ assert(buf != NULL);
20
+ CFStringGetCString(cfstr, buf, len+1, kCFStringEncodingUTF8);
21
+ register VALUE str = rb_str_new(buf, len);
22
+ free(buf);
23
+ return str;
24
+ }
25
+
26
+ // Coerces to String as well.
27
+ static CFStringRef
28
+ str_to_cfstr(VALUE str) {
29
+ return CFStringCreateWithCString(NULL, RSTRING_PTR(rb_String(str)), kCFStringEncodingUTF8);
30
+ }
31
+
32
+
33
+ static VALUE
34
+ generate_uuid(void) {
35
+ CFUUIDRef uuid = CFUUIDCreate(NULL);
36
+ CFStringRef strRef = CFUUIDCreateString(NULL, uuid);
37
+ CFRelease(uuid);
38
+
39
+ CFArrayRef components = CFStringCreateArrayBySeparatingStrings(NULL, strRef, CFSTR("-"));
40
+ CFRelease(strRef);
41
+ strRef = CFStringCreateByCombiningStrings(NULL, components, CFSTR(""));
42
+ CFRelease(components);
43
+
44
+ UniChar buffer[24];
45
+ CFStringGetCharacters(strRef, CFRangeMake(0, 24), buffer);
46
+ CFStringRef strRef2 = CFStringCreateWithCharacters(NULL, buffer, 24);
47
+
48
+ VALUE str = cfstr_to_str(strRef2);
49
+ CFRelease(strRef);
50
+ CFRelease(strRef2);
51
+ return str;
52
+ }
53
+
54
+
55
+ static void
56
+ hash_set(const void *keyRef, const void *valueRef, void *hash) {
57
+ VALUE key = cfstr_to_str(keyRef);
58
+ register VALUE value = Qnil;
59
+
60
+ CFTypeID valueType = CFGetTypeID(valueRef);
61
+ if (valueType == CFStringGetTypeID()) {
62
+ value = cfstr_to_str(valueRef);
63
+
64
+ } else if (valueType == CFDictionaryGetTypeID()) {
65
+ value = rb_hash_new();
66
+ CFDictionaryApplyFunction(valueRef, hash_set, (void *)value);
67
+
68
+ } else if (valueType == CFArrayGetTypeID()) {
69
+ value = rb_ary_new();
70
+ CFIndex i, count = CFArrayGetCount(valueRef);
71
+ for (i = 0; i < count; i++) {
72
+ CFStringRef x = CFArrayGetValueAtIndex(valueRef, i);
73
+ if (CFGetTypeID(x) == CFStringGetTypeID()) {
74
+ rb_ary_push(value, cfstr_to_str(x));
75
+ } else {
76
+ rb_raise(rb_eTypeError, "Plist array value contains a object type unsupported by Xcodeproj.");
77
+ }
78
+ }
79
+
80
+ } else {
81
+ rb_raise(rb_eTypeError, "Plist contains a hash value object type unsupported by Xcodeproj.");
82
+ }
83
+
84
+ rb_hash_aset((VALUE)hash, key, value);
85
+ }
86
+
87
+ static int
88
+ dictionary_set(st_data_t key, st_data_t value, CFMutableDictionaryRef dict) {
89
+ CFStringRef keyRef = str_to_cfstr(key);
90
+
91
+ CFTypeRef valueRef = NULL;
92
+ if (TYPE(value) == T_HASH) {
93
+ valueRef = CFDictionaryCreateMutable(NULL,
94
+ 0,
95
+ &kCFTypeDictionaryKeyCallBacks,
96
+ &kCFTypeDictionaryValueCallBacks);
97
+ st_foreach(RHASH_TBL(value), dictionary_set, (st_data_t)valueRef);
98
+
99
+ } else if (TYPE(value) == T_ARRAY) {
100
+ long i, count = RARRAY_LEN(value);
101
+ valueRef = CFArrayCreateMutable(NULL, count, &kCFTypeArrayCallBacks);
102
+ for (i = 0; i < count; i++) {
103
+ CFStringRef x = str_to_cfstr(RARRAY_PTR(value)[i]);
104
+ CFArrayAppendValue((CFMutableArrayRef)valueRef, x);
105
+ CFRelease(x);
106
+ }
107
+
108
+ } else {
109
+ valueRef = str_to_cfstr(value);
110
+ }
111
+
112
+ CFDictionaryAddValue(dict, keyRef, valueRef);
113
+ CFRelease(keyRef);
114
+ CFRelease(valueRef);
115
+ return ST_CONTINUE;
116
+ }
117
+
118
+ static CFURLRef
119
+ str_to_url(VALUE path) {
120
+ #ifdef FilePathValue
121
+ VALUE p = FilePathValue(path);
122
+ #else
123
+ VALUE p = rb_String(path);
124
+ #endif
125
+ CFURLRef fileURL = CFURLCreateFromFileSystemRepresentation(NULL, RSTRING_PTR(p), RSTRING_LEN(p), false);
126
+ if (!fileURL) {
127
+ rb_raise(rb_eArgError, "Unable to create CFURL from `%s'.", RSTRING_PTR(rb_inspect(path)));
128
+ }
129
+ return fileURL;
130
+ }
131
+
132
+
133
+ // TODO handle errors
134
+ static VALUE
135
+ read_plist(VALUE self, VALUE path) {
136
+ CFPropertyListRef dict;
137
+ CFStringRef errorString;
138
+ CFDataRef resourceData;
139
+ SInt32 errorCode;
140
+
141
+ CFURLRef fileURL = str_to_url(path);
142
+ if (CFURLCreateDataAndPropertiesFromResource(NULL, fileURL, &resourceData, NULL, NULL, &errorCode)) {
143
+ CFRelease(fileURL);
144
+ }
145
+ if (!resourceData) {
146
+ rb_raise(rb_eArgError, "Unable to read data from `%s'", RSTRING_PTR(rb_inspect(path)));
147
+ }
148
+
149
+ dict = CFPropertyListCreateFromXMLData(NULL, resourceData, kCFPropertyListImmutable, &errorString);
150
+ if (!dict) {
151
+ rb_raise(rb_eArgError, "Unable to read plist data from `%s': %s", RSTRING_PTR(rb_inspect(path)), RSTRING_PTR(cfstr_to_str(errorString)));
152
+ }
153
+ CFRelease(resourceData);
154
+
155
+ register VALUE hash = rb_hash_new();
156
+ CFDictionaryApplyFunction(dict, hash_set, (void *)hash);
157
+ CFRelease(dict);
158
+
159
+ return hash;
160
+ }
161
+
162
+ static VALUE
163
+ write_plist(VALUE self, VALUE hash, VALUE path) {
164
+ VALUE h = rb_check_convert_type(hash, T_HASH, "Hash", "to_hash");
165
+ if (NIL_P(h)) {
166
+ rb_raise(rb_eTypeError, "%s can't be coerced to Hash", rb_obj_classname(hash));
167
+ }
168
+
169
+ CFMutableDictionaryRef dict = CFDictionaryCreateMutable(NULL,
170
+ 0,
171
+ &kCFTypeDictionaryKeyCallBacks,
172
+ &kCFTypeDictionaryValueCallBacks);
173
+
174
+ st_foreach(RHASH_TBL(h), dictionary_set, (st_data_t)dict);
175
+
176
+ CFURLRef fileURL = str_to_url(path);
177
+ CFWriteStreamRef stream = CFWriteStreamCreateWithFile(NULL, fileURL);
178
+ CFRelease(fileURL);
179
+
180
+ CFIndex success = 0;
181
+ if (CFWriteStreamOpen(stream)) {
182
+ CFStringRef errorString;
183
+ success = CFPropertyListWriteToStream(dict, stream, kCFPropertyListXMLFormat_v1_0, &errorString);
184
+ if (!success) {
185
+ CFShow(errorString);
186
+ }
187
+ } else {
188
+ printf("Unable to open stream!\n");
189
+ }
190
+
191
+ CFRelease(dict);
192
+ return success ? Qtrue : Qfalse;
193
+ }
194
+
195
+
196
+ void Init_xcodeproj_ext() {
197
+ Xcodeproj = rb_define_module("Xcodeproj");
198
+ rb_define_singleton_method(Xcodeproj, "generate_uuid", generate_uuid, 0);
199
+ rb_define_singleton_method(Xcodeproj, "read_plist", read_plist, 1);
200
+ rb_define_singleton_method(Xcodeproj, "write_plist", write_plist, 2);
201
+ }
data/lib/xcodeproj.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Xcodeproj
2
- VERSION = '0.0.2'
2
+ VERSION = '0.1.0'
3
3
 
4
4
  autoload :Config, 'xcodeproj/config'
5
5
  autoload :Project, 'xcodeproj/project'
@@ -346,7 +346,7 @@ module Xcodeproj
346
346
  end
347
347
 
348
348
  # String inflections define new methods on the String class to transform names for different purposes.
349
- class NSString
349
+ class String
350
350
  include Xcodeproj::ActiveSupport
351
351
 
352
352
  # Returns the plural form of the word in the string.
@@ -1,6 +1,6 @@
1
- framework 'Foundation'
2
1
  require 'fileutils'
3
2
  require 'xcodeproj/inflector'
3
+ require 'xcodeproj/xcodeproj_ext'
4
4
 
5
5
  module Xcodeproj
6
6
  class Project
@@ -194,12 +194,7 @@ module Xcodeproj
194
194
  private
195
195
 
196
196
  def generate_uuid
197
- _uuid = CFUUIDCreate(nil)
198
- uuid = CFUUIDCreateString(nil, _uuid)
199
- CFRelease(_uuid)
200
- CFMakeCollectable(uuid)
201
- # Xcode's version is actually shorter, not worrying about collisions too much right now.
202
- uuid.gsub('-', '')[0..23]
197
+ Xcodeproj.generate_uuid
203
198
  end
204
199
 
205
200
  def list_by_class(uuids, klass, scoped = nil, &block)
@@ -221,7 +216,7 @@ module Xcodeproj
221
216
  # valid classes in a Xcode project. A new PBXObject subclass is created
222
217
  # for the constant and returned.
223
218
  def self.const_missing(name)
224
- if name =~ /^(PBX|XC)/
219
+ if name.to_s =~ /^(PBX|XC)/
225
220
  klass = Class.new(PBXObject)
226
221
  const_set(name, klass)
227
222
  klass
@@ -534,7 +529,7 @@ module Xcodeproj
534
529
 
535
530
  # Only makes sense on lists that contain mixed classes.
536
531
  def select_by_class(klass)
537
- scoped = @scoped_hash.select { |_, attr| attr['isa'] == klass.isa }
532
+ scoped = Hash[*@scoped_hash.select { |_, attr| attr['isa'] == klass.isa }.flatten]
538
533
  PBXObjectList.new(klass, @project, scoped) do |object|
539
534
  # Objects added to the subselection should still use the same
540
535
  # callback as this list.
@@ -558,7 +553,7 @@ module Xcodeproj
558
553
  def initialize(xcodeproj = nil)
559
554
  if xcodeproj
560
555
  file = File.join(xcodeproj, 'project.pbxproj')
561
- @plist = NSMutableDictionary.dictionaryWithContentsOfFile(file.to_s)
556
+ @plist = Xcodeproj.read_plist(file.to_s)
562
557
  else
563
558
  @plist = {
564
559
  'archiveVersion' => '1',
@@ -658,7 +653,7 @@ module Xcodeproj
658
653
  def save_as(projpath)
659
654
  projpath = projpath.to_s
660
655
  FileUtils.mkdir_p(projpath)
661
- @plist.writeToFile(File.join(projpath, 'project.pbxproj'), atomically:true)
656
+ Xcodeproj.write_plist(@plist, File.join(projpath, 'project.pbxproj'))
662
657
  end
663
658
  end
664
659
  end
@@ -1,12 +1,12 @@
1
- framework 'Foundation'
2
1
  require 'fileutils'
2
+ require 'rexml/document'
3
3
 
4
4
  module Xcodeproj
5
5
  class Workspace
6
6
  def initialize(*projpaths)
7
7
  @projpaths = projpaths
8
8
  end
9
-
9
+
10
10
  def self.new_from_xcworkspace(path)
11
11
  begin
12
12
  from_s(File.read(File.join(path, 'contents.xcworkspacedata')))
@@ -14,36 +14,37 @@ module Xcodeproj
14
14
  new
15
15
  end
16
16
  end
17
-
17
+
18
18
  def self.from_s(xml)
19
- doc = NSXMLDocument.alloc.initWithXMLString(xml, options:0, error:nil)
20
- projpaths = doc.nodesForXPath("/Workspace/FileRef", error:nil).map do |node|
21
- node.attributeForName("location").stringValue.sub(/^group:/, '')
19
+ document = REXML::Document.new(xml)
20
+ projpaths = document.get_elements("/Workspace/FileRef").map do |node|
21
+ node.attribute("location").to_s.sub(/^group:/, '')
22
22
  end
23
23
  new(*projpaths)
24
24
  end
25
-
25
+
26
26
  attr_reader :projpaths
27
-
27
+
28
28
  def <<(projpath)
29
29
  @projpaths << projpath
30
30
  end
31
-
31
+
32
32
  def include?(projpath)
33
33
  @projpaths.include?(projpath)
34
34
  end
35
-
35
+
36
36
  TEMPLATE = %q[<?xml version="1.0" encoding="UTF-8"?><Workspace version="1.0"></Workspace>]
37
+
37
38
  def to_s
38
- doc = NSXMLDocument.alloc.initWithXMLString(TEMPLATE, options:0, error:nil)
39
- @projpaths.each do |projpath|
40
- el = NSXMLNode.elementWithName("FileRef")
41
- el.addAttribute(NSXMLNode.attributeWithName("location", stringValue:"group:#{projpath}"))
42
- doc.rootElement.addChild(el)
43
- end
44
- NSString.alloc.initWithData(doc.XMLData, encoding:NSUTF8StringEncoding)
39
+ REXML::Document.new(TEMPLATE).tap do |document|
40
+ @projpaths.each do |projpath|
41
+ document.root << REXML::Element.new("FileRef").tap do |el|
42
+ el.attributes['location'] = "group:#{projpath}"
43
+ end
44
+ end
45
+ end.to_s
45
46
  end
46
-
47
+
47
48
  def save_as(path)
48
49
  FileUtils.mkdir_p(path)
49
50
  File.open(File.join(path, 'contents.xcworkspacedata'), 'w') do |out|
metadata CHANGED
@@ -1,68 +1,58 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: xcodeproj
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 0
8
- - 2
9
- version: 0.0.2
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
10
6
  platform: ruby
11
- authors:
7
+ authors:
12
8
  - Eloy Duran
13
9
  autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
-
17
- date: 2011-11-10 00:00:00 +01:00
18
- default_executable:
12
+ date: 2011-11-10 00:00:00.000000000 Z
19
13
  dependencies: []
20
-
21
- description: Xcodeproj lets you create and modify Xcode projects from MacRuby. Script boring management tasks or build Xcode-friendly libraries. Also includes support for Xcode workspaces (.xcworkspace) and configuration files (.xcconfig).
14
+ description: Xcodeproj lets you create and modify Xcode projects from MacRuby. Script
15
+ boring management tasks or build Xcode-friendly libraries. Also includes support
16
+ for Xcode workspaces (.xcworkspace) and configuration files (.xcconfig).
22
17
  email: eloy.de.enige@gmail.com
23
18
  executables: []
24
-
25
- extensions: []
26
-
19
+ extensions:
20
+ - ext/xcodeproj/extconf.rb
27
21
  extra_rdoc_files: []
28
-
29
- files:
22
+ files:
30
23
  - lib/xcodeproj/config.rb
31
24
  - lib/xcodeproj/inflector.rb
32
25
  - lib/xcodeproj/project.rb
33
26
  - lib/xcodeproj/workspace.rb
34
27
  - lib/xcodeproj.rb
28
+ - ext/xcodeproj/extconf.rb
29
+ - ext/xcodeproj/xcodeproj_ext.c
35
30
  - README.md
36
31
  - LICENSE
37
- has_rdoc: true
38
32
  homepage: https://github.com/cocoapods/xcodeproj
39
- licenses:
33
+ licenses:
40
34
  - MIT
41
35
  post_install_message:
42
36
  rdoc_options: []
43
-
44
- require_paths:
37
+ require_paths:
38
+ - ext
45
39
  - lib
46
- required_ruby_version: !ruby/object:Gem::Requirement
47
- requirements:
48
- - - ">="
49
- - !ruby/object:Gem::Version
50
- segments:
51
- - 0
52
- version: "0"
53
- required_rubygems_version: !ruby/object:Gem::Requirement
54
- requirements:
55
- - - ">="
56
- - !ruby/object:Gem::Version
57
- segments:
58
- - 0
59
- version: "0"
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ! '>='
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
60
52
  requirements: []
61
-
62
53
  rubyforge_project:
63
- rubygems_version: 1.3.6
54
+ rubygems_version: 1.8.11
64
55
  signing_key:
65
56
  specification_version: 3
66
57
  summary: Create and modify Xcode projects from MacRuby.
67
58
  test_files: []
68
-