flexdot 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 1cce20c75873ecb10cd057fa7e02177580915e399768e6e2b24a908924717d99
4
+ data.tar.gz: 89328d00bc1991493907c2ec558662d4ada76110e6d33052eeaa521ecac64e22
5
+ SHA512:
6
+ metadata.gz: 8ba2f0a613eff80271375c8a1eaee73af9e3f573c2ae08ca86b61eff337a4363d55b5d9b45a8212d3b75ad5536215105541f9430910eed87708ec8ca3f583838
7
+ data.tar.gz: 3a06a1a126bf0beec0a9b9c7d72f5d96c8778a926d242dc0ed74db0ea198b0a8e6d30c0b64c8a4f40be7525ce731eefec6fe7251a8ac3ad0ad5ab4fef0789013
@@ -0,0 +1,3 @@
1
+ # These are supported funding model platforms
2
+
3
+ github: [hidakatsuya]
@@ -0,0 +1,26 @@
1
+
2
+ name: Test
3
+
4
+ on: [push, pull_request]
5
+
6
+ jobs:
7
+ test:
8
+ name: Test on ruby ${{ matrix.ruby_version }}
9
+ runs-on: ubuntu-latest
10
+ strategy:
11
+ matrix:
12
+ ruby_version:
13
+ - 2.5.x
14
+ - 2.6.x
15
+ - 2.7.x
16
+ steps:
17
+ - uses: actions/checkout@v1
18
+ - name: Set up Ruby ${{ matrix.ruby_version }}
19
+ uses: actions/setup-ruby@v1
20
+ with:
21
+ ruby-version: ${{ matrix.ruby_version }}
22
+ - name: Build and test with Rake
23
+ run: |
24
+ gem install bundler
25
+ bundle install --jobs 4 --retry 3
26
+ bundle exec rake test
@@ -0,0 +1,12 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ /Gemfile.lock
10
+
11
+ /test/home/*
12
+ !/test/home/dotfiles/*
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at hidakatsuya@gmail.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [https://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: https://contributor-covenant.org
74
+ [version]: https://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'rake', '>= 12.0'
6
+ gem 'minitest', '~> 5.0'
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2020 Katsuya Hidaka
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
13
+ all 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
21
+ THE SOFTWARE.
@@ -0,0 +1,213 @@
1
+ # Flexdot
2
+
3
+ [![Test](https://github.com/hidakatsuya/flexdot/workflows/Test/badge.svg?branch=master)](https://github.com/hidakatsuya/flexdot/actions?query=workflow%3ATest)
4
+
5
+ A Flexible and Rake based dotfile manager.
6
+
7
+ ## Getting Started
8
+
9
+ ### Prerequisite
10
+
11
+ Ruby 2.5+
12
+
13
+ ### Installing
14
+
15
+ Install it as:
16
+
17
+ $ gem install flexdot
18
+
19
+ Then, create the following directory structure:
20
+
21
+ ```
22
+ $HOME/
23
+ dotfiles/
24
+ ```
25
+
26
+ Create a `$HOME/dotfiles/Rakefile` with the following codes:
27
+
28
+ ```ruby
29
+ require 'flexdot'
30
+
31
+ Flexdot.install_tasks(
32
+ base_dir: '.', # $HOME/dotfiles/
33
+ target_dir: '/home/username' # $HOME/
34
+ )
35
+ ```
36
+
37
+ Finally, run `rake -T` in the `$HOME/dotfiles` and make sure that the output is as follows:
38
+
39
+ $ rake -T
40
+ rake clear_backups
41
+
42
+ ## Example
43
+
44
+ This example is my actual dotfile environment.
45
+
46
+ I have two working environments, macOS and ubuntu. The dotfiles in these environments are slightly different, so each dotfile is separated.
47
+
48
+ ### Directory Structure
49
+
50
+ ```
51
+ $HOME/dotfiles
52
+ ├── common
53
+ │   ├── bin
54
+ │   │   ├── git-delete-other-branches
55
+ │   │   └── git-reset-and-clean
56
+ │   ├── git
57
+ │   │   └── ignore
58
+ │   ├── rubygems
59
+ │   │   └── .gemrc
60
+ │   └── vim
61
+ │   └── .vimrc
62
+ ├── macOS
63
+ │   ├── bash
64
+ │   │   ├── .bash_profile
65
+ │   │   └── .bashrc
66
+ │   ├── git
67
+ │   │   └── .gitconfig
68
+ │   ├── karabiner
69
+ │   │   └── tab-emulation.json
70
+ │   └── vscode
71
+ │   ├── keybindings.json
72
+ │   └── settings.json
73
+ ├── ubuntu
74
+ │   ├── bash
75
+ │   │   └── .bashrc
76
+ │   ├── bin
77
+ │   │   ├── upgrade-ghcli
78
+ │   │   ├── utils
79
+ │   │   ├── x-copy
80
+ │   │   └── x-open
81
+ │   ├── git
82
+ │   │   └── .gitconfig
83
+ │   ├── vscode
84
+ │   │   ├── keybindings.json
85
+ │   │   └── settings.json
86
+ │   └── xkeysnail
87
+ │   ├── config.py
88
+ │   ├── debug.sh
89
+ │   ├── restart.sh
90
+ │   ├── start.sh
91
+ │   └── stop.sh
92
+ ├── macOS.yml
93
+ ├── ubuntu.yml
94
+ └── Rakefile
95
+ ```
96
+
97
+ ### Available Commands
98
+
99
+ When you run the `rake -T` command in that directory structure, you should have two installation commands available:
100
+
101
+ $ rake -T
102
+ rake clear_backups # Clear all backups
103
+ rake install:macOS # Install dotfiles for macOS
104
+ rake install:ubuntu # Install dotfiles for ubuntu
105
+
106
+ ### Dotfile Index File
107
+
108
+ `macOS.yml` and `ubuntu.yml` are for setting the link destination of dotfile. dotfile will be installed according to its setting.
109
+
110
+ #### macOS.yml
111
+
112
+ For example, `common -> bin -> git-delete-other-branchs` is `$HOME/dotfiles/common/bin/git-delete-other-branches`.
113
+ And the value `bin` means `$HOME/bin` directory.
114
+
115
+ So this defines linking `$HOME/dotfiles/common/bin/git-delete-other-branches` to `$HOME/bin/git-delete-other-branches`.
116
+
117
+
118
+ ```yml
119
+ common:
120
+ bin:
121
+ git-delete-other-branches: bin
122
+ git-reset-and-clean: bin
123
+ git:
124
+ ignore: .config/git
125
+ rubygems:
126
+ .gemrc: .
127
+ vim:
128
+ .vimrc: .
129
+
130
+ macOS:
131
+ bash:
132
+ .bash_profile: .
133
+ .bashrc: .
134
+ git:
135
+ .gitconfig: .
136
+ karabiner:
137
+ tab-emulation.json: .config/karabiner/assets/complex_modifications
138
+ vscode:
139
+ keybindings.json: Library/Application Support/Code/User
140
+ settings.json: Library/Application Support/Code/User
141
+ ```
142
+
143
+ #### ubuntu.yml
144
+
145
+ ```yml
146
+ common:
147
+ bin:
148
+ git-delete-other-branchs: bin
149
+ git-reset-and-clean: bin
150
+ git:
151
+ ignore: .config/git
152
+ rubygems:
153
+ .gemrc: .
154
+ vim:
155
+ .vimrc: .
156
+
157
+ ubuntu:
158
+ bash:
159
+ .bashrc: .
160
+ bin:
161
+ upgrade-ghcli: bin
162
+ utils: bin
163
+ x-copy: bin
164
+ x-open: bin
165
+ git:
166
+ .gitconfig: .
167
+ vscode:
168
+ keybindings.json: .config/Code/User
169
+ settings.json: .config/Code/User
170
+ xkeysnail:
171
+ config.py: .xkeysnail
172
+ debug.sh: .xkeysnail
173
+ restart.sh: .xkeysnail
174
+ start.sh: .xkeysnail
175
+ stop.sh: .xkeysnail
176
+ ```
177
+
178
+ ### Installing dotfiles
179
+
180
+ $ rake install:macOS
181
+
182
+ The following is the output result:
183
+
184
+ ```
185
+ [already_linked] bin/git-delete-other-branches
186
+ [already_linked] bin/git-reset-and-clean
187
+ [already_linked] .config/git/ignore
188
+ [already_linked] .gemrc
189
+ [already_linked] .vimrc
190
+ [link_created] .bash_profile (backup)
191
+ [link_created] .bashrc (backup)
192
+ [link_created] .gitconfig (backup)
193
+ [link_created] .config/karabiner/assets/complex_modifications/tab-emulation.json (backup)
194
+ [link_created] Library/Application Support/Code/User/keybindings.json (backup)
195
+ [link_created] Library/Application Support/Code/User/settings.json (backup)
196
+ ```
197
+
198
+ `already_linked` means skipped because `bin/git-delete-other-branches` is already linked. `link_created` means the link was created.
199
+ Also, `(backup)` means that a file exists in the link path and that file was backed up to `$HOME/dotfiles/backup/YYYYMMDDHHIISS/filename`.
200
+
201
+ ### Misc
202
+
203
+ You can clear all backups in `$HOME/dotfiles/backup/YYYYMMDDHHIISS` to run `rake clear_backups`.
204
+
205
+ $ rake clear_backups
206
+
207
+ ## License
208
+
209
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
210
+
211
+ ## Code of Conduct
212
+
213
+ Everyone interacting in the Flexdot project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/hidakatsuya/flexdot/blob/master/CODE_OF_CONDUCT.md).
@@ -0,0 +1,10 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << 'test'
6
+ t.libs << 'lib'
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ end
9
+
10
+ task :default => :test
@@ -0,0 +1,19 @@
1
+ require_relative 'lib/flexdot/version'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = 'flexdot'
5
+ spec.version = Flexdot::VERSION
6
+ spec.authors = ['Katsuya Hidaka']
7
+ spec.email = ['hidakatsuya@gmail.com']
8
+
9
+ spec.summary = 'A Flexible and Rake based dotfile manager'
10
+ spec.description = 'Flexdot is a Flexible and Rake based dotfile manager'
11
+ spec.homepage = 'https://github.com/hidakatsuya/flexdot'
12
+ spec.license = 'MIT'
13
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.5.0')
14
+
15
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
16
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test)/}) }
17
+ end
18
+ spec.require_paths = ['lib']
19
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'flexdot/version'
4
+ require_relative 'flexdot/tasks'
5
+
6
+ module Flexdot
7
+ def self.install_tasks(base_dir:, target_dir:)
8
+ Tasks.new(base_dir, target_dir).install
9
+ end
10
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pathname'
4
+ require 'fileutils'
5
+
6
+ module Flexdot
7
+ class Backup
8
+ BASE_DIR = 'backup'
9
+
10
+ class << self
11
+ def clear_all
12
+ base_dir.glob('*').each(&:rmtree)
13
+ end
14
+
15
+ def base_dir
16
+ Pathname.pwd.join(BASE_DIR)
17
+ end
18
+ end
19
+
20
+ def initialize
21
+ backup_dir.mkpath unless backup_dir.exist?
22
+ end
23
+
24
+ def call(file)
25
+ FileUtils.mv(file, backup_dir)
26
+ end
27
+
28
+ private
29
+
30
+ def backup_dir
31
+ @backup_dir ||= self.class.base_dir.join(Time.now.strftime('%Y%m%d%H%M%S'))
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Flexdot
4
+ class Index
5
+ def initialize(index)
6
+ @index = index
7
+ end
8
+
9
+ def each(&block)
10
+ index.each do |root, descendants|
11
+ fetch_descendants(descendants, paths: [root], &block)
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ attr_reader :index
18
+
19
+ def fetch_descendants(descendants, paths:, &block)
20
+ descendants.each do |k, v|
21
+ dotfile_path = paths + [k]
22
+ case v
23
+ when String
24
+ block.call(dotfile_path: File.join(*dotfile_path), target_path: v)
25
+ when Hash
26
+ fetch_descendants(v, paths: dotfile_path, &block)
27
+ else
28
+ raise ArgumentError, v
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yaml'
4
+
5
+ require_relative 'logger'
6
+ require_relative 'backup'
7
+ require_relative 'index'
8
+
9
+ module Flexdot
10
+ class Installer
11
+ def initialize(name, base_dir:, target_dir:)
12
+ @name = name
13
+ @base_dir = base_dir
14
+ @target_dir = target_dir
15
+ @backup = Backup.new
16
+ @logger = Logger.new(@target_dir)
17
+ end
18
+
19
+ def install(index_file)
20
+ index = Index.new(YAML.load_file(index_file.to_path))
21
+ index.each do |dotfile_path:, target_path:|
22
+ install_link(dotfile_path, target_path)
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ attr_reader :name, :base_dir, :target_dir, :backup, :logger
29
+
30
+ def install_link(dotfile_path, target_path)
31
+ dotfile = @base_dir.join(dotfile_path).expand_path
32
+ target_file = @target_dir.join(target_path, dotfile.basename).expand_path
33
+
34
+ logger.log(target_file) do |status|
35
+ if target_file.symlink?
36
+ if target_file.readlink == dotfile
37
+ status.result = :already_linked
38
+ else
39
+ target_file.unlink
40
+ target_file.make_symlink(dotfile.to_path)
41
+ status.result = :link_updated
42
+ end
43
+ else
44
+ if target_file.exist?
45
+ backup.call(target_file)
46
+ status.backuped = true
47
+ elsif !target_file.dirname.exist?
48
+ target_file.dirname.mkpath
49
+ end
50
+
51
+ target_file.make_symlink(dotfile.to_path)
52
+ status.result = :link_created
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Flexdot
4
+ class Logger
5
+ Status = Struct.new(:target_file, :result, :backuped)
6
+
7
+ def initialize(target_dir)
8
+ @target_dir = target_dir
9
+ end
10
+
11
+ def log(target_file)
12
+ status = Status.new(target_file)
13
+ yield(status)
14
+ puts message_for(status)
15
+ end
16
+
17
+ private
18
+
19
+ attr_reader :target_dir
20
+
21
+ def message_for(status)
22
+ [].tap { |msg|
23
+ msg << "[#{status.result}]"
24
+ msg << status.target_file.relative_path_from(target_dir)
25
+ msg << '(backup)' if status.backuped
26
+ }.join(' ')
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pathname'
4
+ require_relative 'installer'
5
+ require_relative 'backup'
6
+
7
+ module Flexdot
8
+ class Tasks
9
+ include Rake::DSL
10
+
11
+ def initialize(base_dir, target_dir)
12
+ @base_dir = Pathname.new(base_dir)
13
+ @target_dir = Pathname.new(target_dir)
14
+ end
15
+
16
+ def install
17
+ desc 'Clear backups'
18
+ task :clear_backups do
19
+ Backup.clear_all
20
+ end
21
+
22
+ namespace :install do
23
+ Pathname.new(base_dir).glob('*.yml') do |index_file|
24
+ name = index_file.basename('.*')
25
+
26
+ desc "Install dotfiles for #{name}"
27
+ task name do
28
+ installer = Installer.new(
29
+ name,
30
+ base_dir: base_dir,
31
+ target_dir: target_dir
32
+ )
33
+ installer.install(index_file)
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ attr_reader :base_dir, :target_dir
42
+ end
43
+ end
44
+
45
+
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Flexdot
4
+ VERSION = '1.0.2'
5
+ end
metadata ADDED
@@ -0,0 +1,59 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: flexdot
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Katsuya Hidaka
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-07-21 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Flexdot is a Flexible and Rake based dotfile manager
14
+ email:
15
+ - hidakatsuya@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".github/FUNDING.yml"
21
+ - ".github/workflows/test.yml"
22
+ - ".gitignore"
23
+ - CODE_OF_CONDUCT.md
24
+ - Gemfile
25
+ - LICENSE.txt
26
+ - README.md
27
+ - Rakefile
28
+ - flexdot.gemspec
29
+ - lib/flexdot.rb
30
+ - lib/flexdot/backup.rb
31
+ - lib/flexdot/index.rb
32
+ - lib/flexdot/installer.rb
33
+ - lib/flexdot/logger.rb
34
+ - lib/flexdot/tasks.rb
35
+ - lib/flexdot/version.rb
36
+ homepage: https://github.com/hidakatsuya/flexdot
37
+ licenses:
38
+ - MIT
39
+ metadata: {}
40
+ post_install_message:
41
+ rdoc_options: []
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: 2.5.0
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ requirements: []
55
+ rubygems_version: 3.1.2
56
+ signing_key:
57
+ specification_version: 4
58
+ summary: A Flexible and Rake based dotfile manager
59
+ test_files: []