40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
# File 'lib/cocoapods-pack/find_follow.rb', line 40
def find_follow(*paths)
block_given? || (return enum_for(__method__, *paths))
link_cache = {}
link_resolve = lambda { |path|
return link_cache[path] if link_cache[path]
return link_cache[path] = Pathname.new(path).realpath.to_s
}
link_cache_reset = lambda { |path|
link_cache.select! do |k, _v|
path == k || k == '/' || path.start_with?(k + '/')
end
}
link_is_recursive = lambda { |path|
pn_initial = Pathname.new(path)
unless pn_initial.absolute?
pn_initial = Pathname.new(File.join(Dir.pwd, path))
end
link_cache_reset.call(pn_initial.to_s)
link_dst = link_resolve.call(pn_initial.to_s)
pn_initial.ascend do |pn|
return { link: path, dst: pn } if pn != pn_initial && link_dst == link_resolve.call(pn.to_s)
end
return false
}
do_find = proc { |path|
Find.find(path) do |result|
if File.symlink?(result) && File.directory?(File.realpath(result))
if result[-1] == '/'
yield(result.dup)
Dir.new(result).each do |subpath|
do_find.call(result + subpath) unless ['.', '..'].include?(subpath)
end
elsif is_recursive = link_is_recursive.call(result)
raise "cannot handle recursive links: #{is_recursive[:link]} => #{is_recursive[:dst]}"
else
do_find.call(result + '/')
end
else
yield(result)
end
end
}
while path = paths.shift
do_find.call(path)
end
end
|