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

Make chdir chdir again? #421

Merged
merged 4 commits into from
Sep 26, 2016
Merged
Show file tree
Hide file tree
Changes from 3 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
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@

##### Bug Fixes

* None.
* Cover more cases of the Dir.chdir breakages.
[Danielle Tomlinson](https://github.com/dantoml)
[#]()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you have a PR ID now



## 1.3.1 (2016-09-10)
Expand Down
36 changes: 5 additions & 31 deletions lib/xcodeproj/plist/ffi.rb
Original file line number Diff line number Diff line change
@@ -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.
#
Expand Down Expand Up @@ -171,7 +142,10 @@ def ruby_hash_write_devtoolscore(hash, path)
end

def monkey_patch_chdir
Dir.send(:include, Extensions::Dir)
require 'xcodeproj/plist/ffi/chdir_override'
class << Dir
alias_method :chdir, :cp_chdir
end
end
end
end
Expand Down
27 changes: 27 additions & 0 deletions lib/xcodeproj/plist/ffi/chdir_override.rb
Original file line number Diff line number Diff line change
@@ -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 = cp_actually_chdir(path)

if block_given?
begin
return yield
ensure
cp_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
9 changes: 9 additions & 0 deletions spec/project_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down