xcodeproj 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
-