elliottcable-LaunchDoctor 0

Sign up to get free protection for your applications and to get access to all the features.
data/.manifest ADDED
@@ -0,0 +1,7 @@
1
+ lib/launchdr/launchd.rb
2
+ lib/launchdr/property_list.rb
3
+ lib/launchdr/tasks.rb
4
+ lib/launchdr.rb
5
+ Rakefile.rb
6
+ README.markdown
7
+ .manifest
data/README.markdown ADDED
@@ -0,0 +1,61 @@
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 = LaunchDoctor::Launchd.new "name.elliottcable.launchdr.test"
17
+ plist[:program_arguments] = ['/Applications/Calculator.app/Contents/MacOS/Calculator']
18
+ plist.dump LaunchDoctor::Launchd::Paths[:user_agent]
19
+
20
+ The second is to use the common block idiom, provided by the `LaunchDoctor()`
21
+ method:
22
+
23
+ require 'launchdr'
24
+ LaunchDoctor "name.elliottcable.launchdr.test" do |plist|
25
+ plist[:program_arguments] = ['/Applications/Calculator.app/Contents/MacOS/Calculator']
26
+ end
27
+
28
+ LaunchDoctor can write (`dump`) the property lists to any place on your disk,
29
+ but the idiom method assumes you're going to want to use one of the
30
+ directories that launchd checks for property lists. These are stored in the
31
+ `Launchd::Paths` array. The default is to place it in the user-owned agents
32
+ directory at `~/Library/LaunchAgents`.
33
+
34
+ LaunchDoctor also preforms some 'prettification' on the keys provided by
35
+ launchd's property list structure. All of the keys on the
36
+ [`launchd.plist` manpage][manpage] are available, but they can also be used as
37
+ true 'Ruby-ish' symbol keys. All of the following are legal:
38
+
39
+ plist["UserName"] = "elliottcable"
40
+ plist[:UserName] = "elliottcable"
41
+ plist[:user_name] = "elliottcable"
42
+
43
+ Finally, you can use the Rake task interface to the last method. It simply
44
+ wraps the last method inside a rake task. This method is really great if you
45
+ want to provide a way to let users make your gem's binary run all the time:
46
+
47
+ LaunchDoctor.task :launchd, :bin => 'jello', :arguments => ['-D', 'shortener', 'grabup']
48
+
49
+ This isn't very flexible, but it's not very complicated either. If you need
50
+ more control over the plist, just use the second method inside a `task` block.
51
+ This method defaults to making your gem's binary `run_at_load` and be
52
+ `keep_alive` as well, so it won't die.
53
+
54
+ [plist]: <http://en.wikipedia.org/wiki/Property_list> "Property list on Wikipedia"
55
+ [manpage]: <http://developer.apple.com/DOCUMENTATION/DARWIN/Reference/ManPages/man5/launchd.plist.5.html> "Mac OS X Manual Page for launchd.plist(5)"
56
+ [rake]: <http://rake.rubyforge.org/> "Rake's RDocs"
57
+
58
+ Requirements
59
+ ------------
60
+ - OSX/plist by kballard - `sudo gem install kballard-osx-plist --source=http://gems.github.com/`
61
+ - Ruby Facets - `sudo gem install facets`
data/Rakefile.rb ADDED
@@ -0,0 +1,45 @@
1
+ ($:.unshift File.expand_path(File.join( File.dirname(__FILE__), 'lib' ))).uniq!
2
+ begin
3
+ require 'launchdr'
4
+ rescue LoadError
5
+ module LaunchDoctor; 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', LaunchDoctor::Version) do |g|; g.name = 'LaunchDoctor'
20
+ g.project = 'launchdr'
21
+ g.author = ['elliottcable']
22
+ g.email = ['LaunchDoctor@elliottcable.com']
23
+ g.summary = "One stop shop for launchd property list creation. The doctor is *in*!"
24
+ g.url = 'http://github.com/elliottcable/launchdr'
25
+ g.dependencies = ['kballard-osx-plist', 'facets']
26
+ g.development_dependencies = ['elliottcable-echoe >= 3.0.2']
27
+ g.manifest_name = '.manifest' # I don't want this showing up <,<
28
+ g.retain_gemspec = true # perfect for GitHub
29
+ g.rakefile_name = 'Rakefile.rb' # It's a Ruby file, why not have .rb?
30
+ g.ignore_pattern = /^\.git\/|\.gemspec/
31
+ end
32
+
33
+ desc 'tests packaged files to ensure they are all present'
34
+ task :verify => :package do
35
+ # An error message will be displayed if files are missing
36
+ if system %(ruby -e "require 'rubygems'; require 'pkg/launchdr-#{LaunchDoctor::Version}/lib/launchdr'")
37
+ puts "\nThe library files are present"
38
+ end
39
+ end
40
+ end
41
+
42
+ rescue LoadError
43
+ desc 'You need the `elliottcable-echoe` gem to package LaunchDoctor'
44
+ task :package
45
+ end
data/launchdr.gemspec ADDED
@@ -0,0 +1,40 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{LaunchDoctor}
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 = ["LaunchDoctor@elliottcable.com"]
12
+ s.extra_rdoc_files = ["lib/launchdr/launchd.rb", "lib/launchdr/property_list.rb", "lib/launchdr/tasks.rb", "lib/launchdr.rb", "README.markdown"]
13
+ s.files = ["lib/launchdr/launchd.rb", "lib/launchdr/property_list.rb", "lib/launchdr/tasks.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
data/lib/launchdr.rb ADDED
@@ -0,0 +1,37 @@
1
+ require 'launchdr/property_list'
2
+ require 'launchdr/launchd'
3
+
4
+
5
+ def LaunchDoctor label, opts = {}
6
+ LaunchDoctor.create label, opts, &Proc.new
7
+ end
8
+ module LaunchDoctor
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
+ end
26
+
27
+ def allow_system_agents!
28
+ Options[:system_agents_allowed] = true
29
+ end
30
+
31
+ def allow_system_daemons!
32
+ raise "You must allow System-owned agents to allow System-owned daemons!" unless Options[:system_agents_allowed]
33
+ Options[:system_daemon_allowed] = true
34
+ end
35
+
36
+
37
+ end
@@ -0,0 +1,25 @@
1
+ require 'facets/string'
2
+
3
+ module LaunchDoctor
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
+ # Nothing here as of yet. Maybe some convenience methods to come.
15
+
16
+ def [] key
17
+ super(key.to_s.camelcase)
18
+ end
19
+
20
+ def []= key, value
21
+ super(key.to_s.camelcase, value)
22
+ end
23
+ end
24
+
25
+ end
@@ -0,0 +1,38 @@
1
+ require 'osx/plist'
2
+ require 'uuid'
3
+
4
+ module LaunchDoctor
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 LaunchDoctor
2
+
3
+ def task name = :launchd, opts = {}
4
+ raise "`LaunchDoctor.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
+ LaunchDoctor 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
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: elliottcable-LaunchDoctor
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
+ - LaunchDoctor@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/tasks.rb
56
+ - lib/launchdr.rb
57
+ - README.markdown
58
+ files:
59
+ - lib/launchdr/launchd.rb
60
+ - lib/launchdr/property_list.rb
61
+ - lib/launchdr/tasks.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
+