plister 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2001bfebfa14b94a467d18dbe2592dabcf3a17fc
4
- data.tar.gz: e1b0e8c8d0ca47e7101ab8da0cf9572144c872e3
3
+ metadata.gz: 4c89854e921ebac0cc2eec17810ce5e00d1e23d8
4
+ data.tar.gz: 1ea06e262ee6a703ca8b4a3981830ce7a402b458
5
5
  SHA512:
6
- metadata.gz: 19bd90e4181f2c8810220197702ddde9fa0eebb59d1085d20d1fd5abf7e0b8a134c20547bded8e82608aac1c035366158ceb720a0ce3e5cd2377a8e439a816ed
7
- data.tar.gz: c64ba64d3d675d46ac3a6256a2280df0907c947d0f67c5d06dfe3f5227cc14e23f1f56b5935e6ae321b20e3b5ef46e38fea62c3137e72f5d396a8eeb530c0a4a
6
+ metadata.gz: 86719f7a5f784db7db17cc179d2310933e24d9abe04d15ce5915eac7093aff95bc6d077c263b402195053ed985ad1661cc22a641b8bb8a294bc0466698eb2c18
7
+ data.tar.gz: f0815ed9fb79f949cdded58b47080139aacfff698f39f6449fa243c4a5b979f8f1ae1611023524dfd400e69283c94689b3df6d5161d518704fedecbcb511679b
@@ -1,6 +1,5 @@
1
+ os: osx
1
2
  language: ruby
2
- rvm:
3
- - 2.3.0
4
3
  before_install: gem install bundler -v 1.11.2
5
4
  cache: bundler
6
5
  sudo: false
data/Gemfile CHANGED
@@ -2,3 +2,5 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in plister.gemspec
4
4
  gemspec
5
+
6
+ gem 'pry', github: 'pry/pry'
data/README.md CHANGED
@@ -6,7 +6,9 @@
6
6
 
7
7
  ## What it does
8
8
 
9
- Most dotfile setups have a string of cryptic `defaults write com.apple...`-type commands. Plister simplifies that process by allowing you to store your OS X preferences in a single YAML file (likily in your home directory or within your dotfiles repostiory), and exposes a single `plister` command line tool to set your saved preferences.
9
+ Most dotfile setups have a string of cryptic `defaults write com.apple...`-type commands. Plister simplifies that process by allowing you to store your OS X preferences in a single YAML file (likely in your home directory or within your dotfiles repostiory), and exposes a single `plister` command line tool to set your saved preferences.
10
+
11
+ See [@benbalter's dotfiles for an example](https://github.com/benbalter/dotfiles/blob/master/.osx.yml).
10
12
 
11
13
  ## Usage
12
14
 
@@ -16,7 +18,7 @@ Most dotfile setups have a string of cryptic `defaults write com.apple...`-type
16
18
 
17
19
  ### The command line tool
18
20
 
19
- `$ plister [path-to-your-preferences.yml]`
21
+ `$ plister [path-to-your-preferences.yml] [options]`
20
22
 
21
23
  If no preference file is passed, Plister will default to `~/.osx.yml`.
22
24
 
@@ -26,6 +28,10 @@ If no preference file is passed, Plister will default to `~/.osx.yml`.
26
28
  .
27
29
  2. Add your OS X preferences to the `.osx.yml` file, following the instructions below.
28
30
 
31
+ ### Dumping existing preferences
32
+
33
+ To dump all your existing preferences, run `plister [path-to-your-preferences.yml] --dump`. This will output all your existing preferences as a YAML file at the specified path, defaulting to `~/.osx.yml` if none is given. You can also pass the `--stdout` flag to dump preferences to STDOUT.
34
+
29
35
  ### Describing preferences
30
36
 
31
37
  OS X has several different ways of storing preferences, each with their own domain (e.g., `com.apple.safari`). If you're copying your preferences from a tutorial or someone else's dotfiles, you can tell the domain and type by the command used to set it.
@@ -87,3 +93,13 @@ defaults write NSGlobalDomain WebKitDeveloperExtras -bool true
87
93
  sudo defaults write com.apple.SoftwareUpdate AutomaticCheckEnabled -bool true
88
94
  default write -currentHost com.apple.ScreenSaver.iLifeSlideShows styleKey VintagePrints
89
95
  ```
96
+
97
+ ## Not writable errors
98
+
99
+ If you get an error that looks like:
100
+
101
+ ```
102
+ /Library/Preferences/[DOMAIN].plist is not writable by [USER] (IOError)
103
+ ```
104
+
105
+ You'll need to preface the `plister` command with `sudo` so that Ruby can write the system-wide preference.
@@ -1,12 +1,33 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ require 'slop'
3
4
  require_relative '../lib/plister'
4
5
 
5
- preferences = Plister.preferences(ARGV[0])
6
+ opts = Slop.parse do |o|
7
+ o.banner = 'usage: plister [file] [options]'
8
+ o.bool '-h', '--help', 'display usage information'
9
+ o.bool '-d', '--dump', 'dump preferences to YAML'
10
+ o.bool '-s', '--stdout', 'dump preferences to STDOUT'
11
+ o.on '-v', '--version', 'print the version' do
12
+ puts Plister::VERSION
13
+ exit
14
+ end
15
+ end
6
16
 
7
- puts "Using preference file #{preferences.path}"
8
- puts "Found preferences for #{preferences.domains.count} applications"
9
-
10
- preferences.set!(verbose: true)
11
-
12
- puts 'Preferences set!'
17
+ if opts.help?
18
+ puts opts
19
+ exit 1
20
+ elsif opts.dump?
21
+ exporter = Plister::Exporter.new(opts.arguments.first)
22
+ puts "Dumping preferences to #{exporter.path}"
23
+ exporter.export
24
+ elsif opts.stdout?
25
+ exporter = Plister::Exporter.new(opts.arguments.first)
26
+ puts exporter.to_s
27
+ else
28
+ preferences = Plister.preferences(opts.arguments.first)
29
+ puts "Using preference file #{preferences.path}"
30
+ puts "Found preferences for #{preferences.domains.count} applications"
31
+ preferences.set!(verbose: true)
32
+ puts 'Preferences set!'
33
+ end
@@ -1,10 +1,11 @@
1
1
  require 'cfpropertylist'
2
2
  require 'deep_merge'
3
- require 'yaml'
3
+ require 'psych'
4
4
 
5
5
  require_relative 'plister/version'
6
6
  require_relative 'plister/plist'
7
7
  require_relative 'plister/preferences'
8
+ require_relative 'plister/exporter'
8
9
 
9
10
  module Plister
10
11
  class << self
@@ -13,7 +14,11 @@ module Plister
13
14
  end
14
15
 
15
16
  def user
16
- @user ||= `logname`.strip
17
+ @user ||= begin
18
+ user = `whoami`.strip
19
+ return user unless user == 'root'
20
+ `logname`.strip
21
+ end
17
22
  end
18
23
 
19
24
  def uuid
@@ -0,0 +1,43 @@
1
+ module Plister
2
+ class Exporter
3
+ attr_reader :path
4
+
5
+ def initialize(path = nil)
6
+ @path = path || "/Users/#{Plister.user}/.osx.yml"
7
+ end
8
+
9
+ def export
10
+ File.write path, to_s
11
+ end
12
+
13
+ def to_s
14
+ Psych.dump(preferences)
15
+ end
16
+
17
+ private
18
+
19
+ def types
20
+ @types ||= {
21
+ system: '/Library/Preferences',
22
+ user: "/Users/#{Plister.user}/Library/Preferences",
23
+ host: "/Users/#{Plister.user}/Library/preferences/ByHost"
24
+ }
25
+ end
26
+
27
+ def paths
28
+ @paths ||= types.map { |type, path| [type, Dir["#{path}/*.plist"]] }.to_h
29
+ end
30
+
31
+ def preferences
32
+ @preferences ||= begin
33
+ output = {}
34
+ paths.each do |type, plist_paths|
35
+ plists = plist_paths.map { |domain| Plist.new domain, type: type }
36
+ plists.select!(&:readable?)
37
+ output[type.to_s] = plists.map { |p| [p.domain, p.to_h] }.to_h
38
+ end
39
+ output
40
+ end
41
+ end
42
+ end
43
+ end
@@ -4,14 +4,17 @@ module Plister
4
4
  TYPES = %w(user system host).freeze
5
5
 
6
6
  def initialize(domain, type: 'user')
7
- @domain = domain
7
+ @domain = normalize_domain(domain)
8
8
  @type = type.to_s
9
- fail ArgumentError, 'Invalid type' unless valid_type?
9
+ raise ArgumentError, 'Invalid type' unless valid_type?
10
10
  end
11
11
 
12
12
  def preferences
13
13
  @preferences ||= CFPropertyList.native_types(list.value)
14
+ rescue CFFormatError
15
+ {}
14
16
  end
17
+ alias to_h preferences
15
18
 
16
19
  def preferences=(prefs)
17
20
  list.value = CFPropertyList.guess(prefs, convert_unknown_to_string: true)
@@ -24,10 +27,22 @@ module Plister
24
27
  end
25
28
 
26
29
  def write
27
- fail IOError, "#{path} is not writable by #{Plister.user}" unless writable?
30
+ raise IOError, "#{path} is not writable by #{Plister.user}" unless writable?
28
31
  list.save
29
32
  end
30
33
 
34
+ def exists?
35
+ File.exist?(path)
36
+ end
37
+
38
+ def writable?
39
+ File.writable?(path)
40
+ end
41
+
42
+ def readable?
43
+ File.readable?(path)
44
+ end
45
+
31
46
  private
32
47
 
33
48
  def path
@@ -44,25 +59,20 @@ module Plister
44
59
  end
45
60
 
46
61
  def list
47
- fail IOError, "#{path} does not exist" unless exists?
48
- fail IOError, "#{path} is not readable by #{Plister.user}" unless readable?
62
+ raise IOError, "#{path} does not exist" unless exists?
63
+ raise IOError, "#{path} is not readable by #{Plister.user}" unless readable?
49
64
  @list ||= CFPropertyList::List.new file: path
50
65
  end
51
66
 
52
- def exists?
53
- File.exist?(path)
54
- end
55
-
56
- def writable?
57
- File.writable?(path)
58
- end
59
-
60
- def readable?
61
- File.readable?(path)
62
- end
63
-
64
67
  def valid_type?
65
68
  TYPES.include?(type)
66
69
  end
70
+
71
+ def normalize_domain(domain)
72
+ domain = File.basename(domain)
73
+ domain = domain.sub(/\.plist\z/, '')
74
+ domain = domain.sub(/\.#{Plister.uuid}\z/, '')
75
+ domain
76
+ end
67
77
  end
68
78
  end
@@ -24,7 +24,7 @@ module Plister
24
24
  private
25
25
 
26
26
  def data
27
- @data ||= YAML.load(contents)
27
+ @data ||= Psych.load(contents) || {}
28
28
  end
29
29
 
30
30
  def contents
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Plister
3
- VERSION = '0.1.1'.freeze
3
+ VERSION = '0.2.0'.freeze
4
4
  end
@@ -21,10 +21,10 @@ Gem::Specification.new do |spec|
21
21
 
22
22
  spec.add_dependency 'CFPropertyList', '~> 2.3'
23
23
  spec.add_dependency 'deep_merge', '~> 1.0'
24
+ spec.add_dependency 'slop', '~> 4.0'
24
25
 
25
26
  spec.add_development_dependency 'bundler', '~> 1.11'
26
27
  spec.add_development_dependency 'rake', '~> 10.0'
27
28
  spec.add_development_dependency 'rspec', '~> 3.0'
28
- spec.add_development_dependency 'pry', '~> 0.10'
29
29
  spec.add_development_dependency 'rubocop', '~> 0.36'
30
30
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plister
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Balter
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-18 00:00:00.000000000 Z
11
+ date: 2016-08-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: CFPropertyList
@@ -39,61 +39,61 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: bundler
42
+ name: slop
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '1.11'
48
- type: :development
47
+ version: '4.0'
48
+ type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '1.11'
54
+ version: '4.0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: rake
56
+ name: bundler
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '10.0'
61
+ version: '1.11'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '10.0'
68
+ version: '1.11'
69
69
  - !ruby/object:Gem::Dependency
70
- name: rspec
70
+ name: rake
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '3.0'
75
+ version: '10.0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '3.0'
82
+ version: '10.0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: pry
84
+ name: rspec
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '0.10'
89
+ version: '3.0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '0.10'
96
+ version: '3.0'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: rubocop
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -126,6 +126,7 @@ files:
126
126
  - Rakefile
127
127
  - bin/plister
128
128
  - lib/plister.rb
129
+ - lib/plister/exporter.rb
129
130
  - lib/plister/plist.rb
130
131
  - lib/plister/preferences.rb
131
132
  - lib/plister/version.rb
@@ -153,9 +154,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
153
154
  version: '0'
154
155
  requirements: []
155
156
  rubyforge_project:
156
- rubygems_version: 2.5.1
157
+ rubygems_version: 2.6.6
157
158
  signing_key:
158
159
  specification_version: 4
159
160
  summary: A utility for programmatically setting OS X plist file preferences
160
161
  test_files: []
161
- has_rdoc: