dutiful 0.0.2 → 0.0.3

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: 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