caligari 0.1.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,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7d28cdbceef43dd381e3754c8edf16801550b4c8
4
+ data.tar.gz: 1345087a5222d642cdade41b78c21be222891030
5
+ SHA512:
6
+ metadata.gz: d3f798fd7ead95117d0f6f1dfd5cbf9aec789bfa6c7ba83aaefffd912884f8550902dba6371815bfc0fa5f299ca1c584ce948ed3417f92cbfacdfba5fe0f17e2
7
+ data.tar.gz: 8afe108d18661153e28598f96edd97dcc478b6c5fceff2eacf4a28ccc9541a3cac92a851b7557759e291b3cb3c751d3c9d586fbcdde86c76aeddcaff8a6537c9
@@ -0,0 +1,8 @@
1
+ .yardoc/
2
+ doc/
3
+ Gemfile.lock
4
+ pkg/
5
+
6
+ man/**/*.html
7
+ man/**/*.css
8
+ man/**/*.?
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,17 @@
1
+ Copyright (c) 2016 Robin Owen
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this
4
+ software and associated documentation files (the "Software"), to deal in the Software
5
+ without restriction, including without limitation the rights to use, copy, modify, merge,
6
+ publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
7
+ to whom the Software is furnished to do so, subject to the following conditions:
8
+
9
+ The above copyright notice and this permission notice shall be included in all copies or
10
+ substantial portions of the Software.
11
+
12
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13
+ INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14
+ PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
15
+ FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
+ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17
+ DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,99 @@
1
+ # Caligari
2
+ _"...I must become Caligari!"_
3
+
4
+ ## Description
5
+ `caligari` installs configuration files by symbolically linking all of the
6
+ files from the given paths directly to the current user's home directory with
7
+ the same relative file structure, creating any requisite directories as-needed.
8
+
9
+ ## Usage
10
+ `caligari` allows you to exclude files matching a given `fnmatch` pattern with
11
+ the **--exclude/-x** flag. For example, the following may be used to exclude
12
+ all backup files and `vim` swap files:
13
+
14
+ ```sh
15
+ caligari --exclude '**/*~' '**/*.swp'
16
+ ```
17
+
18
+ By default, `caligari` will simply skip over any files which already exist in
19
+ the current user's home directory; however, you can force `caligari` to
20
+ overwrite existing files with the **--force/-f** flag:
21
+
22
+ ```sh
23
+ caligari --force
24
+ ```
25
+
26
+ `caligari` is normally silent except for warnings and errors; if you want more
27
+ explicit output about the operations `caligari` performs, simply use the
28
+ **--verbose/-V** flag. This flag will report all of the file system operations
29
+ `caligari` performs, each with an appropriate label:
30
+
31
+ * **ln** for created symbolic links
32
+ * **path** for created directory paths
33
+ * **rm** for unlinked files
34
+ * **err** for any errors encountered
35
+
36
+ `caligari` reports operations in this way so that they may be filtered in
37
+ whichever way the user desires. For example, you could print a list of the
38
+ files removed by a forceful `caligari` run like so:
39
+
40
+ ```sh
41
+ caligari --force --verbose | awk '/^rm:/ { print $2 }'
42
+ ```
43
+
44
+ You may also simulate the actions `caligari` would normally take upon the file
45
+ system by passing the **--simulate/-s** flag. This implies the **--verbose**
46
+ flag, allowing you to inspect which actions `caligari` would take if run:
47
+
48
+ ```
49
+ $ caligari --simulate --force
50
+ rm: /home/user/do-not-remove
51
+ ln: /home/user/do-not-remove
52
+ ```
53
+
54
+ ## Configuration
55
+ `caligari` may be configured by editing the system-wide configuration file
56
+ (defined by default as */etc/xdg/caligari.yml*) or the per-user configuration
57
+ file (defined by default as *~/.config/caligari.yml*). These configuration
58
+ files are simple YAML files which define the default exclusion patterns used
59
+ by `caligari`.
60
+
61
+ Example *~/.config/caligari.yml* to automatically exclude the *.git* directory
62
+ and all *README.md* files:
63
+
64
+ ```yaml
65
+ ---
66
+ :exclude:
67
+ - "**/.git"
68
+ - "**/README.md"
69
+ ```
70
+
71
+ ## Installation
72
+ ```sh
73
+ gem install caligari
74
+ ```
75
+
76
+ ## Development
77
+ Just clone the [git repository][repo] and run `bundle install` to install the
78
+ development and runtime dependencies:
79
+
80
+ ```sh
81
+ git clone https://github.com/vthrenody/caligari.git
82
+ cd caligari
83
+ bundle install
84
+ ```
85
+
86
+ You can run Caligari locally for development purposes by running it directly
87
+ from the repository like so:
88
+
89
+ ```sh
90
+ bin/caligari
91
+ ```
92
+
93
+ To install a local copy of Caligari, simply run `rake install`.
94
+
95
+ ## License
96
+ Caligari is made available under the terms of the MIT Expat license. See the
97
+ included LICENSE file for more information.
98
+
99
+ [repo]: https://www.github.com/vthrenody/caligari
@@ -0,0 +1,13 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'md2man/rakefile'
3
+ require 'yard'
4
+
5
+ YARD::Rake::YardocTask.new do |yard|
6
+ yard.options = [
7
+ '--title', 'Caligari Documentation',
8
+ '--readme', 'README.md',
9
+ '--files', 'LICENSE',
10
+ '--markup', 'markdown',
11
+ '--private',
12
+ ]
13
+ end
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'trollop'
4
+
5
+ if $0.start_with?('/')
6
+ require 'caligari'
7
+ else
8
+ warn 'warn: running local caligari'
9
+ require_relative '../lib/caligari'
10
+ end
11
+
12
+ def die(message)
13
+ $stderr.puts "err: #{message}"
14
+ exit 1
15
+ end
16
+
17
+ options = Trollop.options do
18
+ version Caligari::COPYRIGHT
19
+ banner <<-EOS
20
+ #{Caligari::COPYRIGHT}
21
+
22
+ caligari is a simple configuration file installer. By default, this utility
23
+ will generate symbolic links in the current user's home directory for all of
24
+ the files present in the target path(s).
25
+
26
+ Usage:
27
+ caligari [OPTION]... [PATH]...
28
+
29
+ Options:
30
+ EOS
31
+
32
+ opt :exclude, 'Exclude the given files or directories', short: 'x',
33
+ type: :strings
34
+ opt :force, 'Force installation over existing files'
35
+ opt :simulate, 'Simulate installation (implies --verbose)'
36
+ opt :traverse, 'Traverse into the given paths while processing'
37
+ opt :verbose, 'Print verbose installation information', short: 'V'
38
+ end
39
+
40
+ # Make sure we have at least an empty array for exclusions.
41
+ options[:exclude] ||= []
42
+
43
+ # Make sure `ARGV` is populated with the current working directory if not
44
+ # otherwise specified. Note that we use "." here instead of, for example,
45
+ # `Dir.pwd` -- Caligari does not like absolute paths.
46
+ ARGV.push('.') if ARGV.empty?
47
+
48
+ begin
49
+ Caligari::Application.new(*ARGV, options).run
50
+ rescue Psych::SyntaxError => ex
51
+ die("configuration is malformed:\n\t#{ex.message}")
52
+ rescue Exception => ex
53
+ die(ex.message)
54
+ end
@@ -0,0 +1,31 @@
1
+ lib = File.expand_path('lib', __dir__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+
4
+ require 'caligari/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = 'caligari'
8
+ gem.version = Caligari::VERSION
9
+ gem.authors = ['Robin Owen']
10
+ gem.email = ['vthrenody@gmail.com']
11
+ gem.homepage = 'https://github.com/vthrenody/caligari'
12
+ gem.platform = Gem::Platform::RUBY
13
+ gem.license = 'MIT'
14
+
15
+ gem.summary = 'Caligari symbolically links configuration files.'
16
+ gem.description = %{
17
+ Caligari is designed to allow the quick and easy installation of
18
+ configuration files by symbolically linking files from external sources
19
+ directly to the user's home directory.
20
+ }.gsub!(/\s+/, " ").strip
21
+
22
+ %w(bundler md2man rake yard).each do |dep|
23
+ gem.add_development_dependency(dep)
24
+ end
25
+ gem.add_dependency('trollop')
26
+
27
+ gem.files = `git ls-files -z`.split("\x0")
28
+ gem.files += Dir['man/man?/*.?'] # Explicitly add generated man page.
29
+ gem.executables = 'caligari'
30
+ gem.require_path = 'lib'
31
+ end
@@ -0,0 +1,9 @@
1
+ require_relative 'caligari/application'
2
+ require_relative 'caligari/xdg'
3
+ require_relative 'caligari/version'
4
+
5
+ # Caligari is designed to allow the quick and easy installation of
6
+ # configuration files by symbolically linking files from external sources
7
+ # directly to the user's home directory.
8
+ module Caligari
9
+ end
@@ -0,0 +1,127 @@
1
+ require 'pathname'
2
+ require 'yaml/store'
3
+
4
+ require_relative 'xdg'
5
+
6
+ module Caligari
7
+ # This class is instantiated and used to run a single invocation of the
8
+ # `caligari` application.
9
+ class Application
10
+ # The flags to be passed to `Pathname#fnmatch?` to filter exclusions.
11
+ FLAGS = File::FNM_DOTMATCH | File::FNM_PATHNAME
12
+
13
+ # The `Pathname` representation of the current user's home directory.
14
+ HOME = Pathname.new(Dir.home)
15
+
16
+ # Instantiates a new {Application} instance.
17
+ #
18
+ # @param paths [Array<String>]
19
+ # the paths for this {Application} to {#run} on
20
+ # @param options [Hash]
21
+ # the hash of options to apply to this {Application}
22
+ # @return [self]
23
+ # the initialized {Application} instance
24
+ def initialize(*paths, **options)
25
+ @paths = paths.map { |path| Pathname.new(path) }
26
+ options.each do |key, value|
27
+ instance_variable_set(:"@#{key}", value)
28
+ end
29
+ collect_exclusions
30
+ end
31
+
32
+ # Runs Caligari.
33
+ #
34
+ # @return [self]
35
+ def run
36
+ @paths.each do |path|
37
+ fail "#{path} is not a valid path" unless path.directory?
38
+ if @traverse
39
+ Dir.chdir(path) do
40
+ each_file(Pathname.new('.')) { |file| link(file) }
41
+ end
42
+ else
43
+ each_file(path) { |file| link(file) }
44
+ end
45
+ end
46
+ self
47
+ end
48
+
49
+ # Collects the list of exclusion patterns for Caligari from a combination
50
+ # of XDG configuration directories and the given CLI exclusions.
51
+ #
52
+ # @note Exclusion patterns are used to filter the files to act upon via the
53
+ # `Pathname#fnmatch?` instance method. The actual filtering, however,
54
+ # takes place within {#each_file}.
55
+ #
56
+ # @return [Array<String>]
57
+ # the array of patterns to exclude
58
+ #
59
+ # @see #each_file
60
+ private def collect_exclusions
61
+ XDG::CONFIG_FILES.each do |file|
62
+ config = YAML::Store.new(file)
63
+ @exclude |= config.transaction { config.fetch(:exclude, []) }
64
+ end
65
+ @exclude
66
+ end
67
+
68
+ # Recursively iterates over each file in the given `path`, excluding those
69
+ # which match any of the exclusion patterns collected via the
70
+ # {#collect_exclusions} private instance method. The given `block` is
71
+ # executed for each file.
72
+ #
73
+ # @param path [Pathname]
74
+ # the base directory to iterate over
75
+ # @yieldparam entry [Pathname]
76
+ # the representation of a file
77
+ # @return [Array<Pathname>]
78
+ #
79
+ # @see #collect_exclusions
80
+ private def each_file(path, &block)
81
+ path.each_child do |entry|
82
+ next if @exclude.any? { |pattern| entry.fnmatch?(pattern, FLAGS) }
83
+ entry.directory? ? each_file(entry, &block) : yield(entry)
84
+ end
85
+ end
86
+
87
+ # Symbolically links the given `file` to the current user's home directory.
88
+ #
89
+ # @param file [Pathname]
90
+ # the `Pathname` representation of a file to link
91
+ # @return [Boolean]
92
+ # `true` if the given `file` was symbolically linked, `false` otherwise
93
+ private def link(file)
94
+ return false unless file.exist?
95
+ dest = HOME + file.dirname
96
+ unless dest.exist?
97
+ report "path: #{dest}"
98
+ dest.mkpath unless @simulate
99
+ end
100
+ dest += file.basename
101
+ if @force && dest.file?
102
+ report "rm: #{dest}"
103
+ dest.delete unless @simulate
104
+ end
105
+ report "ln: #{dest}" if @simulate || !dest.file?
106
+ if @simulate || dest.file?
107
+ false
108
+ else
109
+ dest.make_symlink(file.expand_path)
110
+ true
111
+ end
112
+ end
113
+
114
+ # Reports the given `message` on the given `stream` if Caligari has been
115
+ # configured to run in verbose or simulation mode.
116
+ #
117
+ # @param message [#to_s]
118
+ # the message to report
119
+ # @param stream [#puts]
120
+ # the stream to write a message to
121
+ # @return [nil]
122
+ private def report(message, stream = $stdout)
123
+ return unless @verbose || @simulate
124
+ stream.puts message.to_s
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,7 @@
1
+ module Caligari
2
+ # Semantic version of Caligari.
3
+ VERSION = '0.1.0'.freeze
4
+
5
+ # Copyright notice for Caligari.
6
+ COPYRIGHT = "caligari #{VERSION} (c) 2016 Robin Owen".freeze
7
+ end
@@ -0,0 +1,41 @@
1
+ require 'pathname'
2
+
3
+ module Caligari
4
+ # This module contains constants representing XDG configuration directories
5
+ # and files for Caligari as specified by the XDG Base Directory
6
+ # Specification.
7
+ #
8
+ # @see http://polr.me/zjp XDG Base Directory Specification
9
+ module XDG
10
+ # Collects configuration directories as defined by the XDG Base Directory
11
+ # Specification as `Pathname` instances.
12
+ #
13
+ # @api private
14
+ # @return [Array<Pathname>] the collected XDG configuration directories
15
+ def self.collect_xdg_config_dirs
16
+ dirs = ENV['XDG_CONFIG_DIRS']
17
+ if dirs
18
+ dirs.split(':').map! do |dir|
19
+ Pathname.new(dir).expand_path.freeze
20
+ end.freeze
21
+ else
22
+ [Pathname.new('/etc/xdg').freeze].freeze
23
+ end
24
+ end
25
+ private_class_method :collect_xdg_config_dirs
26
+
27
+ # The global XDG configuration directories as an array of `Pathname`
28
+ # instances.
29
+ CONFIG_DIRS = collect_xdg_config_dirs
30
+
31
+ # The user XDG configuration directory as a `Pathname` instance.
32
+ CONFIG_HOME =
33
+ Pathname.new(ENV['XDG_CONFIG_HOME'] || '~/.config').expand_path.freeze
34
+
35
+ # The existent XDG configuration files for Caligari as a `Pathname`
36
+ # instance.
37
+ CONFIG_FILES = (CONFIG_DIRS + [CONFIG_HOME]).map! do |dir|
38
+ (dir + 'caligari.yml').freeze
39
+ end.select! { |file| file.exist? }.freeze
40
+ end
41
+ end
@@ -0,0 +1,105 @@
1
+ CALIGARI 1
2
+ ===============================================================================
3
+
4
+ NAME
5
+ -------------------------------------------------------------------------------
6
+
7
+ caligari - symbolically link external configuration files
8
+
9
+ SYNOPSIS
10
+ -------------------------------------------------------------------------------
11
+
12
+ `caligari` [*OPTION*]... [*PATH*]...
13
+
14
+ DESCRIPTION
15
+ -------------------------------------------------------------------------------
16
+
17
+ `caligari` installs configuration files by symbolically linking all of the
18
+ files from the given paths directly to the current user's home directory with
19
+ the same relative file structure, creating any requisite directories as-needed.
20
+
21
+
22
+ OPTIONS
23
+ -------------------------------------------------------------------------------
24
+
25
+ `-x`, `--exclude` *pattern* ...
26
+ Exclude the files and directories matching the given patterns. Patterns may
27
+ be supplied as *fnmatch* patterns. Note that exclusions are automatically
28
+ given the **FNM_DOTMATCH** and **FNM_PATHNAME** flags.
29
+
30
+ `-f`, `--force`
31
+ Force installation over existing files.
32
+
33
+ `-s`, `--simulate`
34
+ Simulate installation (implies `--verbose`). Any action which would normally
35
+ affect the file system is simply reported rather than acted upon.
36
+
37
+ `-t`, `--traverse`
38
+ Traverse into the given directories while processing. This ensures that each
39
+ path given acts as its own relative "root" path during processing -- the
40
+ files in each path will be linked directly to the user's home directory
41
+ rather than being treated as children of the current working directory.
42
+
43
+ `-V`, `--verbose`
44
+ Print verbose installation information while processing. Each item printed
45
+ by this flag is announced with an appropriate label for the action being
46
+ taken (or simulated): `ln:` for created symbolic links, `path:` for created
47
+ directory paths, `rm:` for unlinked files, and `err:` for any errors
48
+ encountered.
49
+
50
+ CONFIGURATION
51
+ -------------------------------------------------------------------------------
52
+
53
+ `caligari` may be configured by editing the system-wide configuration file
54
+ (defined by default as */etc/xdg/caligari.yml*) or the per-user configuration
55
+ file (defined by default as *~/.config/caligari.yml*). These configuration
56
+ files are simple YAML files which define the default exclusion patterns used
57
+ by `caligari`.
58
+
59
+ EXAMPLES
60
+ -------------------------------------------------------------------------------
61
+
62
+ Create symbolic links for all of the files in the current directory excluding
63
+ the *.git* directory and all *README.md* files:
64
+
65
+ ```sh
66
+ caligari -x '**/.git' '**/README.md'
67
+ ```
68
+
69
+ Forcefully create symbolic links for all of the files in the directories
70
+ *dotfiles* and *more-dotfiles*, traversing to each so the files are linked
71
+ directly to the home directory:
72
+
73
+ ```sh
74
+ caligari -tf dotfiles more-dotfiles
75
+ ```
76
+
77
+ Print each file which was forcefully removed:
78
+
79
+ ```sh
80
+ caligari -Vf | awk '/^rm:/ { print $2 }'
81
+ ```
82
+
83
+ Example *~/.config/caligari.yml* to automatically exclude the *.git* directory
84
+ and all *README.md* files:
85
+
86
+ ```yaml
87
+ ---
88
+ :exclude:
89
+ - "**/.git"
90
+ - "**/README.md"
91
+ ```
92
+
93
+ FILES
94
+ -------------------------------------------------------------------------------
95
+
96
+ */etc/xdg/caligari.yml*
97
+ The system-wide configuration file.
98
+
99
+ *~/.config/caligari.yml*
100
+ Per-user configuration file.
101
+
102
+ AUTHOR
103
+ -------------------------------------------------------------------------------
104
+
105
+ Robin Owen <vthrenody@gmail.com>
metadata ADDED
@@ -0,0 +1,130 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: caligari
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Robin Owen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-08-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: md2man
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: yard
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: trollop
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Caligari is designed to allow the quick and easy installation of configuration
84
+ files by symbolically linking files from external sources directly to the user's
85
+ home directory.
86
+ email:
87
+ - vthrenody@gmail.com
88
+ executables:
89
+ - caligari
90
+ extensions: []
91
+ extra_rdoc_files: []
92
+ files:
93
+ - ".gitignore"
94
+ - Gemfile
95
+ - LICENSE
96
+ - README.md
97
+ - Rakefile
98
+ - bin/caligari
99
+ - caligari.gemspec
100
+ - lib/caligari.rb
101
+ - lib/caligari/application.rb
102
+ - lib/caligari/version.rb
103
+ - lib/caligari/xdg.rb
104
+ - man/man1/caligari.1
105
+ - man/man1/caligari.1.md
106
+ homepage: https://github.com/vthrenody/caligari
107
+ licenses:
108
+ - MIT
109
+ metadata: {}
110
+ post_install_message:
111
+ rdoc_options: []
112
+ require_paths:
113
+ - lib
114
+ required_ruby_version: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ required_rubygems_version: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ requirements: []
125
+ rubyforge_project:
126
+ rubygems_version: 2.6.6
127
+ signing_key:
128
+ specification_version: 4
129
+ summary: Caligari symbolically links configuration files.
130
+ test_files: []