elliottcable-launchdr 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.
data/.manifest ADDED
@@ -0,0 +1,7 @@
1
+ lib/launchdr/launchd.rb
2
+ lib/launchdr/property_list.rb
3
+ lib/launchdr/task.rb
4
+ lib/launchdr.rb
5
+ Rakefile.rb
6
+ README.markdown
7
+ .manifest
data/README.markdown ADDED
@@ -0,0 +1,66 @@
1
+ LaunchDoctor
2
+ ============
3
+ I've got a PhD in [launchd][], and I'm not afraid to use it!
4
+
5
+ [launchd]: <http://en.wikipedia.org/wiki/Launchd> "launchd on Wikipedia"
6
+
7
+ Usage
8
+ -----
9
+ LaunchDoctor is really simple. It is essentially an easy interface to
10
+ [launchd][]'s [property list][plist] files.
11
+
12
+ There are three ways to use LaunchDoctor - the simplest being directly
13
+ creating property lists and treating them as hashes:
14
+
15
+ require 'launchdr'
16
+ plist = LaunchDr::Launchd.new "name.elliottcable.launchdr.test"
17
+ plist[:program_arguments] = ['/Applications/Calculator.app/Contents/MacOS/Calculator']
18
+ plist.dump LaunchDr::Launchd::Paths[:user_agent]
19
+
20
+ The second is to use the common block idiom, provided by the `LaunchDr()`
21
+ method:
22
+
23
+ require 'launchdr'
24
+ LaunchDr "name.elliottcable.launchdr.test" do |plist|
25
+ plist[:program_arguments] = ['/Applications/Calculator.app/Contents/MacOS/Calculator']
26
+ end
27
+
28
+ LaunchDoctor will automatically add the property list to `launchctl`, and then
29
+ start it running. Once you run the above snippet, the target will immediately
30
+ be launched for the first time.
31
+
32
+ LaunchDoctor can write (`dump`) the property lists to any place on your disk,
33
+ but the idiom method assumes you're going to want to use one of the
34
+ directories that launchd checks for property lists. These are stored in the
35
+ `Launchd::Paths` array. The default is to place it in the user-owned agents
36
+ directory at `~/Library/LaunchAgents`.
37
+
38
+ LaunchDoctor also preforms some 'prettification' on the keys provided by
39
+ launchd's property list structure. All of the keys on the
40
+ [`launchd.plist` manpage][manpage] are available, but they can also be used as
41
+ true 'Ruby-ish' symbol keys. All of the following are legal:
42
+
43
+ plist["UserName"] = "elliottcable"
44
+ plist[:UserName] = "elliottcable"
45
+ plist[:user_name] = "elliottcable"
46
+
47
+ Finally, you can use the Rake task interface to the last method. It simply
48
+ wraps the last method inside a rake task. This method is really great if you
49
+ want to provide a way to let users make your gem's binary run all the time:
50
+
51
+ require 'launchdr/task'
52
+ LaunchDr.task :launchd, :bin => 'jello', :arguments => ['-D', 'shortener', 'grabup']
53
+
54
+ This isn't very flexible, but it's not very complicated either. If you need
55
+ more control over the plist, just use the second method inside a `task` block.
56
+ This method defaults to making your gem's binary `run_at_load` and be
57
+ `keep_alive` as well, so it won't die.
58
+
59
+ [plist]: <http://en.wikipedia.org/wiki/Property_list> "Property list on Wikipedia"
60
+ [manpage]: <http://developer.apple.com/DOCUMENTATION/DARWIN/Reference/ManPages/man5/launchd.plist.5.html> "Mac OS X Manual Page for launchd.plist(5)"
61
+ [rake]: <http://rake.rubyforge.org/> "Rake's RDocs"
62
+
63
+ Requirements
64
+ ------------
65
+ - OSX/plist by kballard - `sudo gem install kballard-osx-plist --source=http://gems.github.com/`
66
+ - Ruby Facets - `sudo gem install facets`
data/Rakefile.rb ADDED
@@ -0,0 +1,44 @@
1
+ ($:.unshift File.expand_path(File.join( File.dirname(__FILE__), 'lib' ))).uniq!
2
+ begin
3
+ require 'launchdr'
4
+ rescue LoadError
5
+ module LaunchDr; Version = -1; end
6
+ end
7
+
8
+ # =======================
9
+ # = Gem packaging tasks =
10
+ # =======================
11
+ begin
12
+ require 'echoe'
13
+
14
+ task :package => :'package:package'
15
+ task :install => :'package:install'
16
+ task :manifest => :'package:manifest'
17
+ task :clobber => :'package:clobber'
18
+ namespace :package do
19
+ Echoe.new('launchdr', LaunchDr::Version) do |g|
20
+ g.author = ['elliottcable']
21
+ g.email = ['launchdr@elliottcable.com']
22
+ g.summary = "One stop shop for launchd property list creation. The doctor is *in*!"
23
+ g.url = 'http://github.com/elliottcable/launchdr'
24
+ g.dependencies = ['kballard-osx-plist', 'facets']
25
+ g.development_dependencies = ['elliottcable-echoe >= 3.0.2']
26
+ g.manifest_name = '.manifest' # I don't want this showing up <,<
27
+ g.retain_gemspec = true # perfect for GitHub
28
+ g.rakefile_name = 'Rakefile.rb' # It's a Ruby file, why not have .rb?
29
+ g.ignore_pattern = /^\.git\/|\.gemspec/
30
+ end
31
+
32
+ desc 'tests packaged files to ensure they are all present'
33
+ task :verify => :package do
34
+ # An error message will be displayed if files are missing
35
+ if system %(ruby -e "require 'rubygems'; require 'pkg/launchdr-#{LaunchDr::Version}/lib/launchdr'")
36
+ puts "\nThe library files are present"
37
+ end
38
+ end
39
+ end
40
+
41
+ rescue LoadError
42
+ desc 'You need the `elliottcable-echoe` gem to package LaunchDr'
43
+ task :package
44
+ end
data/launchdr.gemspec ADDED
@@ -0,0 +1,40 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{launchdr}
5
+ s.version = "0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["elliottcable"]
9
+ s.date = %q{2008-12-23}
10
+ s.description = %q{One stop shop for launchd property list creation. The doctor is *in*!}
11
+ s.email = ["launchdr@elliottcable.com"]
12
+ s.extra_rdoc_files = ["lib/launchdr/launchd.rb", "lib/launchdr/property_list.rb", "lib/launchdr/task.rb", "lib/launchdr.rb", "README.markdown"]
13
+ s.files = ["lib/launchdr/launchd.rb", "lib/launchdr/property_list.rb", "lib/launchdr/task.rb", "lib/launchdr.rb", "Rakefile.rb", "README.markdown", ".manifest", "launchdr.gemspec"]
14
+ s.has_rdoc = true
15
+ s.homepage = %q{http://github.com/elliottcable/launchdr}
16
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Launchdr", "--main", "README.markdown"]
17
+ s.require_paths = ["lib"]
18
+ s.rubyforge_project = %q{launchdr}
19
+ s.rubygems_version = %q{1.3.0}
20
+ s.summary = %q{One stop shop for launchd property list creation. The doctor is *in*!}
21
+
22
+ if s.respond_to? :specification_version then
23
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
24
+ s.specification_version = 2
25
+
26
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
27
+ s.add_runtime_dependency(%q<kballard-osx-plist>, [">= 0"])
28
+ s.add_runtime_dependency(%q<facets>, [">= 0"])
29
+ s.add_development_dependency(%q<elliottcable-echoe>, [">= 0", "= 3.0.2"])
30
+ else
31
+ s.add_dependency(%q<kballard-osx-plist>, [">= 0"])
32
+ s.add_dependency(%q<facets>, [">= 0"])
33
+ s.add_dependency(%q<elliottcable-echoe>, [">= 0", "= 3.0.2"])
34
+ end
35
+ else
36
+ s.add_dependency(%q<kballard-osx-plist>, [">= 0"])
37
+ s.add_dependency(%q<facets>, [">= 0"])
38
+ s.add_dependency(%q<elliottcable-echoe>, [">= 0", "= 3.0.2"])
39
+ end
40
+ end
@@ -0,0 +1,43 @@
1
+ require 'facets/string'
2
+
3
+ module LaunchDr
4
+
5
+ class Launchd < PropertyList
6
+ Paths = {
7
+ :user_agent => "~/Library/LaunchAgents",
8
+ :agent => "/Library/LaunchAgents",
9
+ :daemon => "/Library/LaunchDaemons",
10
+ :system_agent => "/System/Library/LaunchAgents",
11
+ :system_daemon => "/System/Library/LaunchDaemons"
12
+ }
13
+
14
+ def [] key
15
+ super(key.to_s.camelcase)
16
+ end
17
+
18
+ def []= key, value
19
+ super(key.to_s.camelcase, value)
20
+ end
21
+
22
+ # Adds the property list to `launchctl`'s indexes, and starts it (unless
23
+ # disabled).
24
+ def load!
25
+ system "launchctl load #{file}"
26
+ end
27
+
28
+ # Removes the propertly list from `launchctl`'s indexes.
29
+ def unload!
30
+ system "launchctl unload #{file}"
31
+ end
32
+
33
+ # Finds the plist file, if it's been created
34
+ def file
35
+ Paths.values.each do |dir|
36
+ file = File.expand_path(File.join(dir, self[:label] + '.plist'))
37
+ return file if File.file? file
38
+ end
39
+ raise "#{self[:label]} doesn't exist in any of the default locations. Did you #dump it?"
40
+ end
41
+ end
42
+
43
+ end
@@ -0,0 +1,38 @@
1
+ require 'osx/plist'
2
+ require 'uuid'
3
+
4
+ module LaunchDr
5
+
6
+ class PropertyList
7
+ attr_reader :elements
8
+
9
+ def initialize label = nil, elements = {}
10
+ @elements = elements
11
+ @elements['Label'] = label || "rb.launchdr.#{UUID.new.generate}"
12
+ end
13
+
14
+ def [] key
15
+ @elements[key.to_s]
16
+ end
17
+
18
+ def []= key, value
19
+ @elements[key] = value
20
+ end
21
+
22
+ def to_plist
23
+ @elements.to_plist
24
+ end
25
+
26
+ def dump path
27
+ out = File.new(File.expand_path(File.join(path, @elements['Label'] + '.plist')), 'w+')
28
+ OSX::PropertyList.dump out, @elements
29
+ out.close
30
+ end
31
+
32
+ def self.load filename
33
+ elements = OSX::PropertyList.load File.new(File.expand_path filename, 'r')
34
+ new elements[:label], elements
35
+ end
36
+ end
37
+
38
+ end
@@ -0,0 +1,18 @@
1
+ module LaunchDr
2
+
3
+ def task name = :launchd, opts = {}
4
+ raise "`LaunchDr.task`'s options must include the name of the binary for your gem!" unless opts[:bin]
5
+ opts = {:desc => 'Creates a launchd property list for this gem', :arguments => []}.merge opts
6
+
7
+ desc opts[:desc] unless opts[:no_desc]
8
+ task name do
9
+ LaunchDr label do |plist|
10
+ plist[:program_arguments] = [File.join('/usr/local/bin', opts[:bin]), opts[:arguments]].flatten
11
+ plist[:keep_alive] = true
12
+ plist[:run_at_load] = true
13
+ end
14
+ end
15
+
16
+ end
17
+
18
+ end
data/lib/launchdr.rb ADDED
@@ -0,0 +1,38 @@
1
+ require 'launchdr/property_list'
2
+ require 'launchdr/launchd'
3
+
4
+
5
+ def LaunchDr label, opts = {}
6
+ LaunchDr.create label, opts, &Proc.new
7
+ end
8
+ module LaunchDr
9
+ extend self
10
+
11
+ Version = 0
12
+ Options = Hash.new
13
+
14
+ def create label, opts = {}
15
+ plist = Launchd.new label
16
+
17
+ yield plist if block_given?
18
+
19
+ raise "You must run as a root user and allow_system_agents! if you wish to preform the dangerous act of writing to #{Launchd::Paths[:system_agent]}!" unless !(opts[:type] == :system_agent) or Options[:system_agents_allowed]
20
+ raise "You must run as a root user, allow_system_agents!, *and* allow_system_daemons! if you wish to preform the very dangerous act of writing to #{Launchd::Paths[:system_daemon]}!" unless !(opts[:type] == :system_daemon) or Options[:system_daemon_allowed]
21
+ path = Launchd::Paths[opts[:type] || :user_agent]
22
+ raise "Type error! Must be one of #{Launchd::Paths.keys.join(", ")}" unless path
23
+
24
+ plist.dump File.expand_path(path)
25
+ plist.load!
26
+ end
27
+
28
+ def allow_system_agents!
29
+ Options[:system_agents_allowed] = true
30
+ end
31
+
32
+ def allow_system_daemons!
33
+ raise "You must allow System-owned agents to allow System-owned daemons!" unless Options[:system_agents_allowed]
34
+ Options[:system_daemon_allowed] = true
35
+ end
36
+
37
+
38
+ end
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: elliottcable-launchdr
3
+ version: !ruby/object:Gem::Version
4
+ version: "0"
5
+ platform: ruby
6
+ authors:
7
+ - elliottcable
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-12-23 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: kballard-osx-plist
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: "0"
23
+ version:
24
+ - !ruby/object:Gem::Dependency
25
+ name: facets
26
+ version_requirement:
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ version: "0"
32
+ version:
33
+ - !ruby/object:Gem::Dependency
34
+ name: elliottcable-echoe
35
+ version_requirement:
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: "0"
41
+ - - "="
42
+ - !ruby/object:Gem::Version
43
+ version: 3.0.2
44
+ version:
45
+ description: One stop shop for launchd property list creation. The doctor is *in*!
46
+ email:
47
+ - launchdr@elliottcable.com
48
+ executables: []
49
+
50
+ extensions: []
51
+
52
+ extra_rdoc_files:
53
+ - lib/launchdr/launchd.rb
54
+ - lib/launchdr/property_list.rb
55
+ - lib/launchdr/task.rb
56
+ - lib/launchdr.rb
57
+ - README.markdown
58
+ files:
59
+ - lib/launchdr/launchd.rb
60
+ - lib/launchdr/property_list.rb
61
+ - lib/launchdr/task.rb
62
+ - lib/launchdr.rb
63
+ - Rakefile.rb
64
+ - README.markdown
65
+ - .manifest
66
+ - launchdr.gemspec
67
+ has_rdoc: true
68
+ homepage: http://github.com/elliottcable/launchdr
69
+ post_install_message:
70
+ rdoc_options:
71
+ - --line-numbers
72
+ - --inline-source
73
+ - --title
74
+ - Launchdr
75
+ - --main
76
+ - README.markdown
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: "0"
84
+ version:
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: "1.2"
90
+ version:
91
+ requirements: []
92
+
93
+ rubyforge_project: launchdr
94
+ rubygems_version: 1.2.0
95
+ signing_key:
96
+ specification_version: 2
97
+ summary: One stop shop for launchd property list creation. The doctor is *in*!
98
+ test_files: []
99
+