sheldon 0.2.6
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 +7 -0
- data/LICENSE +21 -0
- data/README.md +86 -0
- data/bin/sheldon +75 -0
- data/lib/sheldon.rb +7 -0
- data/lib/sheldon/brain.rb +51 -0
- data/lib/sheldon/builder.rb +28 -0
- data/lib/sheldon/helpers.rb +18 -0
- data/lib/sheldon/memory.rb +34 -0
- data/lib/sheldon/sheldon.rb +35 -0
- metadata +109 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: bc997c5b4f37ad9017e95676da13f93ccda540c2
|
4
|
+
data.tar.gz: 3597991837046118327d7a54d29bac5c648755c5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fdf2d411262be96f41d48f8c09d49e89214d5cc66adcbacdf6f4501e84e709d45145df515a687d43096857a619c774b5b776ad16024757129875d5aa8374ab43
|
7
|
+
data.tar.gz: 9b20b0a6110eb0f7210314f00c80d26c2302d70c411bd2ceea67a994ce3c9bf250d1dc9aa2df2489eae49b4cf53431a10bd488ff032e967fdcc64f2d721ad95b
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 David V Jones
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
# Sheldon
|
2
|
+
[](https://travis-ci.org/dvjones89/sheldon)
|
3
|
+
|
4
|
+
Designed with the obsessive developer in mind, Sheldon makes it easy for you to manage your .dotfiles and configs across all your OS X / linux devices.
|
5
|
+
|
6
|
+
### How It Works
|
7
|
+
#### Add files/folders to Sheldon (sheldon learn)
|
8
|
+
Teach Sheldon about new files or directories using the `learn` command:
|
9
|
+
```shell
|
10
|
+
sheldon learn ~/.gitconfig
|
11
|
+
Recall Cue For File/Folder: git
|
12
|
+
```
|
13
|
+
|
14
|
+
Sheldon will move the original file/directory into his data directory (defaults to `~/sheldon`) and symlink back to it's original location.
|
15
|
+
```shell
|
16
|
+
ls -al ~ | grep .gitconfig
|
17
|
+
.gitconfig -> /Users/dave/sheldon/git/.gitconfig
|
18
|
+
```
|
19
|
+
Keep Sheldon's data directory synchronised across all your devices using your tool of choice, Dropbox, Google Drive, BTSync.
|
20
|
+
|
21
|
+
#### Recall your files on other machines (sheldon recall)
|
22
|
+
Sheldon's `recall` command will symlink the file from the data directory to it's correct location on any filesystem (even under different home directories):
|
23
|
+
|
24
|
+
```shell
|
25
|
+
sheldon recall git
|
26
|
+
|
27
|
+
ls -al ~ | grep .gitconfig
|
28
|
+
.gitconfig -> /Users/john/sheldon/git/.gitconfig
|
29
|
+
```
|
30
|
+
|
31
|
+
Pass the `-i` flag to Sheldon's `recall` command for interactive mode:
|
32
|
+
```shell
|
33
|
+
sheldon recall -i
|
34
|
+
Recall git_config (Y/N): y
|
35
|
+
Recall .zshrc (Y/N): y
|
36
|
+
```
|
37
|
+
|
38
|
+
#### Build Bespoke Configs For Your Host (sheldon build)
|
39
|
+
Sometimes copying an entire config file between all your machine is overkill. What if you only want a subset of your configuration? Sheldon can help.
|
40
|
+
|
41
|
+
Split your ssh config into `config_work` and `config_personal`
|
42
|
+
|
43
|
+
Use Sheldon `learn` and `recall` to make the appropriate `_config` files available on the appropriate hosts.
|
44
|
+
|
45
|
+
Once the files are in the right place, use Sheldon `build` to create a single `config` file that can be easily sourced.
|
46
|
+
|
47
|
+
```shell
|
48
|
+
cd ~/.ssh
|
49
|
+
|
50
|
+
ls -l
|
51
|
+
config_dev -> /Users/dave/sheldon/ssh_config_dev/config_dev
|
52
|
+
config_personal -> /Users/dave/sheldon/ssh_config_personal/config_personal
|
53
|
+
|
54
|
+
sheldon build ~/.ssh
|
55
|
+
💥 Sheldon💥 Built .ssh
|
56
|
+
|
57
|
+
ls -l
|
58
|
+
config_dev -> /Users/dave/sheldon/ssh_config_dev/config_dev
|
59
|
+
config_personal -> /Users/dave/sheldon/ssh_config_personal/config_personal
|
60
|
+
config
|
61
|
+
|
62
|
+
source ~/.ssh/config
|
63
|
+
```
|
64
|
+
|
65
|
+
### Installation:
|
66
|
+
1) `gem install Sheldon-<version>.gem`
|
67
|
+
|
68
|
+
2) Sync Sheldon's data directory (`~/sheldon` by default) across all of your machines. You can override the default folder location by setting the`SHELDON_DATA_DIR` environment variable on each host.
|
69
|
+
|
70
|
+
### Isn't This Just Homesick?
|
71
|
+
Yes, yes it is. Unfortunately, I'd written 90% of Sheldon before I discovered the awesome [homesick](https://github.com/technicalpickles/homesick) so I decided to keep going.
|
72
|
+
Sheldon's `build` command is (as far as I know) unique to Sheldon and will perhaps prove useful to those who chunk their configs.
|
73
|
+
If nothing else, I hope this code will be a good point of reference for other developers (and indeed my future self).
|
74
|
+
|
75
|
+
### Contributing
|
76
|
+
|
77
|
+
1. Fork it ( https://github.com/[your-github-username]/sheldon/fork )
|
78
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
79
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
80
|
+
4. Make sure you haven't broken anything `bundle exec rspec`
|
81
|
+
5. Add your own specs for your new feature
|
82
|
+
6. Push to the branch (`git push origin my-new-feature`)
|
83
|
+
7. Create a new Pull Request
|
84
|
+
|
85
|
+
### License
|
86
|
+
See LICENSE
|
data/bin/sheldon
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "thor"
|
3
|
+
require_relative "../lib/sheldon"
|
4
|
+
|
5
|
+
module CLI
|
6
|
+
class Sheldon < Thor
|
7
|
+
map link: :recall
|
8
|
+
map ls: :list
|
9
|
+
|
10
|
+
desc "build path", "Tell Sheldon to build all config_ files in a directory to single master config"
|
11
|
+
def build(rel_path_to_target)
|
12
|
+
abs_learn_path = File.expand_path(rel_path_to_target)
|
13
|
+
sheldon.build(abs_learn_path)
|
14
|
+
announce("Built #{File.basename(rel_path_to_target)}")
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "learn path", "Add a new file/folder to Sheldon's brain. Supply a recall_cue at runtime."
|
18
|
+
def learn(rel_path_to_target)
|
19
|
+
abs_learn_path = File.expand_path(rel_path_to_target)
|
20
|
+
recall_cue = prompt_user("Recall Cue For File/Folder")
|
21
|
+
sheldon.learn(recall_cue, abs_learn_path)
|
22
|
+
end
|
23
|
+
|
24
|
+
desc "recall recall_cue", "Symlink a previously learnt file/directory to it's original location on the filesystem.\nUse `sheldon list` for available cues."
|
25
|
+
option :i, type: :boolean, desc: "Interactive mode - prompts Y/N for each available recall_cue"
|
26
|
+
|
27
|
+
def recall(recall_cue=nil)
|
28
|
+
if options[:i]
|
29
|
+
sheldon.list_cues.each do |recall_cue|
|
30
|
+
answer = prompt_user("Recall #{recall_cue}? (Y/N)")
|
31
|
+
sheldon.recall(recall_cue) if answer.downcase == "y"
|
32
|
+
end
|
33
|
+
else
|
34
|
+
recall_cue ||= prompt_user("Recall Cue For File/Folder")
|
35
|
+
sheldon.recall(recall_cue)
|
36
|
+
end
|
37
|
+
|
38
|
+
announce("Recall Complete.")
|
39
|
+
end
|
40
|
+
|
41
|
+
desc "list", "List all recall cues known by Sheldon"
|
42
|
+
def list
|
43
|
+
puts sheldon.list_cues
|
44
|
+
end
|
45
|
+
|
46
|
+
desc "version", "Prints the current version of Sheldon"
|
47
|
+
def version
|
48
|
+
announce ::Sheldon::VERSION
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def prompt_user(prompt)
|
54
|
+
print(prompt + ": ")
|
55
|
+
STDIN.gets.chomp
|
56
|
+
end
|
57
|
+
|
58
|
+
def announce(message)
|
59
|
+
logo = "💥".encode("utf-8")
|
60
|
+
puts logo + " Sheldon" + logo + " #{message}"
|
61
|
+
end
|
62
|
+
|
63
|
+
def sheldon
|
64
|
+
@sheldon ||= ::Sheldon.new(sheldon_data_dir)
|
65
|
+
end
|
66
|
+
|
67
|
+
def sheldon_data_dir
|
68
|
+
path = ENV["SHELDON_DATA_DIR"] || "~/sheldon"
|
69
|
+
File.expand_path(path)
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
CLI::Sheldon.start(ARGV)
|
data/lib/sheldon.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
class Brain
|
2
|
+
|
3
|
+
attr_reader :memory
|
4
|
+
|
5
|
+
def initialize(sheldon_data_dir, opts = {})
|
6
|
+
@brain_location = sheldon_data_dir
|
7
|
+
@memory = opts[:memory] || Memory.new(@brain_location)
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
def learn(recall_cue, abs_learn_path)
|
12
|
+
cell = get_cell(recall_cue)
|
13
|
+
FileUtils.mkdir_p(cell)
|
14
|
+
FileUtils.mv(abs_learn_path, cell)
|
15
|
+
entry = { filepath: remove_home(abs_learn_path) }
|
16
|
+
memory.add(recall_cue, entry)
|
17
|
+
end
|
18
|
+
|
19
|
+
def recall(recall_cue)
|
20
|
+
entry = memory.recall(recall_cue)
|
21
|
+
destination_path = add_home(entry[:filepath])
|
22
|
+
destination_dir = File.dirname(destination_path)
|
23
|
+
FileUtils.mkdir_p(destination_dir) unless File.directory?(destination_dir)
|
24
|
+
source_cell = get_cell(recall_cue)
|
25
|
+
FileUtils.ln_s(read_cell(source_cell), destination_path, force: true)
|
26
|
+
end
|
27
|
+
|
28
|
+
def has_cue?(recall_cue)
|
29
|
+
memory.has_cue?(recall_cue)
|
30
|
+
end
|
31
|
+
|
32
|
+
def size
|
33
|
+
memory.size
|
34
|
+
end
|
35
|
+
|
36
|
+
def list_cues
|
37
|
+
memory.list_cues
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def get_cell(recall_cue)
|
43
|
+
File.join(@brain_location, recall_cue)
|
44
|
+
end
|
45
|
+
|
46
|
+
def read_cell(cell)
|
47
|
+
basename = (Dir.entries(cell) - [".", "..", ".DS_Store"]).first
|
48
|
+
File.join(cell, basename)
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class Builder
|
2
|
+
require "fileutils"
|
3
|
+
|
4
|
+
def build(abs_build_path)
|
5
|
+
entries = Dir.glob(abs_build_path + "/*")
|
6
|
+
master_content = entries.inject("") do |buffer, entry|
|
7
|
+
is_config?(entry) ? add_entry_to_buffer(entry, buffer) : buffer
|
8
|
+
end
|
9
|
+
|
10
|
+
unless master_content.empty?
|
11
|
+
master_path = File.join(abs_build_path, "config")
|
12
|
+
File.open(master_path, "w") { |f| f.write(master_content) }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def add_entry_to_buffer(abs_path, buffer)
|
19
|
+
content = File.read(abs_path)
|
20
|
+
buffer + content + "\n"
|
21
|
+
end
|
22
|
+
|
23
|
+
def is_config?(abs_path)
|
24
|
+
basename = File.basename(abs_path)
|
25
|
+
File.file?(abs_path) && basename.include?("config_") ? true : false
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Helpers
|
2
|
+
require "pathname"
|
3
|
+
|
4
|
+
def remove_home(path)
|
5
|
+
home_path = Pathname(File.expand_path("~"))
|
6
|
+
Pathname(path).relative_path_from(home_path).to_s
|
7
|
+
end
|
8
|
+
|
9
|
+
def add_home(path)
|
10
|
+
abs_home = File.expand_path("~")
|
11
|
+
File.join(abs_home, path).to_s
|
12
|
+
end
|
13
|
+
|
14
|
+
def abs(rel_path)
|
15
|
+
File.expand_path(rel_path).to_s
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require "yaml/store"
|
2
|
+
|
3
|
+
class Memory
|
4
|
+
|
5
|
+
def initialize(brain_location)
|
6
|
+
database_path = File.join(brain_location, "db.yml")
|
7
|
+
@database = YAML::Store.new(database_path)
|
8
|
+
end
|
9
|
+
|
10
|
+
def add(recall_cue, hash)
|
11
|
+
raise "cue already used" if has_cue?(recall_cue)
|
12
|
+
@database.transaction do
|
13
|
+
@database[recall_cue] = hash
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def recall(recall_cue)
|
18
|
+
raise "no entry for cue" unless has_cue?(recall_cue)
|
19
|
+
@database.transaction { @database[recall_cue] }
|
20
|
+
end
|
21
|
+
|
22
|
+
def size
|
23
|
+
list_cues.size
|
24
|
+
end
|
25
|
+
|
26
|
+
def list_cues
|
27
|
+
@database.transaction { @database.roots }
|
28
|
+
end
|
29
|
+
|
30
|
+
def has_cue?(recall_cue)
|
31
|
+
list_cues.any?{ |cue| cue == recall_cue }
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require "fileutils"
|
2
|
+
|
3
|
+
class Sheldon
|
4
|
+
VERSION = "0.2.6".freeze
|
5
|
+
attr_reader :brain, :builder
|
6
|
+
|
7
|
+
def initialize(sheldon_data_dir, opts = {})
|
8
|
+
raise "Directory #{sheldon_data_dir} does not exist" unless Dir.exists?(sheldon_data_dir)
|
9
|
+
@brain = opts[:brain] || Brain.new(sheldon_data_dir)
|
10
|
+
@builder = opts[:builder] || Builder.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def build(abs_learn_path)
|
14
|
+
builder.build(abs_learn_path)
|
15
|
+
end
|
16
|
+
|
17
|
+
def learn(recall_cue, abs_learn_path)
|
18
|
+
if brain.has_cue?(recall_cue)
|
19
|
+
raise "This cue has already been used."
|
20
|
+
else
|
21
|
+
brain.learn(recall_cue, abs_learn_path)
|
22
|
+
brain.recall(recall_cue)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def list_cues
|
27
|
+
brain.list_cues
|
28
|
+
end
|
29
|
+
|
30
|
+
def recall(recall_cue)
|
31
|
+
raise "Cue '#{recall_cue}' could not be found." unless brain.has_cue?(recall_cue)
|
32
|
+
brain.recall(recall_cue)
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
metadata
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sheldon
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.6
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- David Jones
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-03-31 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: thor
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.9'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.9'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '11.1'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '11.1'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.3'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.3'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: simplecov
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.10'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.10'
|
69
|
+
description: Another config and dotfile manager for unix environments
|
70
|
+
email: david@dvj.me.uk
|
71
|
+
executables:
|
72
|
+
- sheldon
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- LICENSE
|
77
|
+
- README.md
|
78
|
+
- bin/sheldon
|
79
|
+
- lib/sheldon.rb
|
80
|
+
- lib/sheldon/brain.rb
|
81
|
+
- lib/sheldon/builder.rb
|
82
|
+
- lib/sheldon/helpers.rb
|
83
|
+
- lib/sheldon/memory.rb
|
84
|
+
- lib/sheldon/sheldon.rb
|
85
|
+
homepage: https://github.com/dvjones89/sheldon
|
86
|
+
licenses:
|
87
|
+
- MIT
|
88
|
+
metadata: {}
|
89
|
+
post_install_message:
|
90
|
+
rdoc_options: []
|
91
|
+
require_paths:
|
92
|
+
- lib
|
93
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
requirements: []
|
104
|
+
rubyforge_project:
|
105
|
+
rubygems_version: 2.5.1
|
106
|
+
signing_key:
|
107
|
+
specification_version: 4
|
108
|
+
summary: Another config and dotfile manager for unix environments
|
109
|
+
test_files: []
|