dutiful 0.0.2 → 0.0.3

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: e6e4c29b27d8c3ae5615ff691a712b33210694a7
4
- data.tar.gz: e8dcdd5062a88e517f0e336af7e6ff99b0413930
3
+ metadata.gz: c8a2e348ad20c4d7f7f6c8020c335d26f307fcbb
4
+ data.tar.gz: 40ec00a948a65351aeaa8c0a79282f4e6f5bd2a0
5
5
  SHA512:
6
- metadata.gz: e9d9245efc419702a02ae9fdce52efebca255fa0412cd73292c925dbf56bd86a3330bfa7e68d0e8bd7253e20ae5bbc22a2c77512178f338e06bf937416b9e053
7
- data.tar.gz: 4515e4eaff2eaaf3654e9026256355c92ff2830b59c5cd941e0c20616ddd44400f2e8d5fe0a45a1ed5ef82417a6275af66bbd65e8a78ab843f119291619b7f43
6
+ metadata.gz: a83c9c088f34fa2e491f7a36398ee11336e0b9dc36a2d440aa251efe077f6a716c8d39902beb508016b87f81bf7054f7ebcfd8ba34253b2ecb5e4fe1f7bc6c11
7
+ data.tar.gz: 6496d9a4531a3eefe2099f4c91e8bc76efc3385e2fb46f44d25f571d4a9042888320488e751f68c6e0353148c1562eba0281a8764de5639ce50ed9b57aff8460
data/bin/dutiful CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'dutiful'
4
- require 'dutiful/command'
4
+ require 'dutiful/commands'
5
5
  require 'dutiful/version'
6
6
 
7
- Dutiful::Command.run
7
+ Dutiful::Command::Main.run
@@ -0,0 +1,3 @@
1
+ [storage]
2
+ name = 'Dropbox'
3
+ path = '~/Dropbox'
@@ -0,0 +1,3 @@
1
+ [storage]
2
+ name = 'iCloud'
3
+ path = '~/Library/Mobile Documents'
data/db/bundler.toml ADDED
@@ -0,0 +1,5 @@
1
+ [application]
2
+ name = 'Bundler'
3
+
4
+ [[files]]
5
+ path = '.bundle/config'
data/db/dutiful.toml ADDED
@@ -0,0 +1,5 @@
1
+ [application]
2
+ name = 'Dutiful'
3
+
4
+ [[files]]
5
+ path = '.dutiful/config.toml'
data/db/fish.toml ADDED
@@ -0,0 +1,5 @@
1
+ [application]
2
+ name = 'Fish'
3
+
4
+ [[files]]
5
+ path = '.config/fish/config.fish'
data/db/git.toml ADDED
@@ -0,0 +1,5 @@
1
+ [application]
2
+ name = 'Git'
3
+
4
+ [[files]]
5
+ path = '.gitconfig'
data/db/iterm2.toml ADDED
@@ -0,0 +1,5 @@
1
+ [application]
2
+ name = 'iTerm2'
3
+
4
+ [[files]]
5
+ path = 'Library/Preferences/com.googlecode.iterm2.plist'
data/db/tmux.toml ADDED
@@ -0,0 +1,5 @@
1
+ [application]
2
+ name = 'tmux'
3
+
4
+ [[files]]
5
+ path = '.tmux.conf'
data/db/vim.toml ADDED
@@ -0,0 +1,8 @@
1
+ [application]
2
+ name = 'Vim'
3
+
4
+ [[files]]
5
+ path = '.vimrc'
6
+
7
+ [[files]]
8
+ path = '.gvimrc'
@@ -1,69 +1,54 @@
1
- module Dutiful
2
- class Application
3
- def initialize(path)
4
- @path = path
5
- end
1
+ class Dutiful::Application
2
+ def initialize(path)
3
+ @path = path
4
+ end
6
5
 
7
- def name
8
- content[:application][:name]
9
- end
6
+ def name
7
+ content[:application][:name]
8
+ end
10
9
 
11
- def files
12
- content[:files].map { |file| File.new file[:path] }
13
- end
10
+ def files
11
+ content[:files].map { |file| Dutiful::ApplicationFile.new file[:path] }
12
+ end
14
13
 
15
- def exist?
16
- files.any? &:exist?
17
- end
14
+ def exist?
15
+ files.any? &:exist?
16
+ end
18
17
 
19
- def sync
20
- files.each do |file|
21
- if file.exist?
22
- result = Dutiful::Config.storage.sync(file) if file.exist?
23
- yield file, result
24
- else
25
- yield file
26
- end
18
+ def sync
19
+ files.each do |file|
20
+ if file.exist? || file.has_backup?
21
+ result = Dutiful::Config.storage.sync(file)
22
+ yield file, result if block_given?
23
+ else
24
+ yield file if block_given?
27
25
  end
28
26
  end
27
+ end
29
28
 
30
- def to_s
31
- output = "#{name}:\n"
32
-
33
- files.each_with_index do |file, index|
34
- next unless file.exist?
35
-
36
- if file.synced?
37
- output << " #{file.path} ✔".green
38
- else
39
- output << " #{file.path} (pending)".yellow
40
- end
41
-
42
- output << "\n" if index < files.count
43
- end
29
+ def to_s
30
+ output = "#{name}:\n"
44
31
 
45
- output
46
- end
47
-
48
- def self.all
49
- Dir.foreach('db').map do |filename|
50
- next if filename == '.' or filename == '..'
32
+ output << files.map do |file|
33
+ " #{file}" if file.exist? || file.has_backup?
34
+ end.compact.join("\n")
35
+ end
51
36
 
52
- application = Dutiful::Application.new "db/#{filename}"
53
- application if application.exist?
54
- end.compact
55
- end
37
+ def self.all
38
+ Dir["#{Dutiful.dir}/db/*.toml"].map do |filename|
39
+ Dutiful::Application.new filename
40
+ end.compact
41
+ end
56
42
 
57
- def self.each
58
- return enum_for(:each) unless block_given?
43
+ def self.each
44
+ return enum_for(:each) unless block_given?
59
45
 
60
- all.each { |application| yield application }
61
- end
46
+ all.each { |application| yield application }
47
+ end
62
48
 
63
- private
49
+ private
64
50
 
65
- def content
66
- @content ||= Tomlrb.load_file(@path, symbolize_keys: true)
67
- end
51
+ def content
52
+ @content ||= Tomlrb.load_file(@path, symbolize_keys: true)
68
53
  end
69
54
  end
@@ -0,0 +1,46 @@
1
+ class Dutiful::ApplicationFile
2
+ attr_reader :full_path, :path
3
+
4
+ def initialize(path)
5
+ @path = path
6
+ @full_path = File.expand_path "~/#{path}"
7
+ end
8
+
9
+ def backup_path
10
+ Dutiful::Config.storage.path path
11
+ end
12
+
13
+ def backup_timestamp
14
+ File.mtime backup_path if has_backup?
15
+ end
16
+
17
+ def timestamp
18
+ File.mtime full_path if exist?
19
+ end
20
+
21
+ def exist?
22
+ File.exist? full_path
23
+ end
24
+
25
+ def has_backup?
26
+ Dutiful::Config.storage.exist? self
27
+ end
28
+
29
+ def synced?
30
+ has_backup? && Dutiful::Config.storage.synced?(self)
31
+ end
32
+
33
+ def to_s
34
+ if exist?
35
+ return "#{path} ✔".green if synced?
36
+
37
+ if has_backup?
38
+ return "#{path} (modified)".yellow
39
+ else
40
+ return "#{path} (pending backup)".yellow
41
+ end
42
+ end
43
+
44
+ "#{path} (pending restore)".yellow if has_backup?
45
+ end
46
+ end
@@ -0,0 +1,7 @@
1
+ class Dutiful::Command::List < Clamp::Command
2
+ def execute
3
+ puts "Storage: #{Dutiful::Config.storage.name}\n\n"
4
+
5
+ puts Dutiful::Application.all
6
+ end
7
+ end
@@ -0,0 +1,21 @@
1
+ class Dutiful::Command::Main < Clamp::Command
2
+ option ['-v', '--version'], :flag, 'Show version' do
3
+ puts "dutiful #{Dutiful::VERSION}"
4
+ exit 0
5
+ end
6
+
7
+ subcommand 'sync', 'Sync all preference files', Dutiful::Command::Sync
8
+ subcommand 'list', 'List all preference files', Dutiful::Command::List
9
+
10
+ subcommand 'restore', 'Restore all preference files' do
11
+ def execute
12
+ puts 'Not implemented yet'
13
+ end
14
+ end
15
+
16
+ subcommand 'which', 'Display the full path to a preference file' do
17
+ def execute
18
+ puts 'Not implemented yet'
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,23 @@
1
+ class Dutiful::Command::Sync < Clamp::Command
2
+ option ['-v', '--verbose'], :flag, 'Verbose mode'
3
+
4
+ def execute
5
+ puts "Storage: #{Dutiful::Config.storage.name}\n\n"
6
+
7
+ Dutiful::Application.each do |application|
8
+ puts "#{application.name}:\n"
9
+
10
+ application.sync do |file, result|
11
+ if result
12
+ if result.success?
13
+ puts " #{file.path} ✔".green
14
+ else
15
+ puts " #{file.path} ✖ - #{result.error}".red
16
+ end
17
+ else
18
+ puts " #{file.path} does not exist (skipping)".yellow if verbose?
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,6 @@
1
+ module Dutiful::Command; end
2
+
3
+ require 'clamp'
4
+ require 'dutiful/commands/list'
5
+ require 'dutiful/commands/sync'
6
+ require 'dutiful/commands/main'
@@ -1,5 +1,5 @@
1
1
  class Dutiful::Config
2
- PATH = ::File.expand_path '~/.dutiful/config.toml'
2
+ PATH = File.expand_path '~/.dutiful/config.toml'
3
3
 
4
4
  def self.storage
5
5
  @storage ||= if content[:storage]
@@ -15,6 +15,6 @@ class Dutiful::Config
15
15
  private
16
16
 
17
17
  def self.content
18
- @content ||= Tomlrb.load_file(PATH, symbolize_keys: true) || {}
18
+ @content ||= Tomlrb.load_file(PATH, symbolize_keys: true) rescue {}
19
19
  end
20
20
  end
@@ -2,59 +2,60 @@ require 'fileutils'
2
2
  require 'shellwords'
3
3
 
4
4
  class Dutiful::Storage
5
- attr_reader :content, :full_path, :path
5
+ attr_reader :name, :storage_path
6
6
 
7
7
  def initialize(name: nil, path: nil)
8
8
  name ||= 'Custom folder'
9
- path ||= Tomlrb.load_file("config/#{name.downcase}.toml", symbolize_keys: true)[:storage][:path]
9
+ path ||= Tomlrb.load_file("#{Dutiful.dir}/config/#{name.downcase}.toml", symbolize_keys: true)[:storage][:path]
10
10
 
11
- @content = {
12
- name: name,
13
- path: path
14
- }
11
+ @name = name
12
+ @storage_path = File.expand_path path
13
+ @path = "#{@storage_path}/dutiful"
15
14
  end
16
15
 
17
16
  def available?
18
- ::File.exist? path
17
+ File.exist? storage_path
19
18
  end
20
19
 
21
20
  def create_dir(file)
22
- file_directory_path = ::File.dirname "#{dutiful_path}/#{file.path}"
23
- `mkdir -p #{file_directory_path.shellescape}`
24
- end
25
-
26
- def dutiful_path
27
- "#{path}/dutiful"
21
+ FileUtils.mkdir_p File.dirname "#{path}/#{file.path}".shellescape
28
22
  end
29
23
 
30
24
  def exist?(file)
31
- ::File.exist? "#{dutiful_path}/#{file.path}"
25
+ File.exist? "#{path}/#{file.path}"
32
26
  end
33
27
 
34
- def name
35
- content[:name]
36
- end
37
-
38
- def path
39
- @path ||= ::File.expand_path content[:path]
28
+ def path(path = nil)
29
+ if path
30
+ "#{@path}/#{path}"
31
+ else
32
+ @path
33
+ end
40
34
  end
41
35
 
42
36
  def sync(file)
43
37
  create_dir file
44
- Rsync.run file.full_path.shellescape, "#{dutiful_path}/#{file.path}".shellescape
38
+
39
+ if file.exist?
40
+ if file.has_backup? && file.backup_timestamp > file.timestamp
41
+ Rsync.run file.backup_path.shellescape, file.full_path.shellescape
42
+ else
43
+ Rsync.run file.full_path.shellescape, file.backup_path.shellescape
44
+ end
45
+ else
46
+ Rsync.run file.backup_path.shellescape, file.full_path.shellescape
47
+ end
45
48
  end
46
49
 
47
50
  def synced?(file)
48
- FileUtils.identical? file.full_path, "#{dutiful_path}/#{file.path}"
51
+ FileUtils.identical? file.full_path, "#{path}/#{file.path}"
49
52
  end
50
53
 
51
54
  private
52
55
 
53
56
  def self.all
54
- Dir.foreach('config').map do |filename|
55
- next if filename == '.' or filename == '..'
56
-
57
- data = Tomlrb.load_file("config/#{filename}", symbolize_keys: true)[:storage]
57
+ Dir["#{Dutiful.dir}/config/*.toml"].map do |filename|
58
+ data = Tomlrb.load_file(filename, symbolize_keys: true)[:storage]
58
59
  Dutiful::Storage.new name: data[:name], path: data[:path]
59
60
  end.compact
60
61
  end
@@ -1,3 +1,3 @@
1
1
  module Dutiful
2
- VERSION = '0.0.2'
2
+ VERSION = '0.0.3'
3
3
  end
data/lib/dutiful.rb CHANGED
@@ -1,7 +1,13 @@
1
+ module Dutiful
2
+ def self.dir
3
+ File.dirname(__dir__)
4
+ end
5
+ end
6
+
1
7
  require 'dutiful/application'
2
- require 'dutiful/command'
8
+ require 'dutiful/application_file'
9
+ require 'dutiful/commands'
3
10
  require 'dutiful/config'
4
- require 'dutiful/file'
5
11
  require 'dutiful/storage'
6
12
  require 'colorize'
7
13
  require 'rsync'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dutiful
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bruno Pinto
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-22 00:00:00.000000000 Z
11
+ date: 2015-08-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: clamp
@@ -66,6 +66,34 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '1.1'
69
+ - !ruby/object:Gem::Dependency
70
+ name: fakefs
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.6'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.6'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.3'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.3'
69
97
  description: Dotfiles manager
70
98
  email: brunoferreirapinto@gmail.com
71
99
  executables:
@@ -74,11 +102,23 @@ extensions: []
74
102
  extra_rdoc_files: []
75
103
  files:
76
104
  - bin/dutiful
105
+ - config/dropbox.toml
106
+ - config/icloud.toml
107
+ - db/bundler.toml
108
+ - db/dutiful.toml
109
+ - db/fish.toml
110
+ - db/git.toml
111
+ - db/iterm2.toml
112
+ - db/tmux.toml
113
+ - db/vim.toml
77
114
  - lib/dutiful.rb
78
115
  - lib/dutiful/application.rb
79
- - lib/dutiful/command.rb
116
+ - lib/dutiful/application_file.rb
117
+ - lib/dutiful/commands.rb
118
+ - lib/dutiful/commands/list.rb
119
+ - lib/dutiful/commands/main.rb
120
+ - lib/dutiful/commands/sync.rb
80
121
  - lib/dutiful/config.rb
81
- - lib/dutiful/file.rb
82
122
  - lib/dutiful/storage.rb
83
123
  - lib/dutiful/version.rb
84
124
  homepage: http://github.com/bpinto/dutiful
@@ -104,5 +144,5 @@ rubyforge_project:
104
144
  rubygems_version: 2.4.5
105
145
  signing_key:
106
146
  specification_version: 4
107
- summary: dutiful-0.0.2
147
+ summary: dutiful-0.0.3
108
148
  test_files: []
@@ -1,52 +0,0 @@
1
- require 'clamp'
2
-
3
- class Dutiful::Command < Clamp::Command
4
- option ['-v', '--version'], :flag, 'Show version' do
5
- puts "dutiful #{Dutiful::VERSION}"
6
- exit 0
7
- end
8
-
9
- subcommand 'backup', 'Backup all preference files' do
10
- option ['-v', '--verbose'], :flag, 'Verbose mode'
11
-
12
- def execute
13
- puts "Storage: #{Dutiful::Config.storage.name}\n\n"
14
-
15
- Dutiful::Application.each do |application|
16
- puts "#{application.name}:\n"
17
-
18
- application.sync do |file, result|
19
- if result
20
- if result.success?
21
- puts " #{file.path} ✔".green
22
- else
23
- puts " #{file.path} ✖ - #{result.error}".red
24
- end
25
- else
26
- puts " #{file.path} does not exist (skipping)".yellow if verbose?
27
- end
28
- end
29
- end
30
- end
31
- end
32
-
33
- subcommand 'list', 'List all preference files' do
34
- def execute
35
- puts "Storage: #{Dutiful::Config.storage.name}\n\n"
36
-
37
- puts Dutiful::Application.all
38
- end
39
- end
40
-
41
- subcommand 'restore', 'Restore all preference files' do
42
- def execute
43
- puts 'Not implemented yet'
44
- end
45
- end
46
-
47
- subcommand 'which', 'Display the full path to a preference file' do
48
- def execute
49
- puts 'Not implemented yet'
50
- end
51
- end
52
- end
data/lib/dutiful/file.rb DELETED
@@ -1,18 +0,0 @@
1
- module Dutiful
2
- class File
3
- attr_reader :full_path, :path
4
-
5
- def initialize(path)
6
- @path = path
7
- @full_path = ::File.expand_path "~/#{path}"
8
- end
9
-
10
- def exist?
11
- ::File.exist? @full_path
12
- end
13
-
14
- def synced?
15
- Dutiful::Config.storage.exist?(self) && Dutiful::Config.storage.synced?(self)
16
- end
17
- end
18
- end