dotbox 1.0.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.
@@ -0,0 +1,2 @@
1
+ /pkg/
2
+ /tmp/
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
@@ -0,0 +1,43 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ backbox (1.0.0)
5
+ thor
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ aruba (0.5.1)
11
+ childprocess (~> 0.3.6)
12
+ cucumber (>= 1.1.1)
13
+ rspec-expectations (>= 2.7.0)
14
+ builder (3.2.0)
15
+ childprocess (0.3.8)
16
+ ffi (~> 1.0, >= 1.0.11)
17
+ cucumber (1.2.1)
18
+ builder (>= 2.1.2)
19
+ diff-lcs (>= 1.1.3)
20
+ gherkin (~> 2.11.0)
21
+ json (>= 1.4.6)
22
+ diff-lcs (1.2.1)
23
+ ffi (1.4.0)
24
+ gherkin (2.11.6)
25
+ json (>= 1.7.6)
26
+ json (1.7.7)
27
+ rspec (2.13.0)
28
+ rspec-core (~> 2.13.0)
29
+ rspec-expectations (~> 2.13.0)
30
+ rspec-mocks (~> 2.13.0)
31
+ rspec-core (2.13.0)
32
+ rspec-expectations (2.13.0)
33
+ diff-lcs (>= 1.1.3, < 2.0)
34
+ rspec-mocks (2.13.0)
35
+ thor (0.17.0)
36
+
37
+ PLATFORMS
38
+ ruby
39
+
40
+ DEPENDENCIES
41
+ aruba
42
+ backbox!
43
+ rspec
@@ -0,0 +1,41 @@
1
+ # Dotbox
2
+
3
+ Backup your dotfiles to dropbox and restore them easily.
4
+
5
+ ## Installation
6
+
7
+ ```
8
+ gem i dotbox
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```
14
+ $ dotbox -h
15
+ Tasks:
16
+ dotbox add # Backup the file
17
+ dotbox help [TASK] # Describe available tasks or one specific task
18
+ dotbox remove # Remove the backuped file
19
+ dotbox restore # Restore all backuped files
20
+ dotbox setup # Setup bakbox
21
+ ```
22
+
23
+ ## How does it works?
24
+
25
+ Assume that we have a file named `/home/meck/.zshrc`.
26
+
27
+ When you run `dotbox add .zshrc`, it equals running following commands:
28
+ ```
29
+ $ mv /home/meck/.zshrc /home/meck/Dropbox/Apps/Dotbox/.zshrc
30
+ $ ln -s /home/meck/Dropbox/Apps/Dotbox/.zshrc /home/meck/.zshrc
31
+ ```
32
+
33
+ When you run `dotbox remove .zshrc`, it equals running following commands:
34
+ ```
35
+ $ rm /home/meck/.zshrc
36
+ $ mv /home/meck/Dropbox/Apps/Dotbox/.zshrc /home/meck.zshrc
37
+ ```
38
+
39
+ When you run `dotbox restore` it will link all files in dropbox to their original postions.
40
+
41
+
@@ -0,0 +1,9 @@
1
+ require "bundler"
2
+ require "rspec/core/rake_task"
3
+
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task :default => :spec
9
+ task :test => :spec
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.expand_path("../../lib", __FILE__)
4
+
5
+ require 'dotbox/cli'
6
+
7
+ Dotbox::CLI.start
@@ -0,0 +1,17 @@
1
+ require File.expand_path("../lib/dotbox/version", __FILE__)
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "dotbox"
5
+ s.description = "Backup your dotfiles to dropbox and restore them easily."
6
+ s.summary = s.description
7
+ s.authors = ["Wei Zhu"]
8
+ s.email = ["yesmeck@gmail.com"]
9
+ s.files = `git ls-files`.split("\n")
10
+ s.homepage = "https://github.com/yesmeck/dotbox"
11
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
12
+ s.version = Dotbox::VERSION::STRING
13
+
14
+ s.add_dependency 'thor'
15
+ s.add_development_dependency 'aruba'
16
+ s.add_development_dependency 'rspec'
17
+ end
@@ -0,0 +1,29 @@
1
+ Feature: add file to dropbox
2
+
3
+ In order backup the file
4
+ As a user
5
+ I want to add the file to dropbox and link it back
6
+
7
+ @announce
8
+ Scenario: add a not exist file
9
+ When I run `dotbox add not_exist_file`
10
+ Then the stdout should contain "not exist"
11
+
12
+ @announce
13
+ Scenario: add a exists file
14
+ Given an empty file named "foo/bar"
15
+ When I run `dotbox add foo/bar`
16
+ Then a file named "dropbox/Apps/Dotbox/foo/bar" should exist
17
+ And the link named "foo/bar" should be a link of "dropbox/Apps/Dotbox/foo/bar"
18
+ And the record file should contain "foo/bar" => "file"
19
+
20
+ @announce
21
+ Scenario: add a directory
22
+ Given a directory named "foo/bar"
23
+ Given an empty file named "foo/bar/example"
24
+ When I run `dotbox add foo/bar`
25
+ Then a directory named "dropbox/Apps/Dotbox/foo/bar"
26
+ And a directory named "dropbox/Apps/Dotbox/foo/bar" should exist
27
+ And the link named "foo/bar" should be a link of "dropbox/Apps/Dotbox/foo/bar"
28
+ And the record file should contain "foo/bar" => "directory"
29
+
@@ -0,0 +1,48 @@
1
+ Feature: remove a file from dotbox
2
+
3
+ As a user
4
+ I want to remove a file from dotbox
5
+
6
+ @announce
7
+ Scenario: remove a not exist file
8
+ When I run `dotbox remove not_exist_file`
9
+ Then the stdout should contain "not exist"
10
+
11
+ @announce
12
+ Scenario: remove a not backuped file
13
+ Given an empty file named "foo/bar"
14
+ When I run `dotbox remove foo/bar`
15
+ Then the stdout should contain "not backuped"
16
+
17
+ @announce
18
+ Scenario: remove a backuped file
19
+ Given a backuped file named "foo/bar"
20
+ When I run `dotbox remove foo/bar`
21
+ Then a file named "dropbox/Apps/Dotbox/foo/bar" should not exist
22
+ And a file named "dropbox/Apps/Dotbox/foo" should not exist
23
+ And a file named "foo/bar" should exist
24
+ And the file named "foo/bar" should not be a link
25
+ And the record file should not contain "foo/bar"
26
+
27
+ @announce
28
+ Scenario: remove a backuped directory
29
+ Given a backuped directory named "foo/bar"
30
+ When I run `dotbox remove foo/bar`
31
+ Then a directory named "dropbox/Apps/Dotbox/foo/bar" should not exist
32
+ And a directory named "dropbox/Apps/Dotbox/foo" should not exist
33
+ And a directory named "foo/bar" should exist
34
+ And the directory named "foo/bar" should not be a link
35
+ And the record file should not contain "foo/bar"
36
+
37
+ @announce
38
+ Scenario: remove a backuped file in which directory has two files
39
+ Given a backuped file named "foo/bar"
40
+ And a backuped file named "foo/baz"
41
+ When I run `dotbox remove foo/bar`
42
+ Then a file named "dropbox/Apps/Dotbox/foo/bar" should not exist
43
+ And a file named "dropbox/Apps/Dotbox/foo/baz" should exist
44
+ And a file named "foo/bar" should exist
45
+ And the file named "foo/bar" should not be a link
46
+ And the record file should not contain "foo/bar"
47
+ And the record file should contain "foo/baz" => "file"
48
+
@@ -0,0 +1,16 @@
1
+ Feature: restore backuped files
2
+
3
+ I got a fresh system
4
+ In order to restore all my backuped files
5
+ I can use `dotbox restore`
6
+
7
+ @announce
8
+ Scenario: restore all backuped files
9
+ Given a backup file named "foo/bar"
10
+ Given a backup directory named "baz/bar"
11
+ When I run `dotbox restore`
12
+ Then a link named "foo/bar" should exist
13
+ And the link named "foo/bar" should be a link of "dropbox/Apps/Dotbox/foo/bar"
14
+ And a link named "baz/bar" should exist
15
+ And the link named "baz/bar" should be a link of "dropbox/Apps/Dotbox/baz/bar"
16
+
@@ -0,0 +1,15 @@
1
+ Feature: setup dotbox
2
+
3
+ This is my first time to use dotbox
4
+ So I want to setup it
5
+
6
+ @announce
7
+ Scenario: setup dotbox
8
+ Given a directory named "dropbox"
9
+ When I run `dotbox setup` interactively
10
+ And I type "dropbox"
11
+ Then a file named ".dotbox" should exist
12
+ And the file ".dotbox" should contain exactly:
13
+ """
14
+ dropbox
15
+ """
@@ -0,0 +1,65 @@
1
+ require 'dotbox'
2
+ require 'dotbox/config'
3
+ require 'dotbox/record'
4
+ require 'dotbox/api'
5
+
6
+ World(Aruba::Api)
7
+ World(Dotbox::Api)
8
+
9
+ Given /^a backuped file named "(.*?)"$/ do |path|
10
+ write_file(path, "")
11
+ in_current_dir do
12
+ create_backup(path)
13
+ end
14
+ end
15
+
16
+ Given /^a backuped directory named "(.*?)"$/ do |path|
17
+ in_current_dir do
18
+ _mkdir(path)
19
+ create_backup(path)
20
+ end
21
+ end
22
+
23
+ Given /^a backup file named "(.*?)"$/ do |path|
24
+ in_current_dir do
25
+ create_backup_file path
26
+ end
27
+ end
28
+
29
+ Given /^a backup directory named "(.*?)"$/ do |path|
30
+ in_current_dir do
31
+ create_backup_directory path
32
+ end
33
+ end
34
+
35
+
36
+ Then /^the link named "(.*?)" should be a link of "(.*?)"$/ do |link, file|
37
+ in_current_dir do
38
+ link_file = File.readlink(link) rescue nil
39
+ link_file.should == File.expand_path(file)
40
+ end
41
+ end
42
+
43
+ Then /^the (?:file|directory) named "(.*?)" should not be a link$/ do |path|
44
+ in_current_dir do
45
+ File.should_not be_symlink(path)
46
+ end
47
+ end
48
+
49
+ Then /^a link named "(.*?)" should exist$/ do |link|
50
+ in_current_dir do
51
+ File.should be_symlink(link)
52
+ end
53
+ end
54
+
55
+ Then /^the record file should contain "(.*?)" => "(.*?)"$/ do |path, type|
56
+ record = Dotbox::Record.new
57
+ record[path].should == type
58
+ end
59
+
60
+
61
+ Then /^the record file should not contain "(.*?)"$/ do |path|
62
+ record = Dotbox::Record.new
63
+ record[path].should be nil
64
+ end
65
+
@@ -0,0 +1,7 @@
1
+ require 'aruba/cucumber'
2
+ require 'cucumber/rspec/doubles'
3
+ require File.expand_path('../../../lib/dotbox/config.rb', __FILE__)
4
+
5
+ ENV['PATH'] = "#{File.expand_path('../../bin/dotbox', __FILE__)}#{File::PATH_SEPARATOR}#{ENV['PATH']}"
6
+ ENV['HOME'] = File.expand_path('../../../tmp/aruba', __FILE__)
7
+ ENV['DROPBOX_PATH'] = "#{ENV['HOME']}/dropbox"
@@ -0,0 +1,5 @@
1
+ require 'thor'
2
+
3
+ module Dotbox
4
+ CONFIG_FILE = "#{Thor::Util.user_home}/.dotbox"
5
+ end
@@ -0,0 +1,13 @@
1
+ module Dotbox
2
+ module Actions
3
+
4
+ def rm_empty_dir(path)
5
+ return nil if !::File.directory?(path)
6
+ if (Dir.entries(path) - %w{. ..}).empty?
7
+ FileUtils.rm_r path
8
+ rm_empty_dir ::File.dirname(path)
9
+ end
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,29 @@
1
+ require 'dotbox'
2
+ require 'dotbox/config'
3
+ require 'dotbox/record'
4
+ require 'dotbox/file'
5
+
6
+ module Dotbox
7
+ module Api
8
+
9
+ def create_backup(path)
10
+ file = Dotbox::File.new(path)
11
+ file.backup
12
+ Dotbox::Record.new.add file
13
+ end
14
+
15
+ def create_backup_file(path)
16
+ FileUtils.mkdir ::File.dirname(path)
17
+ FileUtils.touch path
18
+ create_backup path
19
+ FileUtils.rm path
20
+ end
21
+
22
+ def create_backup_directory(path)
23
+ FileUtils.mkdir_p path
24
+ create_backup path
25
+ FileUtils.rm_r path
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,75 @@
1
+ require 'dotbox'
2
+ require 'dotbox/config'
3
+ require 'dotbox/file'
4
+ require 'dotbox/record'
5
+
6
+ module Dotbox
7
+ class CLI < Thor
8
+
9
+ desc :setup, 'Setup bakbox'
10
+ def setup
11
+ dropbox_path = ask('Enter dropbox folder location:').strip
12
+ Dotbox::Config.new(Dotbox::CONFIG_FILE, dropbox_path)
13
+ end
14
+
15
+ desc :add, 'Backup the file'
16
+ def add(*pathes)
17
+ check_setup
18
+ @record = Record.new
19
+ pathes.each do |path|
20
+ path = ::File.expand_path(path)
21
+ if ::File.exists?(path)
22
+ file = File.new(path)
23
+ file.backup
24
+ @record.add file
25
+ else
26
+ say "#{path} not exists."
27
+ end
28
+ end
29
+ end
30
+
31
+ desc :remove, 'Remove the backuped file'
32
+ def remove(*pathes)
33
+ check_setup
34
+ @record = Record.new
35
+ pathes.each do |path|
36
+ path = ::File.expand_path(path)
37
+ file = File.new(path)
38
+ if !::File.exists?(path)
39
+ die "#{path} not exists."
40
+ elsif !file.backuped?
41
+ die "#{path} is not backuped."
42
+ end
43
+ file.remove
44
+ @record.remove file
45
+ end
46
+ end
47
+
48
+ desc :restore, 'Restore all backuped files'
49
+ def restore
50
+ check_setup
51
+ @record = Record.new
52
+ @record.each do |path|
53
+ file = File.new(path)
54
+ file.restore
55
+ end
56
+ end
57
+
58
+ def self.source_root
59
+ ::File.dirname(::File.expand_path('../../../bin/dotbox', __FILE__))
60
+ end
61
+
62
+ private
63
+ def check_setup
64
+ if !Config.new(Dotbox::CONFIG_FILE).setted?
65
+ die 'Use `bakbox setup` to setup dotbox first.'
66
+ end
67
+ end
68
+
69
+ def die(msg)
70
+ say msg
71
+ exit;
72
+ end
73
+
74
+ end
75
+ end
@@ -0,0 +1,31 @@
1
+ module Dotbox
2
+ class Config
3
+
4
+ def initialize(file, value = nil)
5
+ @file = file
6
+ if !value.nil?
7
+ save(value)
8
+ end
9
+ end
10
+
11
+ def value
12
+ if ENV['DROPBOX_PATH'].nil?
13
+ ::File.new(@file).read.strip.chomp('/')
14
+ else
15
+ ENV['DROPBOX_PATH']
16
+ end
17
+ end
18
+
19
+ def setted?
20
+ ::File.exists?(@file) || !ENV['DROPBOX_PATH'].nil?
21
+ end
22
+
23
+ private
24
+ def save(value)
25
+ f = ::File.new(@file, 'w+')
26
+ f.write(value)
27
+ f.close
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,63 @@
1
+ require 'dotbox/actions'
2
+
3
+ module Dotbox
4
+ class File
5
+
6
+ attr_reader :abs_path, :rel_path
7
+
8
+ include Dotbox::Actions
9
+
10
+ def initialize(path)
11
+ @abs_path = ::File.expand_path(path)
12
+ @rel_path = @abs_path.sub(/^#{Thor::Util.user_home}\//, '')
13
+ end
14
+
15
+ def directory?
16
+ ::File.directory?(@abs_path)
17
+ end
18
+
19
+ def backup_path
20
+ if @backup_path.nil?
21
+ backup_path = "#{Config.new(Dotbox::CONFIG_FILE).value}/Apps/Dotbox"
22
+ @backup_path = ::File.expand_path("#{backup_path}/#{@rel_path}")
23
+ end
24
+ @backup_path
25
+ end
26
+
27
+ def backup
28
+ FileUtils.mkdir_p ::File.dirname(backup_path)
29
+ FileUtils.mv @abs_path, backup_path
30
+ FileUtils.ln_s backup_path, @abs_path
31
+ end
32
+
33
+ def remove
34
+ # must get the backup path first
35
+ backup_path
36
+ FileUtils.rm @abs_path
37
+ FileUtils.mv backup_path, @abs_path
38
+ rm_empty_dir ::File.dirname(backup_path)
39
+ end
40
+
41
+ def restore
42
+ FileUtils.mkdir_p ::File.dirname(@abs_path)
43
+ FileUtils.ln_s backup_path, @abs_path
44
+ end
45
+
46
+ def backuped?
47
+ link? && link_of?(backup_path)
48
+ end
49
+
50
+ def link?
51
+ ::File.symlink? @abs_path
52
+ end
53
+
54
+ def link_of?(src)
55
+ ::File.readlink(@abs_path) == src
56
+ end
57
+
58
+ def type
59
+ @type = directory? ? 'directory' : 'file'
60
+ end
61
+
62
+ end
63
+ end
@@ -0,0 +1,43 @@
1
+ require 'yaml'
2
+ require 'dotbox/file'
3
+
4
+ module Dotbox
5
+ class Record
6
+
7
+ def initialize
8
+ @record_file_path = "#{Config.new(Dotbox::CONFIG_FILE).value}/Apps/Dotbox/.dotbox"
9
+ if !::File.exists?(@record_file_path)
10
+ FileUtils.mkdir_p(::File.dirname(@record_file_path))
11
+ FileUtils.touch(@record_file_path)
12
+ end
13
+ @records = YAML.load_file(@record_file_path) || {}
14
+ end
15
+
16
+ def add(file)
17
+ @records[file.rel_path] = file.type
18
+ save
19
+ end
20
+
21
+ def remove(file)
22
+ @records.delete file.rel_path
23
+ save
24
+ end
25
+
26
+ def save
27
+ record_file = ::File.new(@record_file_path, 'w+')
28
+ record_file.puts(YAML.dump(@records))
29
+ record_file.close
30
+ end
31
+
32
+ def [](path)
33
+ @records[path]
34
+ end
35
+
36
+ def each
37
+ @records.each do |path, type|
38
+ yield path
39
+ end
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,10 @@
1
+ module Dotbox
2
+ module VERSION
3
+ MAJOR = 1
4
+ MINOR = 0
5
+ PATCH = 0
6
+ BUILD = nil
7
+
8
+ STRING = [MAJOR, MINOR, PATCH, BUILD].compact.join('.');
9
+ end
10
+ end
metadata ADDED
@@ -0,0 +1,121 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dotbox
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Wei Zhu
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-03-02 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: thor
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: aruba
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: Backup your dotfiles to dropbox and restore them easily.
63
+ email:
64
+ - yesmeck@gmail.com
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - .gitignore
70
+ - Gemfile
71
+ - Gemfile.lock
72
+ - README.md
73
+ - Rakefile
74
+ - bin/dotbox
75
+ - dotbox.gemspec
76
+ - features/add.feature
77
+ - features/remove.feature
78
+ - features/restore.feature
79
+ - features/setup.feature
80
+ - features/step_definitions/file_steps.rb
81
+ - features/support/env.rb
82
+ - lib/dotbox.rb
83
+ - lib/dotbox/actions.rb
84
+ - lib/dotbox/api.rb
85
+ - lib/dotbox/cli.rb
86
+ - lib/dotbox/config.rb
87
+ - lib/dotbox/file.rb
88
+ - lib/dotbox/record.rb
89
+ - lib/dotbox/version.rb
90
+ homepage: https://github.com/yesmeck/dotbox
91
+ licenses: []
92
+ post_install_message:
93
+ rdoc_options: []
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ none: false
104
+ requirements:
105
+ - - ! '>='
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ requirements: []
109
+ rubyforge_project:
110
+ rubygems_version: 1.8.23
111
+ signing_key:
112
+ specification_version: 3
113
+ summary: Backup your dotfiles to dropbox and restore them easily.
114
+ test_files:
115
+ - features/add.feature
116
+ - features/remove.feature
117
+ - features/restore.feature
118
+ - features/setup.feature
119
+ - features/step_definitions/file_steps.rb
120
+ - features/support/env.rb
121
+ has_rdoc: