dotty 0.0.1

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.
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ coverage/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in dotty.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,110 @@
1
+ # Dotty
2
+
3
+ Dotty is a command line tool for managing your dotfiles (written in Ruby, using [Thor](https://github.com/wycats/thor/))
4
+
5
+ ## Features
6
+ * Store dotfiles in multiple git repositories
7
+ * Automate symlinking and other bootstrapping of dotfile repositories
8
+ * Support profiles so that it's easy to switch between sets of dotfiles
9
+ * Shows uncommited changes / unpushed commits for your dotfile repos
10
+ * Easily update submodules in your dotfile repos
11
+
12
+ ## How dotty interacts with dotty repositories
13
+
14
+ By using one or more of the approaches below, you instruct dotty on how it can boostrap and implode (opposite of bootstrap) your dotty repository.
15
+
16
+ ### dotfiles/
17
+
18
+ Dotty will symlink files and directories in the root your repos dotfiles/ directory, relative to ~.
19
+ You can symlink stuff to sub directories of ~ by using the in+subdir directory naming convention.
20
+
21
+ #### Example
22
+
23
+ dotfiles/.vim => ~/.vim
24
+ dotfiles/in+.ssh/config => ~/.ssh/config
25
+ dotfiles/in+a/in+b/c => ~/a/b/c
26
+
27
+
28
+ ### dotty-symlinks.yml
29
+
30
+ If you want more control over the symlinking, you can create a dotty-symlink.yml in the repo root.
31
+
32
+ #### Example
33
+
34
+ file_in_repo:filename_in_home_dir
35
+
36
+ ### dotty-repository.thor
37
+
38
+ If you want to do more than symlinking, you can create a dotty-repository.thor that implements the 'bootstrap' and 'implode' thor tasks.
39
+ The class must be named "DottyRepository".
40
+
41
+ #### Example
42
+
43
+ class DottyRepository < Thor
44
+ include Thor::Actions
45
+
46
+ desc "bootstrap", "Bootstrap this repo"
47
+ def bootstrap
48
+ # Do stuff here
49
+ end
50
+
51
+ desc "implode", "Implode this repo"
52
+ def implode
53
+ # Do stuff here
54
+ end
55
+ end
56
+
57
+ ## Installation / usage
58
+
59
+ gem install dotty
60
+
61
+ ### Requirements
62
+ * ruby (tested on 1.9.2) and rubygems
63
+ * git (the git executable must be in your $PATH)
64
+
65
+ Note: I had graphviz installed via brew, which has a 'dotty' executable. I fixed this by doing "mv /usr/local/bin/dotty{,.graphviz}"
66
+
67
+ $ dotty
68
+
69
+ Tasks:
70
+ dotty add <name> <git repo url> # Add existing dotty git repository
71
+ dotty bootstrap [name] # Bootstrap specified or all dotty repositories. Usually involves making symlinks in your home dir.
72
+ dotty create <name> <git repo url> # Create a new git repository with the specified git repo url as origin
73
+ dotty create_profile <profile name> # Create a new profile
74
+ dotty execute [repo name] <command to run> # For specified or all repositories, run given command
75
+ dotty help [TASK] # Describe available tasks or one specific task
76
+ dotty implode [name] # Opposite of bootstrap
77
+ dotty import_repos <yaml_file_location> # Imports dotty repositories from the specified yaml file location (http works)
78
+ dotty list # List installed dotty repositories
79
+ dotty profile [profile name] # Switch to given profile or show current profile if no profile name is given
80
+ dotty profiles # List profiles
81
+ dotty remove <name> # Remove dotty repository
82
+ dotty remove_profile <profile name> # Remove given profile
83
+ dotty update [name] # Update specified or all dotty repositories
84
+ dotty update_submodules [name] # For specified or all repositories, for submodules and pull
85
+
86
+ ### Creating an example dotty repository
87
+
88
+ $ dotty create dotty-test git@github.com:trym/dotty-test
89
+
90
+ create repo dotty-test [git@github.com:trym/dotty-test]
91
+ run git init /Users/trym/.dotty/default/dotty-test from "."
92
+ Initialized empty Git repository in /Users/trym/.dotty/default/dotty-test/.git/
93
+ run git remote add origin git@github.com:trym/dotty-test from "./.dotty/default/dotty-test"
94
+ create .dotty/default/dotty-test/dotfiles
95
+ create .dotty/default/dotty-test/README.md
96
+
97
+ $ cd ~/.dotty/default/dotty-test
98
+ $ touch dotfiles/testfile
99
+ $ dotty bootstrap dotty-test
100
+ bootstrap dotty-test
101
+ create sers/trym/testfile
102
+
103
+ $ ls -al ~/testfile
104
+ lrwxr-xr-x 1 trym staff 55 May 3 01:05 /Users/trym/testfile -> /Users/trym/.dotty/default/dotty-test/dotfiles/testfile
105
+
106
+ $ dotty implode dotty-test
107
+ implode dotty-test
108
+ remove /Users/trym/testfile
109
+
110
+
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
data/bin/dotty ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ #$:.unshift(File.dirname(__FILE__) + '/../lib') unless $:.include?(File.dirname(__FILE__) + '/../lib')
3
+ require "dotty"
4
+
5
+ Dotty::App.start
data/dotty.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path('../lib', __FILE__)
3
+ require 'dotty/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'dotty'
7
+ s.version = Dotty::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ['Trym Skaar']
10
+ s.email = ['trym@tryms.no']
11
+ s.homepage = 'http://github.com/trym/dotty'
12
+ s.summary = %q{Dotfile manager using git repositories}
13
+ s.description = %q{Command line tool for easily managing your dotfile git repositories}
14
+
15
+ s.rubyforge_project = "dotty"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ['lib']
21
+
22
+ s.add_dependency 'thor'
23
+ s.add_dependency 'hashie'
24
+
25
+ s.add_development_dependency 'rspec', '>= 2.6.0.rc4'
26
+ s.add_development_dependency 'simplecov', '>= 0.4.0'
27
+ end
data/lib/dotty/app.rb ADDED
@@ -0,0 +1,150 @@
1
+ module Dotty
2
+ class App < Thor
3
+ include Thor::Actions
4
+ include Dotty::Helpers
5
+
6
+ ROOT_PATH = File.expand_path(File.join Thor::Util.user_home, '.dotty')
7
+ source_root File.join(File.dirname(__FILE__), '../../templates')
8
+
9
+ desc "list", "List installed dotty repositories"
10
+ def list
11
+ say "Installed dotty repositories for profile '#{Profile::current_profile}'", :blue
12
+ say "\n"
13
+ if Repository.list.empty?
14
+ say "No repositories here. Use 'create', 'add' or 'import_repos' to get going.", :yellow
15
+ else
16
+ table = Repository.list.collect do |repo|
17
+ git_changes = repo.git_status.size > 0 ? shell.set_color(" [#{repo.git_status.size} uncomitted changes]", :red) : ""
18
+ git_changes += shell.set_color(" [unpushed commits]", :red) if repo.unpushed_changes?
19
+ [repo.name, repo.url + git_changes]
20
+ end
21
+ print_table table, :ident => 2, :colwidth => 20
22
+ end
23
+ say "\n"
24
+ end
25
+
26
+ desc "add <name> <git repo url>", "Add existing dotty git repository"
27
+ def add(repo_name, url)
28
+ Repository.add_existing_repository repo_name, url
29
+ end
30
+
31
+ desc "create <name> <git repo url>", "Create a new git repository with the specified git repo url as origin"
32
+ def create(repo_name, repo_url)
33
+ repo = Dotty::Repository.create_repository(repo_name, repo_url)
34
+ empty_directory File.join(repo.local_path, 'dotfiles')
35
+ copy_file "README.md", File.join(repo.local_path, 'README.md')
36
+ end
37
+
38
+ desc "remove <name>", "Remove dotty repository"
39
+ def remove(repo_name)
40
+ find_repo!(repo_name).destroy
41
+ end
42
+
43
+ desc "update [name]", "Update specified or all dotty repositories"
44
+ def update(repo_name=nil)
45
+ for_specified_or_all_repos(repo_name) do |repo|
46
+ actions.update repo
47
+ end
48
+ end
49
+
50
+ desc "bootstrap [name]", "Bootstrap specified or all dotty repositories. Usually involves making symlinks in your home dir."
51
+ def bootstrap(repo_name=nil)
52
+ for_specified_or_all_repos(repo_name) do |repo|
53
+ actions.bootstrap repo
54
+ end
55
+ end
56
+
57
+ desc "implode [name]", "Opposite of bootstrap"
58
+ def implode(repo_name=nil)
59
+ for_specified_or_all_repos(repo_name) do |repo|
60
+ actions.implode repo
61
+ end
62
+ end
63
+
64
+ desc "update_submodules [name]", "For specified or all repositories, for submodules and pull"
65
+ method_options :push => false
66
+ method_options :commit => true
67
+ method_options :ignoredirty => false
68
+ def update_submodules(repo_name=nil)
69
+ for_specified_or_all_repos(repo_name) do |repo|
70
+ actions.invoke :update_submodules, [repo], options
71
+ end
72
+ end
73
+
74
+ desc "execute [repo name] <command to run>", "For specified or all repositories, run given command"
75
+ def execute(repo_name=nil, command)
76
+ for_specified_or_all_repos(repo_name) do |repo|
77
+ inside repo.local_path do
78
+ run command
79
+ say "\n"
80
+ end
81
+ end
82
+ end
83
+
84
+ desc "import_repos <yaml_file_location>", "Imports dotty repositories from the specified yaml file location (http works)"
85
+ def import_repos(location)
86
+ say_status "import yaml", "Importing dotty repositories from '#{location}'", :blue
87
+ Repository.import location
88
+ end
89
+
90
+ desc "profile [profile name]", "Switch to given profile or show current profile if no profile name is given"
91
+ def profile(name=nil)
92
+ if name.nil?
93
+ say "Current dotty profile: " + shell.set_color(Profile.current_profile, :blue)
94
+ else
95
+ name = name.downcase
96
+ Profile.find!(name)
97
+ say_status "profile", "Changing to profile '#{name}'"
98
+ implode # Implode all repos for current profile
99
+ Repository.repositories = nil # Force reload of repositories
100
+ Profile.current_profile = name
101
+ Profile.write_yaml
102
+ bootstrap # Bootstrap repos for the profile we changed to
103
+ end
104
+ end
105
+
106
+ desc "profiles", "List profiles"
107
+ def profiles
108
+ say "DOTTY PROFILES\n", :blue
109
+ profile_names = Profile.profiles
110
+ profile_names << 'default' if profile_names.empty?
111
+ profile_names.each do |profile_name|
112
+ with_padding do
113
+ say Profile.current_profile == profile_name ? shell.set_color('* ' + profile_name, :green) : profile_name
114
+ end
115
+ end
116
+ end
117
+
118
+ desc "create_profile <profile name>", "Create a new profile"
119
+ def create_profile(name)
120
+ say_status "create", "Create profile '#{name}'"
121
+ Profile.create name
122
+ end
123
+
124
+ desc "remove_profile <profile name>", "Remove given profile"
125
+ def remove_profile(name)
126
+ say_status "remove", "Removing profile '#{name}'"
127
+ Profile.remove name
128
+ end
129
+
130
+ protected
131
+
132
+ def find_repo!(name)
133
+ Repository.find(name.downcase) || raise(RepositoryNotFoundError, "The specified repository does not exist")
134
+ end
135
+
136
+ def actions
137
+ @actions ||= RepositoryActions.new
138
+ end
139
+
140
+ def for_specified_or_all_repos(repo_name=nil)
141
+ if repo_name
142
+ yield find_repo!(repo_name.downcase)
143
+ else
144
+ Repository.list.each { |repo| yield repo }
145
+ end
146
+ end
147
+
148
+
149
+ end
150
+ end
@@ -0,0 +1,19 @@
1
+ module Dotty
2
+ module Helpers
3
+ def error(message, halt=true)
4
+ exit if halt
5
+ end
6
+
7
+ def remove_symlink(path)
8
+ if File.exist? path
9
+ say_status "remove", path
10
+ if File.symlink? path
11
+ File.delete path
12
+ else
13
+ say_status "error", "#{path} is not a symlink - not removing"
14
+ end
15
+ end
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,57 @@
1
+ module Dotty
2
+ class Profile
3
+ YAML_PATH = File.join(App::ROOT_PATH, '.profiles.yml')
4
+
5
+ class << self
6
+ attr_accessor :current_profile, :profile_data
7
+
8
+ def create(name)
9
+ profile_data['profiles'].merge!(name => {})
10
+ write_yaml
11
+ end
12
+
13
+ def remove(name)
14
+ find!(name)
15
+ @current_profile = profile_data['current_profile'] = nil
16
+ profile_data['profiles'].delete name
17
+ write_yaml
18
+ end
19
+
20
+ def profile_data
21
+ @profile_data ||= read_yaml || { 'profiles' => {} }
22
+ end
23
+
24
+ def current_profile
25
+ @current_profile ||= profile_data['current_profile'] || profiles.first || 'default'
26
+ end
27
+
28
+ def profiles
29
+ profile_data['profiles'] && profile_data['profiles'].keys or []
30
+ end
31
+
32
+ def current_profile_data
33
+ profile_data['profiles'][current_profile] or {}
34
+ end
35
+
36
+ def read_yaml
37
+ File.exist?(YAML_PATH) && YAML::load(File.open YAML_PATH)
38
+ end
39
+
40
+ def write_yaml
41
+ profile_data['current_profile'] = current_profile
42
+ (profile_data['profiles'][current_profile] ||= {}).merge!(
43
+ 'repositories' => Repository.list.inject({}) { |hsh, repo| hsh.merge(repo.name => { 'url' => repo.url }) }
44
+ )
45
+ FileUtils.mkdir_p App::ROOT_PATH unless File.directory?(App::ROOT_PATH)
46
+ File.open(YAML_PATH, 'w') do |f|
47
+ f.write profile_data.to_yaml
48
+ end
49
+ end
50
+
51
+ def find!(name)
52
+ profile_data['profiles'] && profile_data['profiles'][name] or raise Dotty::Error, "Profile '#{name}' does not exist"
53
+ end
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,141 @@
1
+ module Dotty
2
+ class Repository
3
+ YAML_PATH = File.join(App::ROOT_PATH, '.repos.yml')
4
+
5
+ attr_accessor :name, :url
6
+
7
+ class << self
8
+ attr_accessor :repositories
9
+
10
+ def add_existing_repository(name, url)
11
+ repo = add_repository(name, url)
12
+ actions.checkout(repo)
13
+ actions.bootstrap(repo)
14
+ return repo
15
+ end
16
+
17
+ def add_repository(name, url)
18
+ unless Repository.find(name).nil?
19
+ raise Dotty::Error, "There is already a repository with that name"
20
+ end
21
+ repo = self.new(name, url)
22
+ list << repo
23
+ Profile::write_yaml
24
+ return repo
25
+ end
26
+
27
+ def create_repository(name, url)
28
+ repo = add_repository(name, url)
29
+ actions.create(repo)
30
+ return repo
31
+ end
32
+
33
+ def list
34
+ @repositories ||= (Profile.current_profile_data['repositories'] || {}).collect{ |name, options| Repository.new(name, options['url']) }
35
+ end
36
+
37
+ def find(name)
38
+ list.detect{ |repo| repo.name == name }
39
+ end
40
+
41
+ def actions
42
+ @actions ||= Dotty::RepositoryActions.new
43
+ end
44
+
45
+ def import(location)
46
+ repositories = YAML::load(open(location).read) || {}
47
+ if repositories.empty?
48
+ error "Didn't find any repositories at '#{location}'"
49
+ end
50
+ repositories.keys.each do |name|
51
+ if find(name)
52
+ puts "Not adding '#{name}', a repository with that name already exists"
53
+ next
54
+ end
55
+ add_existing_repository(name, repositories[name]['url'])
56
+ end
57
+ end
58
+
59
+ end
60
+
61
+ def initialize(name, url)
62
+ unless name =~ /^[a-zA-Z0-9\.\-\_]+$/
63
+ raise InvalidRepositoryNameError, "Repository name can only contain letters, numbers and the following characters: .-_"
64
+ end
65
+ @name = name
66
+ @url = url
67
+ end
68
+
69
+ def local_path
70
+ File.join(Dotty::App::ROOT_PATH, Profile::current_profile, @name)
71
+ end
72
+
73
+ def symlinks
74
+ symlinks_from_dotfiles_directories.merge symlinks_from_yaml
75
+ end
76
+
77
+ def symlinks_from_yaml
78
+ symlink_file_path = File.join(local_path, 'dotty-symlinks.yml')
79
+ File.exist?(symlink_file_path) && YAML::load(File.open symlink_file_path) or {}
80
+ end
81
+
82
+ def symlinks_from_dotfiles_directories
83
+ hsh = {}
84
+ Dir.glob(File.join local_path, '*dotfiles/') do |dotfiles_directory|
85
+ dotfiles_directory = Pathname.new(dotfiles_directory)
86
+
87
+ # 'root' files
88
+ dotfiles_directory.children.each do |path|
89
+ next if path.basename.to_s =~ /^in\+/
90
+ source = path.relative_path_from(Pathname.new local_path).to_s
91
+ target = path.relative_path_from(dotfiles_directory).to_s
92
+ hsh.merge!(source => target)
93
+ end
94
+
95
+ # stuff in in+XXX directories
96
+ Dir.glob(File.join(dotfiles_directory.to_s , 'in+*/**/*'), File::FNM_DOTMATCH).each do |path|
97
+ next if path =~ %r([\.]{2}) or path =~ %r(/\.$) # Remove BS entries like dotfiles/../otherstuff TODO: do it in a better way
98
+ path = Pathname.new(path)
99
+ next if path.basename.to_s =~ /^in\+/ # We dont want to do anything with the 'placeholder' directories
100
+ source = path.relative_path_from(Pathname.new local_path).to_s
101
+ target = path.relative_path_from(Pathname.new dotfiles_directory).to_s.gsub('in+', '')
102
+ hsh.merge!(source => target)
103
+ end
104
+ end
105
+ return hsh
106
+ end
107
+
108
+ def git_status
109
+ # TODO use --json when more people have a git that supports it
110
+ git_status_output.split("\n").inject({}) do |hsh, line|
111
+ change_type, file = line[0..1], line[3..-1]
112
+ hsh.merge(file => change_type)
113
+ end
114
+ end
115
+
116
+ def unpushed_changes?
117
+ txt = 'Your branch is ahead of'
118
+ `cd #{local_path} && git status | grep '#{txt}' 2>&1`.include?(txt)
119
+ end
120
+
121
+ def git_status_output
122
+ `cd #{local_path} && git status --porcelain`
123
+ end
124
+
125
+ def has_thor_task?
126
+ File.exist? File.join(local_path, 'dotty-repository.thor')
127
+ end
128
+
129
+ def invoke_action(action, *args)
130
+ self.class.actions.invoke action, args
131
+ end
132
+
133
+ def destroy
134
+ Repository.repositories.reject! { |repo| repo.name == name }
135
+ Dotty::Profile.write_yaml
136
+ Repository.actions.destroy self
137
+ self
138
+ end
139
+
140
+ end
141
+ end
@@ -0,0 +1,110 @@
1
+ module Dotty
2
+ class RepositoryActions < Thor
3
+ USER_HOME = Thor::Util.user_home
4
+
5
+ include Thor::Actions
6
+ include Dotty::Helpers
7
+
8
+ desc "create <repo instance>", "create repository"
9
+ def create(repo)
10
+ say_status "create repo", "#{repo.name} [#{repo.url}]", :blue
11
+ FileUtils.mkdir_p repo.local_path
12
+ run "git init #{repo.local_path}"
13
+ inside repo.local_path do
14
+ run "git remote add origin #{repo.url}"
15
+ end
16
+ end
17
+
18
+ desc "destroy <repo instance>", "remove repository"
19
+ def destroy(repo)
20
+ say_status "remove repo", repo.name, :blue
21
+ implode repo
22
+ say_status "remove", repo.local_path
23
+ FileUtils.rm_rf repo.local_path
24
+ end
25
+
26
+ desc "checkout <repo instance>", "add repository"
27
+ def checkout(repo)
28
+ say_status "add repo", "#{repo.name} => #{repo.url}", :blue
29
+ FileUtils.mkdir_p repo.local_path
30
+ run "git clone #{repo.url} #{repo.local_path}"
31
+ inside repo.local_path do
32
+ run "git submodule update --init"
33
+ end
34
+ end
35
+
36
+ desc "bootstrap <repo instance>", "bootstrap repository"
37
+ def bootstrap(repo)
38
+ say_status "bootstrap", repo.name, :blue
39
+ with_padding do
40
+ # Create symlinks defined in dotty-symlinks.yml
41
+ repo.symlinks.each do |source, destination_filename|
42
+ create_link File.join(USER_HOME, destination_filename), File.join(repo.local_path, source)
43
+ end
44
+
45
+ # Execute repository's bootstrap task
46
+ thor_file_path = File.join(repo.local_path, 'dotty-repository.thor')
47
+ if File.exist? thor_file_path
48
+ inside repo.local_path do
49
+ run "thor dotty_repository:bootstrap"
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ desc "implode <repo instance>", "implode repository"
56
+ def implode(repo)
57
+ say_status "implode", repo.name, :blue
58
+
59
+ # Remove symlinks defined in dotty-symlinks.yml
60
+ repo.symlinks.each do |source, destination_filename|
61
+ destination_path = File.join(USER_HOME, destination_filename)
62
+ remove_symlink destination_path
63
+ end
64
+
65
+ # Execute repository's implode task
66
+ thor_file_path = File.join(repo.local_path, 'dotty-repository.thor')
67
+ if File.exist? thor_file_path
68
+ inside repo.local_path do
69
+ run "thor dotty_repository:implode"
70
+ end
71
+ end
72
+ end
73
+
74
+ desc "update <repo instance>", "update repository"
75
+ def update(repo)
76
+ say_status "update", repo.name, :blue
77
+
78
+ inside repo.local_path do
79
+ run "git fetch && git pull && git submodule update --init"
80
+ end
81
+ end
82
+
83
+ desc "update_submodules", "update repository's submodules"
84
+ method_options :ignoredirty => false
85
+ method_options %w(commit_message -m) => "Updated submodules"
86
+ method_options :commit => true
87
+ method_options :push => false
88
+ def update_submodules(repo)
89
+ say "update submodules", repo.name, :blue
90
+
91
+ inside repo.local_path do
92
+ cmd = []
93
+ cmd << "git submodule update --init"
94
+ cmd << "git submodule foreach git pull origin master"
95
+ if options[:commit]
96
+ changes = run('git status -s', :capture => true)
97
+ if options[:ignoredirty] or [nil, ""].include?(changes)
98
+ cmd << "git commit -am '#{options[:commit_message]}'"
99
+ else
100
+ raise Dotty::Error, "Repository '#{repo.name}' is not in a clean state - cannot commit updated submodules"
101
+ end
102
+ end
103
+ options[:push] && cmd << "git push"
104
+ run cmd.join(" && ")
105
+ end
106
+ end
107
+
108
+
109
+ end
110
+ end
@@ -0,0 +1,3 @@
1
+ module Dotty
2
+ VERSION = "0.0.1"
3
+ end
data/lib/dotty.rb ADDED
@@ -0,0 +1,18 @@
1
+ # encoding: utf-8
2
+
3
+ require 'yaml'
4
+ require 'hashie'
5
+ require 'thor'
6
+ require 'pathname'
7
+
8
+ require 'dotty/helpers'
9
+ require 'dotty/app'
10
+ require 'dotty/profile'
11
+ require 'dotty/repository'
12
+ require 'dotty/repository_actions'
13
+
14
+ module Dotty
15
+ class Error < StandardError; end
16
+ class RepositoryNotFoundError < Error; end
17
+ class InvalidRepositoryNameError < Error; end
18
+ end