From 04bdbae220fc59b1df2e832ffc2cc9810f74a25d Mon Sep 17 00:00:00 2001 From: Danielle Tomlinson Date: Sat, 24 Sep 2016 15:21:43 +0200 Subject: [PATCH 1/4] [FFI] Make Chdir Chdir again. The world is sadness. --- CHANGELOG.md | 4 ++- lib/xcodeproj/plist/ffi.rb | 38 +++++------------------ lib/xcodeproj/plist/ffi/chdir_override.rb | 27 ++++++++++++++++ spec/project_spec.rb | 9 ++++++ 4 files changed, 46 insertions(+), 32 deletions(-) create mode 100644 lib/xcodeproj/plist/ffi/chdir_override.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index 7bd6c47a5..69fca82a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,9 @@ ##### Bug Fixes -* None. +* Cover more cases of the Dir.chdir breakages. + [Danielle Tomlinson](https://github.com/dantoml) + [#]() ## 1.3.1 (2016-09-10) diff --git a/lib/xcodeproj/plist/ffi.rb b/lib/xcodeproj/plist/ffi.rb index 881bc854b..488ae32fc 100644 --- a/lib/xcodeproj/plist/ffi.rb +++ b/lib/xcodeproj/plist/ffi.rb @@ -1,35 +1,6 @@ + module Xcodeproj module Plist - module Extensions - # Since Xcode 8 beta 4, calling `PBXProject.projectWithFile` breaks subsequent calls to - # `chdir`. While sounding ridiculous, this is unfortunately true and debugging it from the - # userland side showed no difference at all to successful calls to `chdir`, but the working - # directory is simply not changed in the end. This workaround is even more absurd, monkey - # patching all calls to `chdir` to use `__pthread_chdir` which appears to work. - module Dir - def self.chdir(path) - old_dir = Dir.getwd - res = actually_chdir(path) - - if block_given? - begin - return yield - ensure - actually_chdir(old_dir) - end - end - - res - end - - def self.actually_chdir(path) - libc = Fiddle.dlopen '/usr/lib/libc.dylib' - f = Fiddle::Function.new(libc['__pthread_chdir'], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT) - f.call(path.to_s) - end - end - end - # Provides support for loading and serializing property list files via # Fiddle and CoreFoundation / Xcode. # @@ -171,7 +142,12 @@ def ruby_hash_write_devtoolscore(hash, path) end def monkey_patch_chdir - Dir.send(:include, Extensions::Dir) + require 'xcodeproj/plist/ffi/chdir_override' + Dir.class_eval do + class << Dir + alias_method :chdir, :cp_chdir + end + end end end end diff --git a/lib/xcodeproj/plist/ffi/chdir_override.rb b/lib/xcodeproj/plist/ffi/chdir_override.rb new file mode 100644 index 000000000..22910b5fc --- /dev/null +++ b/lib/xcodeproj/plist/ffi/chdir_override.rb @@ -0,0 +1,27 @@ +# Since Xcode 8 beta 4, calling `PBXProject.projectWithFile` breaks subsequent calls to +# `chdir`. While sounding ridiculous, this is unfortunately true and debugging it from the +# userland side showed no difference at all to successful calls to `chdir`, but the working +# directory is simply not changed in the end. This workaround is even more absurd, monkey +# patching all calls to `chdir` to use `__pthread_chdir` which appears to work. +class Dir + def self.cp_chdir(path) + old_dir = Dir.getwd + res = actually_chdir(path) + + if block_given? + begin + return yield + ensure + actually_chdir(old_dir) + end + end + + res + end + + def self.cp_actually_chdir(path) + libc = Fiddle.dlopen '/usr/lib/libc.dylib' + f = Fiddle::Function.new(libc['__pthread_chdir'], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT) + f.call(path.to_s) + end +end diff --git a/spec/project_spec.rb b/spec/project_spec.rb index b84620f99..f840ec8d9 100644 --- a/spec/project_spec.rb +++ b/spec/project_spec.rb @@ -87,6 +87,15 @@ module ProjectSpecs @project = Xcodeproj::Project.open(@path) end + it 'does not break the chdir system call' do + require 'pathname' + Dir.mktmpdir do |dir| + Dir.chdir(dir) do + Pathname(dir).realpath.to_s.should == Dir.getwd + end + end + end + it 'sets itself as the owner of the root object' do # The root object might be referenced by other objects like # the PBXContainerItemProxy From 5fd7af9ebf549306ad2b7990968d1a2883f31471 Mon Sep 17 00:00:00 2001 From: Danielle Tomlinson Date: Sat, 24 Sep 2016 22:22:40 +0200 Subject: [PATCH 2/4] Don't class_eval --- lib/xcodeproj/plist/ffi.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/xcodeproj/plist/ffi.rb b/lib/xcodeproj/plist/ffi.rb index 488ae32fc..0b67557be 100644 --- a/lib/xcodeproj/plist/ffi.rb +++ b/lib/xcodeproj/plist/ffi.rb @@ -143,10 +143,8 @@ def ruby_hash_write_devtoolscore(hash, path) def monkey_patch_chdir require 'xcodeproj/plist/ffi/chdir_override' - Dir.class_eval do - class << Dir - alias_method :chdir, :cp_chdir - end + class << Dir + alias_method :chdir, :cp_chdir end end end From 7994f7e50e596f3ef0e07277dc4ee0cc32021824 Mon Sep 17 00:00:00 2001 From: Danielle Tomlinson Date: Sat, 24 Sep 2016 23:25:10 +0200 Subject: [PATCH 3/4] Prefix actually_chdir --- lib/xcodeproj/plist/ffi/chdir_override.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/xcodeproj/plist/ffi/chdir_override.rb b/lib/xcodeproj/plist/ffi/chdir_override.rb index 22910b5fc..86f66aa84 100644 --- a/lib/xcodeproj/plist/ffi/chdir_override.rb +++ b/lib/xcodeproj/plist/ffi/chdir_override.rb @@ -6,13 +6,13 @@ class Dir def self.cp_chdir(path) old_dir = Dir.getwd - res = actually_chdir(path) + res = cp_actually_chdir(path) if block_given? begin return yield ensure - actually_chdir(old_dir) + cp_actually_chdir(old_dir) end end From 1b48366de81e35f9d50afe7d56249e0fb5633b1a Mon Sep 17 00:00:00 2001 From: Danielle Tomlinson Date: Sun, 25 Sep 2016 18:53:51 +0200 Subject: [PATCH 4/4] Add PR ID to CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 69fca82a5..c93b81ca4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ * Cover more cases of the Dir.chdir breakages. [Danielle Tomlinson](https://github.com/dantoml) - [#]() + [#421](https://github.com/CocoaPods/Xcodeproj/pull/421) ## 1.3.1 (2016-09-10)