plister 0.1.1 → 0.2.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.
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: