Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimisations #216

Merged
merged 7 commits into from
Oct 28, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .rubocop_cocoapods.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ GuardClause:
Next:
Enabled: false

# Arbitrary max lengths for classes simply do not work and enabling this will
# lead to a never ending stream of annoyance and changes.
Metrics/ClassLength:
Enabled: false

#- CocoaPods support for Ruby 1.8.7 ------------------------------------------#

HashSyntax:
Expand Down
5 changes: 0 additions & 5 deletions .rubocop_todo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,6 @@
Metrics/BlockNesting:
Max: 4

# Offense count: 9
# Configuration parameters: CountComments.
Metrics/ClassLength:
Max: 267

# Offense count: 7
Metrics/CyclomaticComplexity:
Max: 14
Expand Down
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
# Xcodeproj Changelog

## 0.20.1

###### Minor Enhancements

* `Project` Make `#==` a fast shallow comparison method, which operates only on
its root object UUID and its path on disk. For full data comparisons, use the
`#eql?` method instead.
[Eloy Durán](https://github.com/alloy)
[Xcodeproj#216](https://github.com/CocoaPods/Xcodeproj/pull/216)

* `NativeTarget` Make adding a target dependency O(1) constant speed.
[Eloy Durán](https://github.com/alloy)
[Xcodeproj#216](https://github.com/CocoaPods/Xcodeproj/pull/216)

* `Object` Cache an object's plist name, which is used very often during project
generation.
[Eloy Durán](https://github.com/alloy)
[Xcodeproj#216](https://github.com/CocoaPods/Xcodeproj/pull/216)


## 0.20.0

###### Breaking
Expand Down
36 changes: 30 additions & 6 deletions lib/xcodeproj/project.rb
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,38 @@ def self.open(path)
#
attr_reader :root_object

# A fast way to see if two {Project} instances refer to the same projects on
# disk. Use this over {#eql?} when you do not need to compare the full data.
#
# This shallow comparison was chosen as the (common) `==` implementation,
# because it was too easy to introduce changes into the Xcodeproj code-base
# that were slower than O(1).
#
# @return [Boolean] whether or not the two `Project` instances refer to the
# same projects on disk, determined solely by {#path} and
# `root_object.uuid` equality.
#
# @todo If ever needed, we could also compare `uuids.sort` instead.
#
def ==(other)
other && path == other.path && root_object.uuid == other.root_object.uuid
end

# Compares the project to another one, or to a plist representation.
#
# @note This operation can be extremely expensive, because it converts a
# `Project` instance to a hash, and should _only_ ever be used to
# determine wether or not the data contents of two `Project` instances
# are completely equal.
#
# To simply determine wether or not two {Project} instances refer to
# the same projects on disk, use the {#==} method instead.
#
# @param [#to_hash] other the object to compare.
#
# @return [Boolean] whether the project is equivalent to the given object.
#
def ==(other)
def eql?(other)
other.respond_to?(:to_hash) && to_hash == other.to_hash
end

Expand All @@ -131,9 +156,9 @@ def to_s

alias_method :inspect, :to_s

# @return [Bool] Whether the xcproj conversion should be disabled. The
# conversion can be disable also via the
# `XCODEPROJ_DISABLE_XCPROJ` environment variable.
# @return [Boolean] Whether the `xcproj` conversion should be disabled. The
# conversion can also be disabled via the `XCODEPROJ_DISABLE_XCPROJ`
# environment variable.
#
attr_accessor :disable_xcproj
def disable_xcproj?
Expand Down Expand Up @@ -174,9 +199,8 @@ def initialize_from_scratch
def initialize_from_file
pbxproj_path = path + 'project.pbxproj'
plist = Xcodeproj.read_plist(pbxproj_path.to_s)
root_object_uuid = plist['rootObject']
root_object.remove_referrer(self) if root_object
@root_object = new_from_plist(root_object_uuid, plist['objects'], self)
@root_object = new_from_plist(plist['rootObject'], plist['objects'], self)
@archive_version = plist['archiveVersion']
@object_version = plist['objectVersion']
@classes = plist['classes']
Expand Down
2 changes: 1 addition & 1 deletion lib/xcodeproj/project/object_attributes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def initialize(type, name, owner)
# attribute.plist_name #=> projectRoot
#
def plist_name
CaseConverter.convert_to_plist(name, :lower)
@plist_name ||= CaseConverter.convert_to_plist(name, :lower)
end

# @return [Array<Class>] the list of the classes accepted by the
Expand Down
4 changes: 3 additions & 1 deletion lib/xcodeproj/project/xcproj_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ def touch(path)
command = "xcproj --project \"#{path}\" touch"
success, output = execute(command)
unless success
message = "xcproj failed to touch the project. Check whether you installation of xcproj is functional.\n\n"
message = 'The `xcproj` tool has failed to touch the project. ' \
'Check whether your installation of `xcproj` is ' \
"functional.\n\n"
message << command << "\n"
message << output
UI.warn(message)
Expand Down
2 changes: 1 addition & 1 deletion spec/helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ module ProjectSpecs
end

it 'initalizes with a project and the targets to diff' do
@differ.project.should == @project
@differ.project.should.eql @project
@differ.target1.should == @target1
@differ.target2.should == @target2
end
Expand Down
2 changes: 1 addition & 1 deletion spec/project/object_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ module ProjectSpecs
end

it 'returns the project' do
@object.project.should == @project
@object.project.should.eql @project
end

it 'returns its UUID' do
Expand Down
4 changes: 2 additions & 2 deletions spec/project_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -166,13 +166,13 @@ module ProjectSpecs
it 'saves the project to the default path' do
@project.save(@tmp_path)
new_instance = Xcodeproj::Project.open(@path)
new_instance.should == @project
new_instance.should.eql @project
end

it 'saves the project to the given path' do
@project.save(@tmp_path)
new_instance = Xcodeproj::Project.open(@tmp_path)
new_instance.should == @project
new_instance.should.eql @project
end

it 'can save a project after removing a subproject' do
Expand Down