launchr 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,189 @@
1
+
2
+ module Launchr
3
+ module ActiveSupport
4
+ # <tt></tt>
5
+ # ActiveSupport::OrderedHash
6
+ #
7
+ # Copyright (c) 2005 David Hansson,
8
+ # Copyright (c) 2007 Mauricio Fernandez, Sam Stephenson
9
+ # Copyright (c) 2008 Steve Purcell, Josh Peek
10
+ # Copyright (c) 2009 Christoffer Sawicki
11
+ #
12
+ # Permission is hereby granted, free of charge, to any person obtaining
13
+ # a copy of this software and associated documentation files (the
14
+ # "Software"), to deal in the Software without restriction, including
15
+ # without limitation the rights to use, copy, modify, merge, publish,
16
+ # distribute, sublicense, and/or sell copies of the Software, and to
17
+ # permit persons to whom the Software is furnished to do so, subject to
18
+ # the following conditions:
19
+ #
20
+ # The above copyright notice and this permission notice shall be
21
+ # included in all copies or substantial portions of the Software.
22
+ #
23
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30
+ #
31
+ class OrderedHash < Hash
32
+ def initialize(*args, &block)
33
+ super
34
+ @keys = []
35
+ end
36
+
37
+ def self.[](*args)
38
+ ordered_hash = new
39
+
40
+ if (args.length == 1 && args.first.is_a?(Array))
41
+ args.first.each do |key_value_pair|
42
+ next unless (key_value_pair.is_a?(Array))
43
+ ordered_hash[key_value_pair[0]] = key_value_pair[1]
44
+ end
45
+
46
+ return ordered_hash
47
+ end
48
+
49
+ unless (args.size % 2 == 0)
50
+ raise ArgumentError.new("odd number of arguments for Hash")
51
+ end
52
+
53
+ args.each_with_index do |val, ind|
54
+ next if (ind % 2 != 0)
55
+ ordered_hash[val] = args[ind + 1]
56
+ end
57
+
58
+ ordered_hash
59
+ end
60
+
61
+ def initialize_copy(other)
62
+ super
63
+ # make a deep copy of keys
64
+ @keys = other.keys
65
+ end
66
+
67
+ def store(key, value)
68
+ @keys << key if !has_key?(key)
69
+ super
70
+ end
71
+
72
+ def []=(key, value)
73
+ @keys << key if !has_key?(key)
74
+ super
75
+ end
76
+
77
+ def delete(key)
78
+ if has_key? key
79
+ index = @keys.index(key)
80
+ @keys.delete_at index
81
+ end
82
+ super
83
+ end
84
+
85
+ def delete_if
86
+ super
87
+ sync_keys!
88
+ self
89
+ end
90
+
91
+ def reject!
92
+ super
93
+ sync_keys!
94
+ self
95
+ end
96
+
97
+ def reject(&block)
98
+ dup.reject!(&block)
99
+ end
100
+
101
+ def keys
102
+ (@keys || []).dup
103
+ end
104
+
105
+ def values
106
+ @keys.collect { |key| self[key] }
107
+ end
108
+
109
+ def to_hash
110
+ self
111
+ end
112
+
113
+ def to_a
114
+ @keys.map { |key| [ key, self[key] ] }
115
+ end
116
+
117
+ def each_key
118
+ @keys.each { |key| yield key }
119
+ end
120
+
121
+ def each_value
122
+ @keys.each { |key| yield self[key]}
123
+ end
124
+
125
+ def each
126
+ @keys.each {|key| yield [key, self[key]]}
127
+ end
128
+
129
+ alias_method :each_pair, :each
130
+
131
+ def clear
132
+ super
133
+ @keys.clear
134
+ self
135
+ end
136
+
137
+ def shift
138
+ k = @keys.first
139
+ v = delete(k)
140
+ [k, v]
141
+ end
142
+
143
+ def merge!(other_hash)
144
+ other_hash.each {|k,v| self[k] = v }
145
+ self
146
+ end
147
+
148
+ def merge(other_hash)
149
+ dup.merge!(other_hash)
150
+ end
151
+
152
+ # When replacing with another hash, the initial order of our keys must come from the other hash -ordered or not.
153
+ def replace(other)
154
+ super
155
+ @keys = other.keys
156
+ self
157
+ end
158
+
159
+ def inspect
160
+ "#<OrderedHash #{super}>"
161
+ end
162
+
163
+ private
164
+
165
+ def sync_keys!
166
+ @keys.delete_if {|k| !has_key?(k)}
167
+ end
168
+ end
169
+ end
170
+ end
171
+
172
+ module Launchr
173
+ if RUBY_VERSION >= '1.9'
174
+ # Inheritance
175
+ # Ruby 1.9 < Hash
176
+ # Ruby 1.8 < ActiveSupport::OrderedHash
177
+ class OrderedHash < ::Hash
178
+ end
179
+ else
180
+ # Inheritance
181
+ # Ruby 1.9 < Hash
182
+ # Ruby 1.8 < ActiveSupport::OrderedHash
183
+ class OrderedHash < Launchr::ActiveSupport::OrderedHash
184
+ end
185
+ end
186
+ end
187
+
188
+
189
+
@@ -0,0 +1,219 @@
1
+
2
+ require 'fcntl'
3
+ require 'etc'
4
+ require 'io/wait'
5
+
6
+ module Launchr
7
+ module Popen4
8
+ class << self
9
+ # This is taken directly from Ara T Howard's Open4 library, and then
10
+ # modified to suit the needs of the Chef project.
11
+ #
12
+ # http://github.com/ahoward/open4
13
+ #
14
+ # http://www.ruby-forum.com/topic/54593
15
+ #
16
+ # Don't use the "Block form" calling method. It screws up on the pipes IO.
17
+ #
18
+ # Use "Simple form", always. Simple form = more robust IO handling.
19
+ #
20
+ # @example Simple form
21
+ # def popen4_exec stdin_str, cmd, *args
22
+ # require 'plist4r/mixin/popen4'
23
+ #
24
+ # pid, stdin, stdout, stderr = ::Plist4r::Popen4::popen4 [cmd, *args]
25
+ #
26
+ # stdin.puts stdin_str
27
+ #
28
+ # stdin.close
29
+ # ignored, status = Process::waitpid2 pid
30
+ #
31
+ # stdout_result = stdout.read.strip
32
+ # stderr_result = stderr.read.strip
33
+ #
34
+ # return [cmd, status, stdout_result, stderr_result]
35
+ # end
36
+ def popen4(cmd, args={}, &b)
37
+
38
+ # Waitlast - this is magic.
39
+ #
40
+ # Do we wait for the child process to die before we yield
41
+ # to the block, or after? That is the magic of waitlast.
42
+ #
43
+ # By default, we are waiting before we yield the block.
44
+ args[:waitlast] ||= false
45
+
46
+ args[:user] ||= nil
47
+ unless args[:user].kind_of?(Integer)
48
+ args[:user] = Etc.getpwnam(args[:user]).uid if args[:user]
49
+ end
50
+ args[:group] ||= nil
51
+ unless args[:group].kind_of?(Integer)
52
+ args[:group] = Etc.getgrnam(args[:group]).gid if args[:group]
53
+ end
54
+ args[:environment] ||= {}
55
+
56
+ # Default on C locale so parsing commands output can be done
57
+ # independently of the node's default locale.
58
+ # "LC_ALL" could be set to nil, in which case we also must ignore it.
59
+ unless args[:environment].has_key?("LC_ALL")
60
+ args[:environment]["LC_ALL"] = "C"
61
+ end
62
+
63
+ pw, pr, pe, ps = IO.pipe, IO.pipe, IO.pipe, IO.pipe
64
+
65
+ verbose = $VERBOSE
66
+ begin
67
+ $VERBOSE = nil
68
+ ps.last.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
69
+
70
+ cid = fork {
71
+ pw.last.close
72
+ STDIN.reopen pw.first
73
+ pw.first.close
74
+
75
+ pr.first.close
76
+ STDOUT.reopen pr.last
77
+ pr.last.close
78
+
79
+ pe.first.close
80
+ STDERR.reopen pe.last
81
+ pe.last.close
82
+
83
+ STDOUT.sync = STDERR.sync = true
84
+
85
+ if args[:group]
86
+ Process.egid = args[:group]
87
+ Process.gid = args[:group]
88
+ end
89
+
90
+ if args[:user]
91
+ Process.euid = args[:user]
92
+ Process.uid = args[:user]
93
+ end
94
+
95
+ args[:environment].each do |key,value|
96
+ ENV[key] = value
97
+ end
98
+
99
+ if args[:umask]
100
+ umask = ((args[:umask].respond_to?(:oct) ? args[:umask].oct : args[:umask].to_i) & 007777)
101
+ File.umask(umask)
102
+ end
103
+
104
+ begin
105
+ if cmd.kind_of?(Array)
106
+ exec(*cmd)
107
+ else
108
+ exec(cmd)
109
+ end
110
+ raise 'forty-two'
111
+ rescue Exception => e
112
+ Marshal.dump(e, ps.last)
113
+ ps.last.flush
114
+ end
115
+ ps.last.close unless (ps.last.closed?)
116
+ exit!
117
+ }
118
+ ensure
119
+ $VERBOSE = verbose
120
+ end
121
+
122
+ [pw.first, pr.last, pe.last, ps.last].each{|fd| fd.close}
123
+
124
+ begin
125
+ e = Marshal.load ps.first
126
+ raise(Exception === e ? e : "unknown failure!")
127
+ rescue EOFError # If we get an EOF error, then the exec was successful
128
+ 42
129
+ ensure
130
+ ps.first.close
131
+ end
132
+
133
+ pw.last.sync = true
134
+
135
+ pi = [pw.last, pr.first, pe.first]
136
+
137
+ if b
138
+ begin
139
+ if args[:waitlast]
140
+ b[cid, *pi]
141
+ # send EOF so that if the child process is reading from STDIN
142
+ # it will actually finish up and exit
143
+ pi[0].close_write
144
+ Process.waitpid2(cid).last
145
+ else
146
+ # This took some doing.
147
+ # The trick here is to close STDIN
148
+ # Then set our end of the childs pipes to be O_NONBLOCK
149
+ # Then wait for the child to die, which means any IO it
150
+ # wants to do must be done - it's dead. If it isn't,
151
+ # it's because something totally skanky is happening,
152
+ # and we don't care.
153
+ o = StringIO.new
154
+ e = StringIO.new
155
+
156
+ pi[0].close
157
+
158
+ stdout = pi[1]
159
+ stderr = pi[2]
160
+
161
+ stdout.sync = true
162
+ stderr.sync = true
163
+
164
+ stdout.fcntl(Fcntl::F_SETFL, pi[1].fcntl(Fcntl::F_GETFL) | Fcntl::O_NONBLOCK)
165
+ stderr.fcntl(Fcntl::F_SETFL, pi[2].fcntl(Fcntl::F_GETFL) | Fcntl::O_NONBLOCK)
166
+
167
+ stdout_finished = false
168
+ stderr_finished = false
169
+
170
+ results = nil
171
+
172
+ while !stdout_finished || !stderr_finished
173
+ begin
174
+ channels_to_watch = []
175
+ channels_to_watch << stdout if !stdout_finished
176
+ channels_to_watch << stderr if !stderr_finished
177
+ ready = IO.select(channels_to_watch, nil, nil, 1.0)
178
+ rescue Errno::EAGAIN
179
+ ensure
180
+ results = Process.waitpid2(cid, Process::WNOHANG)
181
+ if results
182
+ stdout_finished = true
183
+ stderr_finished = true
184
+ end
185
+ end
186
+
187
+ if ready && ready.first.include?(stdout)
188
+ line = results ? stdout.gets(nil) : stdout.gets
189
+ if line
190
+ o.write(line)
191
+ else
192
+ stdout_finished = true
193
+ end
194
+ end
195
+ if ready && ready.first.include?(stderr)
196
+ line = results ? stderr.gets(nil) : stderr.gets
197
+ if line
198
+ e.write(line)
199
+ else
200
+ stderr_finished = true
201
+ end
202
+ end
203
+ end
204
+ results = Process.waitpid2(cid) unless results
205
+ o.rewind
206
+ e.rewind
207
+ b[cid, pi[0], o, e]
208
+ results.last
209
+ end
210
+ ensure
211
+ pi.each{|fd| fd.close unless fd.closed?}
212
+ end
213
+ else
214
+ [cid, pw.last, pr.first, pe.first]
215
+ end
216
+ end
217
+ end
218
+ end
219
+ end
@@ -0,0 +1,106 @@
1
+
2
+ require 'launchr'
3
+ require 'pathname'
4
+
5
+ module Launchr
6
+ module Path
7
+ class << self
8
+ def user_launchdaemons
9
+ Pathname.new("~/Library/LaunchAgents").expand_path
10
+ end
11
+
12
+ def boot_launchdaemons
13
+ Pathname.new("/Library/LaunchDaemons")
14
+ end
15
+
16
+ def brew_launchdaemons
17
+ if homebrew_prefix
18
+ homebrew_prefix+"Library/LaunchDaemons"
19
+ else
20
+ false
21
+ end
22
+ end
23
+
24
+ def launchr_default_boot
25
+ Pathname.new("~/Library/Preferences/#{Launchr.label}.default-boot").expand_path
26
+ end
27
+
28
+ def launchr_bin
29
+ Pathname.new(LAUNCHR_BIN).expand_path
30
+ end
31
+
32
+ def launchr_root
33
+ launchr_bin.dirname.parent
34
+ end
35
+
36
+ def launchr_version
37
+ launchr_root+"VERSION"
38
+ end
39
+
40
+ def cwd_homebrew_prefix
41
+ case @cwd_homebrew_prefix
42
+ when nil
43
+ Pathname.pwd.ascend do |path|
44
+ if (path+"/Library/Homebrew").exist?
45
+ @cwd_homebrew_prefix = path
46
+ break
47
+ end
48
+ end
49
+ @cwd_homebrew_prefix ||= false
50
+ else
51
+ @cwd_homebrew_prefix
52
+ end
53
+ end
54
+
55
+ # Same as Kernel.const_defined?, except it works for global constants
56
+ def global_const_defined? string
57
+ begin
58
+ eval string
59
+ true
60
+ rescue NameError
61
+ false
62
+ end
63
+ end
64
+
65
+ def bin_homebrew_prefix
66
+ case @bin_homebrew_prefix
67
+ when nil
68
+ if global_const_defined?("HOMEBREW_PREFIX")
69
+ @bin_homebrew_prefix = HOMEBREW_PREFIX
70
+ elsif launchr_root.include?("Cellar/launchr")
71
+ @bin_homebrew_prefix = Pathname.new(launchr_root.to_s.gsub(/\/Cellar\/launchr.*$/,""))
72
+ end
73
+
74
+ @bin_homebrew_prefix ||= false
75
+ else
76
+ @bin_homebrew_prefix
77
+ end
78
+ end
79
+
80
+ def homebrew_prefix
81
+ # cwd_homebrew_prefix || bin_homebrew_prefix
82
+ bin_homebrew_prefix
83
+ end
84
+
85
+ def chown_down path
86
+ if Launchr.superuser?
87
+ FileUtils.chown_R Launchr.user, Launchr.group, path.to_s
88
+ end
89
+ end
90
+
91
+ end
92
+ end
93
+ end
94
+
95
+
96
+
97
+
98
+
99
+
100
+
101
+
102
+
103
+
104
+
105
+
106
+