freshen 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.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +7 -0
- data/bin/freshen +9 -0
- data/freshen.gemspec +22 -0
- data/lib/freshen/cli.rb +75 -0
- data/lib/freshen/errors.rb +73 -0
- data/lib/freshen/executable.rb +122 -0
- data/lib/freshen/helpers/module.rb +32 -0
- data/lib/freshen/helpers/string.rb +99 -0
- data/lib/freshen/helpers/time.rb +19 -0
- data/lib/freshen/helpers.rb +3 -0
- data/lib/freshen/system.rb +85 -0
- data/lib/freshen/variables.rb +17 -0
- data/lib/freshen.rb +46 -0
- data/lib/freshenary.rb +98 -0
- data/lib/freshener.rb +152 -0
- metadata +81 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d3e573f6d6b66152c1bf8aedd14b40d68ddd70e8
|
4
|
+
data.tar.gz: 946f32367ea70dc4ef246b2b43c0bb82b1611e74
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ab6cd331f1173b12fc12892b93f3b153f16c98dddebadc075f05a6cc82a4c017dc34e6069518631d25521aef20e76f02857e3199590c4470cabc4edd5fd58099
|
7
|
+
data.tar.gz: 9714ef7ffc88015467a1b8c2c8942069a8428644b656ecfeda74a71fa7ac7eac1101e2d46d6214f4f983fe22209d75981a34ab411716b227f6f8c8f5fcaaf2e5
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Nialto Services
|
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
data/bin/freshen
ADDED
data/freshen.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
lib_path = File.expand_path('../lib', __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib_path) unless $LOAD_PATH.include?(lib_path)
|
3
|
+
require 'freshen/variables'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'freshen'
|
7
|
+
s.summary = 'Update installed components'
|
8
|
+
s.description = 'Freshen up installed components on your system (OS X and Linux only)'
|
9
|
+
s.version = Freshen::VERSION
|
10
|
+
s.date = '2015-08-20'
|
11
|
+
s.authors = ['Nialto Services']
|
12
|
+
s.email = ['support@nialtoservices.co.uk']
|
13
|
+
s.homepage = 'http://rubygems.org/gems/freshen'
|
14
|
+
s.files = `git ls-files`.split($/)
|
15
|
+
s.require_paths = ['lib']
|
16
|
+
s.license = 'MIT'
|
17
|
+
|
18
|
+
s.executables << 'freshen'
|
19
|
+
|
20
|
+
s.required_ruby_version = '>= 2.0.0'
|
21
|
+
s.add_dependency 'thor', '~> 0.19', '>= 0.19.1'
|
22
|
+
end
|
data/lib/freshen/cli.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
unless Object.const_defined?('Freshen')
|
2
|
+
raise "You can't load this file. Please load the freshen file instead."
|
3
|
+
end
|
4
|
+
|
5
|
+
unless Freshen.cli?
|
6
|
+
raise "Freshen::CLI should only be used by the command line interface binary"
|
7
|
+
end
|
8
|
+
|
9
|
+
class Freshen
|
10
|
+
# The command line interface class.
|
11
|
+
#
|
12
|
+
class CLI < Thor
|
13
|
+
desc "version", "Print the current version number"
|
14
|
+
long_desc <<-EOF
|
15
|
+
Usage:
|
16
|
+
\x5
|
17
|
+
\x5 $ freshen version
|
18
|
+
EOF
|
19
|
+
def version
|
20
|
+
puts Freshen::VERSION
|
21
|
+
end
|
22
|
+
|
23
|
+
desc "list", "List all installed fresheners"
|
24
|
+
long_desc <<-EOF
|
25
|
+
Usage:
|
26
|
+
\x5
|
27
|
+
\x5 $ freshen list
|
28
|
+
EOF
|
29
|
+
def list
|
30
|
+
fresheners = Freshener.all.keys
|
31
|
+
|
32
|
+
if fresheners.empty?
|
33
|
+
puts "No fresheners are installed"
|
34
|
+
else
|
35
|
+
puts fresheners.join(', ')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
desc "info FRESHENER", "Get info about a specific freshener"
|
40
|
+
long_desc <<-EOF
|
41
|
+
Usage:
|
42
|
+
\x5
|
43
|
+
\x5 $ freshen info rubygems
|
44
|
+
EOF
|
45
|
+
def info(freshener)
|
46
|
+
begin
|
47
|
+
Freshener.ensure_installed! freshener
|
48
|
+
rescue Freshen::FreshenerNotInstalled => e
|
49
|
+
puts "#{String.ballot.red} #{e}"
|
50
|
+
exit! 1
|
51
|
+
end
|
52
|
+
|
53
|
+
freshener = Freshener.instance_of(freshener)
|
54
|
+
|
55
|
+
puts freshener.class.name
|
56
|
+
puts " #{freshener.desc}"
|
57
|
+
end
|
58
|
+
|
59
|
+
desc "up [FRESHENERS]", "Run all/specified fresheners"
|
60
|
+
long_desc <<-EOF
|
61
|
+
Example:
|
62
|
+
\x5
|
63
|
+
\x5 Freshen up everything:
|
64
|
+
\x5 $ freshen up
|
65
|
+
\x5
|
66
|
+
\x5 Freshen up just rubygems:
|
67
|
+
\x5 $ freshen up rubygems
|
68
|
+
EOF
|
69
|
+
def up(*fresheners)
|
70
|
+
Freshenary.freshen_up(*fresheners)
|
71
|
+
end
|
72
|
+
|
73
|
+
default_task :up
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
unless Object.const_defined?('Freshen')
|
2
|
+
raise "You can't load this file. Please load the freshen file instead."
|
3
|
+
end
|
4
|
+
|
5
|
+
class Freshen
|
6
|
+
# A RuntimeError subclass for when the current
|
7
|
+
# system's kernel is unsupported.
|
8
|
+
#
|
9
|
+
class UnsupportedKernel < RuntimeError
|
10
|
+
def initialize(kernel)
|
11
|
+
@kernel = kernel
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_s
|
15
|
+
"Freshen doesn't support a #{@kernel} kernel"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# A NotImplementedError subclass for when the
|
20
|
+
# update method of a freshener subclass has not
|
21
|
+
# been implemented.
|
22
|
+
#
|
23
|
+
class UpdateMethodNotImplementedError < NotImplementedError
|
24
|
+
def initialize(freshener)
|
25
|
+
@name = freshener.class.name.split('::').last
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_s
|
29
|
+
"#{@name} does not implement the update method"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# An Exception subclass for when a freshener
|
34
|
+
# is not installed.
|
35
|
+
#
|
36
|
+
class FreshenerNotInstalled < Exception
|
37
|
+
def initialize(name)
|
38
|
+
@name = name
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_s
|
42
|
+
"The freshener #{@name} is not installed"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# A LoadError subclass for when a freshener
|
47
|
+
# failed to load.
|
48
|
+
#
|
49
|
+
class FreshenerLoadError < LoadError
|
50
|
+
def initialize(name)
|
51
|
+
@name = name
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_s
|
55
|
+
"Unable to load freshener #{@name}"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# A RuntimeError subclass for when an executing
|
60
|
+
# command fails.
|
61
|
+
#
|
62
|
+
class ExecutableError < RuntimeError
|
63
|
+
def initialize(name, command, *args)
|
64
|
+
@name = name
|
65
|
+
@command = command
|
66
|
+
@args = args.map { |a| a.to_s }
|
67
|
+
end
|
68
|
+
|
69
|
+
def to_s
|
70
|
+
"#{@name} Command Failed: '#{Executable.command_string(@command, *@args)}'"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
unless Object.const_defined?('Freshen')
|
2
|
+
raise "You can't load this file. Please load the freshen file instead."
|
3
|
+
end
|
4
|
+
|
5
|
+
class Freshen
|
6
|
+
# This module allows you to execute shell
|
7
|
+
# commands without terminating the current
|
8
|
+
# ruby process.
|
9
|
+
#
|
10
|
+
module Executable
|
11
|
+
# Get the full command string for a
|
12
|
+
# command and it's arguments.
|
13
|
+
#
|
14
|
+
# Example:
|
15
|
+
# >> Freshen::Executable.command_string :gem, :update
|
16
|
+
# => "gem update"
|
17
|
+
#
|
18
|
+
def self.command_string(command, *args)
|
19
|
+
args ||= []
|
20
|
+
args.unshift(command)
|
21
|
+
args.join(' ')
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
# Execute a shell command.
|
26
|
+
#
|
27
|
+
# If you provide a block
|
28
|
+
#
|
29
|
+
# Arguments:
|
30
|
+
# command: (String)
|
31
|
+
# args: (Splat)
|
32
|
+
#
|
33
|
+
# Example:
|
34
|
+
# >> execute :gem, :update
|
35
|
+
# => nil
|
36
|
+
#
|
37
|
+
def execute(command, *args, &block)
|
38
|
+
freshening = ("freshen" == caller_locations(1,1)[0].label)
|
39
|
+
cleaning = ("cleanup" == caller_locations(1,1)[0].label)
|
40
|
+
|
41
|
+
if Freshen.cli?
|
42
|
+
if freshening or cleaning
|
43
|
+
puts "#{String.prefix.blue} #{Executable.command_string(command, *args)}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
read, write = IO.pipe
|
48
|
+
result = ""
|
49
|
+
|
50
|
+
duration = Time.duration_of do
|
51
|
+
begin
|
52
|
+
pid = fork do
|
53
|
+
read.close
|
54
|
+
_execute(write, command, *args)
|
55
|
+
end
|
56
|
+
|
57
|
+
Process.wait(pid)
|
58
|
+
|
59
|
+
write.close
|
60
|
+
|
61
|
+
while buffer = read.gets
|
62
|
+
result += buffer
|
63
|
+
result += "\n"
|
64
|
+
end
|
65
|
+
ensure
|
66
|
+
read.close unless read.closed?
|
67
|
+
write.close unless write.closed?
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
if duration
|
72
|
+
duration = (" %.2f sec" % duration)
|
73
|
+
end
|
74
|
+
|
75
|
+
$stdout.flush
|
76
|
+
|
77
|
+
success = $?.success?
|
78
|
+
|
79
|
+
yield success, result if block_given?
|
80
|
+
|
81
|
+
if freshening or cleaning
|
82
|
+
if success
|
83
|
+
puts "#{String.checkmark.green}#{duration.green}" if Freshen.cli?
|
84
|
+
else
|
85
|
+
puts "#{String.ballot.red}#{duration.red}" if Freshen.cli?
|
86
|
+
|
87
|
+
raise ExecutableError.new(self.class.name, command, *args)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
return success
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
# Execute a shell command using the specified output pipe.
|
96
|
+
#
|
97
|
+
# This method should not be used directly.
|
98
|
+
#
|
99
|
+
# Arguments:
|
100
|
+
# output: (IO)
|
101
|
+
# command: (String)
|
102
|
+
# args: (Splat)
|
103
|
+
#
|
104
|
+
# Example:
|
105
|
+
# >> read, write = IO.pipe
|
106
|
+
# >> _execute(write, :pwd)
|
107
|
+
#
|
108
|
+
def _execute(output, command, *args)
|
109
|
+
$stdout.reopen(output)
|
110
|
+
$stderr.reopen(output)
|
111
|
+
|
112
|
+
output.close
|
113
|
+
|
114
|
+
command = command.to_s
|
115
|
+
args.collect!(&:to_s)
|
116
|
+
|
117
|
+
exec(command, *args) rescue nil
|
118
|
+
|
119
|
+
exit! 1
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class Module
|
2
|
+
# Define static attributes on a class.
|
3
|
+
#
|
4
|
+
# Example:
|
5
|
+
# >> class BaseTest
|
6
|
+
# >> attr_class :name
|
7
|
+
# >> end
|
8
|
+
# >>
|
9
|
+
# >> class Test < BaseTest
|
10
|
+
# >> name "Test"
|
11
|
+
# >> end
|
12
|
+
# >>
|
13
|
+
# >> test = Test.new
|
14
|
+
# >> test.name
|
15
|
+
# => "Test"
|
16
|
+
#
|
17
|
+
def attr_class(*attributes)
|
18
|
+
attributes.each do |attribute|
|
19
|
+
module_eval <<-EOS
|
20
|
+
class << self
|
21
|
+
def #{attribute}(val=nil)
|
22
|
+
val.nil? ? @#{attribute} : @#{attribute} = val
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def #{attribute}
|
27
|
+
self.class.#{attribute}
|
28
|
+
end
|
29
|
+
EOS
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
class String
|
2
|
+
# A simple string prefix.
|
3
|
+
#
|
4
|
+
# Example:
|
5
|
+
# >> String.prefix
|
6
|
+
# => "==>"
|
7
|
+
#
|
8
|
+
def self.prefix
|
9
|
+
"==>"
|
10
|
+
end
|
11
|
+
|
12
|
+
# A UTF-8 checkmark.
|
13
|
+
#
|
14
|
+
# Example:
|
15
|
+
# >> String.checkmark
|
16
|
+
# => "✔"
|
17
|
+
#
|
18
|
+
def self.checkmark
|
19
|
+
"\u2714"
|
20
|
+
end
|
21
|
+
|
22
|
+
# A UTF-8 ballot.
|
23
|
+
#
|
24
|
+
# Example:
|
25
|
+
# >> String.ballot
|
26
|
+
# => "✘"
|
27
|
+
#
|
28
|
+
def self.ballot
|
29
|
+
"\u2718"
|
30
|
+
end
|
31
|
+
|
32
|
+
# Make a string bold.
|
33
|
+
#
|
34
|
+
# Example:
|
35
|
+
# >> puts "freshen".bold
|
36
|
+
# => "\e[1mfreshen\e[0m"
|
37
|
+
#
|
38
|
+
def bold
|
39
|
+
modify(1)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Make a string red.
|
43
|
+
#
|
44
|
+
# Example:
|
45
|
+
# >> puts "freshen".red
|
46
|
+
# => "\e[31mfreshen\e[0m"
|
47
|
+
#
|
48
|
+
def red
|
49
|
+
modify(31)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Make a string green.
|
53
|
+
#
|
54
|
+
# Example:
|
55
|
+
# >> puts "freshen".green
|
56
|
+
# => "\e[32mfreshen\e[0m"
|
57
|
+
#
|
58
|
+
def green
|
59
|
+
modify(32)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Make a string yellow.
|
63
|
+
#
|
64
|
+
# Example:
|
65
|
+
# >> puts "freshen".yellow
|
66
|
+
# => "\e[33mfreshen\e[0m"
|
67
|
+
#
|
68
|
+
def yellow
|
69
|
+
modify(33)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Make a string blue.
|
73
|
+
#
|
74
|
+
# Example:
|
75
|
+
# >> puts "freshen".blue
|
76
|
+
# => "\e[34mfreshen\e[0m"
|
77
|
+
#
|
78
|
+
def blue
|
79
|
+
modify(34)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Make a string gray.
|
83
|
+
#
|
84
|
+
# Example:
|
85
|
+
# >> puts "freshen".gray
|
86
|
+
# => "\e[37mfreshen\e[0m"
|
87
|
+
#
|
88
|
+
def gray
|
89
|
+
modify(37)
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
# Wrap the current string using the
|
94
|
+
# specified code.
|
95
|
+
#
|
96
|
+
def modify(code)
|
97
|
+
"\e[#{code}m#{self}\e[0m"
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class Time
|
2
|
+
# The total time (in seconds) for the block
|
3
|
+
# to complete.
|
4
|
+
#
|
5
|
+
# Example:
|
6
|
+
# >> Time.duration_of { sleep 2 }
|
7
|
+
# => 2.000000000000001
|
8
|
+
def self.duration_of(&block)
|
9
|
+
return nil unless block_given?
|
10
|
+
|
11
|
+
start_time = Time.now
|
12
|
+
|
13
|
+
yield
|
14
|
+
|
15
|
+
end_time = Time.now
|
16
|
+
|
17
|
+
end_time.to_f - start_time.to_f
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
unless Object.const_defined?('Freshen')
|
2
|
+
raise "You can't load this file. Please load the freshen file instead."
|
3
|
+
end
|
4
|
+
|
5
|
+
class Freshen
|
6
|
+
# The system class responsible for checking if
|
7
|
+
# the current system's kernel is supported.
|
8
|
+
#
|
9
|
+
class System
|
10
|
+
# An array of supported kernels
|
11
|
+
#
|
12
|
+
attr_reader :supported_kernels
|
13
|
+
|
14
|
+
# Setup an instance of this class with an array of
|
15
|
+
# supported kernels
|
16
|
+
#
|
17
|
+
# Example:
|
18
|
+
# >> Freshen::System.new
|
19
|
+
# => #<Freshen:0x00000000000000>
|
20
|
+
#
|
21
|
+
def initialize
|
22
|
+
@supported_kernels = [:darwin, :linux]
|
23
|
+
end
|
24
|
+
|
25
|
+
# Get the current version of this system's kernel
|
26
|
+
#
|
27
|
+
# Example (OS X):
|
28
|
+
# >> system = Freshen::System.new
|
29
|
+
# >> system.kernel
|
30
|
+
# => darwin
|
31
|
+
#
|
32
|
+
# Example (Linux):
|
33
|
+
# >> system = Freshen::System.new
|
34
|
+
# >> system.kernel
|
35
|
+
# => linux
|
36
|
+
#
|
37
|
+
def kernel
|
38
|
+
Gem::Platform.local.os
|
39
|
+
end
|
40
|
+
|
41
|
+
# A boolean value of whether or not this system's
|
42
|
+
# kernel is supported
|
43
|
+
#
|
44
|
+
# Example:
|
45
|
+
# >> system = Freshen::System.new
|
46
|
+
# >> system.supported?
|
47
|
+
# => true
|
48
|
+
#
|
49
|
+
def supported?
|
50
|
+
@supported_kernels.each do |k|
|
51
|
+
return true if k.to_s == kernel
|
52
|
+
end
|
53
|
+
|
54
|
+
return false
|
55
|
+
end
|
56
|
+
|
57
|
+
# Check if the current kernel is supported and if not,
|
58
|
+
# raise an UnsupportedKernel error
|
59
|
+
#
|
60
|
+
# Example:
|
61
|
+
# >> system = Freshen::System.new
|
62
|
+
# >> system.check_supported!
|
63
|
+
# => nil
|
64
|
+
#
|
65
|
+
def check_supported!
|
66
|
+
unless supported?
|
67
|
+
raise UnsupportedKernel.new(current)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Check if the current Operating System is supported
|
72
|
+
# and if not, raise an UnsupportedOperatingSystem error
|
73
|
+
#
|
74
|
+
# Example:
|
75
|
+
# >> Freshen::System.check_supported!
|
76
|
+
# => nil
|
77
|
+
#
|
78
|
+
def self.check_supported!
|
79
|
+
system = Freshen::System.new
|
80
|
+
system.check_supported!
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
Freshen::System.check_supported!
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class Freshen
|
2
|
+
# The current version of the gem.
|
3
|
+
#
|
4
|
+
VERSION = '0.0.1'
|
5
|
+
|
6
|
+
# The prefix of where data is stored.
|
7
|
+
#
|
8
|
+
PREFIX = File.join('/', 'usr', 'local')
|
9
|
+
|
10
|
+
# The directory where data is stored.
|
11
|
+
#
|
12
|
+
FRESHEN_DIR = File.join(PREFIX, 'freshen')
|
13
|
+
|
14
|
+
# The directory where fresheners live.
|
15
|
+
#
|
16
|
+
FRESHENERS_DIR = File.join(FRESHEN_DIR, 'fresheners')
|
17
|
+
end
|
data/lib/freshen.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
# This class contains the core Freshen functionality
|
4
|
+
class Freshen
|
5
|
+
# This will use the ruby 'require' method to require
|
6
|
+
# all freshen files included with this gem.
|
7
|
+
#
|
8
|
+
# Example:
|
9
|
+
# >> Freshen.require_tree!
|
10
|
+
# => nil
|
11
|
+
#
|
12
|
+
def self.require_tree!
|
13
|
+
require 'freshen/helpers'
|
14
|
+
require 'freshen/variables'
|
15
|
+
require 'freshen/errors'
|
16
|
+
require 'freshen/system'
|
17
|
+
require 'freshen/executable'
|
18
|
+
require 'freshener'
|
19
|
+
require 'freshenary'
|
20
|
+
|
21
|
+
return nil
|
22
|
+
end
|
23
|
+
|
24
|
+
# This will create all required directories
|
25
|
+
# if they don't exist yet.
|
26
|
+
#
|
27
|
+
# Example:
|
28
|
+
# >> Freshen.create_directories!
|
29
|
+
# => nil
|
30
|
+
#
|
31
|
+
def self.create_directories!
|
32
|
+
FileUtils.mkdir_p FRESHENERS_DIR
|
33
|
+
|
34
|
+
return nil
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns a boolean value of whether or not
|
38
|
+
# we are running by the CLI.
|
39
|
+
#
|
40
|
+
def self.cli?
|
41
|
+
defined? FRESHEN_CLI and true == FRESHEN_CLI
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
Freshen.require_tree!
|
46
|
+
Freshen.create_directories!
|
data/lib/freshenary.rb
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
unless Object.const_defined?('Freshen')
|
2
|
+
raise "You can't load this file. Please load the freshen file instead."
|
3
|
+
end
|
4
|
+
|
5
|
+
class Freshenary
|
6
|
+
# Call the update method on either all
|
7
|
+
# or the specified fresheners.
|
8
|
+
#
|
9
|
+
# Arguments:
|
10
|
+
# fresheners: (Array)
|
11
|
+
#
|
12
|
+
# Example:
|
13
|
+
# >> Freshenary.freshen_up
|
14
|
+
# => nil
|
15
|
+
#
|
16
|
+
def self.freshen_up(*fresheners)
|
17
|
+
if fresheners.empty?
|
18
|
+
fresheners = Freshener.all
|
19
|
+
else
|
20
|
+
if Freshen.cli?
|
21
|
+
begin
|
22
|
+
Freshener.ensure_installed!(*fresheners)
|
23
|
+
rescue Freshen::FreshenerNotInstalled => e
|
24
|
+
puts "#{String.ballot.red} #{e}"
|
25
|
+
exit! 1
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
fresheners = Freshener.instances_of(*fresheners)
|
30
|
+
end
|
31
|
+
|
32
|
+
status = {
|
33
|
+
successful: {
|
34
|
+
color: :green,
|
35
|
+
count: 0
|
36
|
+
},
|
37
|
+
skipped: {
|
38
|
+
color: :yellow,
|
39
|
+
count: 0
|
40
|
+
},
|
41
|
+
failed: {
|
42
|
+
color: :red,
|
43
|
+
count: 0
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
47
|
+
duration = Time.duration_of do
|
48
|
+
fresheners.each do |name, freshener|
|
49
|
+
if freshener.needs_freshening?
|
50
|
+
print "#{String.prefix.green} " if Freshen.cli?
|
51
|
+
puts "Freshening #{freshener.class.name}".bold if Freshen.cli?
|
52
|
+
|
53
|
+
cleaning = false
|
54
|
+
|
55
|
+
begin
|
56
|
+
freshener.freshen
|
57
|
+
|
58
|
+
if freshener.respond_to? :cleanup
|
59
|
+
print "\n#{String.prefix.green} " if Freshen.cli?
|
60
|
+
puts "Cleaning up #{freshener.class.name}".bold if Freshen.cli?
|
61
|
+
|
62
|
+
cleaning = true
|
63
|
+
|
64
|
+
freshener.cleanup(true)
|
65
|
+
end
|
66
|
+
|
67
|
+
status[:successful][:count] += 1
|
68
|
+
rescue Freshen::ExecutableError => e
|
69
|
+
if false == cleaning and freshener.respond_to? :cleanup
|
70
|
+
print "\n#{String.prefix.red} " if Freshen.cli?
|
71
|
+
puts "Cleaning up #{freshener.class.name}".bold if Freshen.cli?
|
72
|
+
|
73
|
+
freshener.cleanup(false)
|
74
|
+
end
|
75
|
+
|
76
|
+
raise e unless Freshen.cli?
|
77
|
+
|
78
|
+
status[:failed][:count] += 1
|
79
|
+
end
|
80
|
+
else
|
81
|
+
print "#{String.prefix.yellow} " if Freshen.cli?
|
82
|
+
puts "#{freshener.class.name} is already fresh".bold if Freshen.cli?
|
83
|
+
|
84
|
+
status[:skipped][:count] += 1
|
85
|
+
end
|
86
|
+
|
87
|
+
puts ""
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
if Freshen.cli?
|
92
|
+
status.delete_if { |key, value| 0 == value[:count] }
|
93
|
+
status = status.map { |key, value| "#{value[:count]} #{key}".send(value[:color]) }
|
94
|
+
|
95
|
+
puts "#{status.join(" / ")} (%.2f sec)" % duration
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
data/lib/freshener.rb
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
unless Object.const_defined?('Freshen')
|
2
|
+
raise "You can't load this file. Please load the freshen file instead."
|
3
|
+
end
|
4
|
+
|
5
|
+
class Freshener
|
6
|
+
include Freshen::Executable
|
7
|
+
|
8
|
+
# A short description of the freshener
|
9
|
+
attr_class :desc
|
10
|
+
|
11
|
+
# Returns a Hash of all installed fresheners.
|
12
|
+
#
|
13
|
+
# Example:
|
14
|
+
# >> Freshener.all
|
15
|
+
# => { "rubygems" => #<Rubygems:0x00000000000000> }
|
16
|
+
#
|
17
|
+
def self.all
|
18
|
+
fresheners = Dir.glob(File.join(Freshen::FRESHENERS_DIR, "*.rb"))
|
19
|
+
fresheners.map! { |path| File.basename(path, ".rb") }
|
20
|
+
instances_of(*fresheners)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns a Hash containing instances of the
|
24
|
+
# specified freshehers.
|
25
|
+
#
|
26
|
+
# Example:
|
27
|
+
# >> Freshener.instances_of :rubygems
|
28
|
+
# => { "rubygems" => #<Rubygems:0x00000000000000> }
|
29
|
+
#
|
30
|
+
def self.instances_of(*fresheners)
|
31
|
+
fresheners.sort_by! do |name|
|
32
|
+
name
|
33
|
+
end
|
34
|
+
|
35
|
+
fresheners.map! do |name|
|
36
|
+
[name.to_s, instance_of(name.to_s)]
|
37
|
+
end
|
38
|
+
|
39
|
+
Hash[*fresheners.flatten]
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns an instance of the specified freshener.
|
43
|
+
#
|
44
|
+
# Arguments:
|
45
|
+
# name: (String)
|
46
|
+
#
|
47
|
+
# Example:
|
48
|
+
# >> Freshener.instance_of :rubygems
|
49
|
+
# => #<Rubygems:0x00000000000000>
|
50
|
+
#
|
51
|
+
def self.instance_of(name)
|
52
|
+
load_by_name(name)
|
53
|
+
|
54
|
+
klass = class_for(name)
|
55
|
+
klass = Object.const_get(klass)
|
56
|
+
klass.new
|
57
|
+
end
|
58
|
+
|
59
|
+
# Get the class name for a freshener.
|
60
|
+
#
|
61
|
+
# Arguments:
|
62
|
+
# name: (String)
|
63
|
+
#
|
64
|
+
# Example:
|
65
|
+
# >> Freshener.class_for :rubygems
|
66
|
+
# => "Rubygems"
|
67
|
+
#
|
68
|
+
def self.class_for(name)
|
69
|
+
klass = name.to_s.capitalize
|
70
|
+
klass.gsub!(/[-_.\s]([a-zA-Z0-9])/) { $1.upcase }
|
71
|
+
klass.tr!("+", "x")
|
72
|
+
klass
|
73
|
+
end
|
74
|
+
|
75
|
+
# Load a freshener from the fresheners directory.
|
76
|
+
#
|
77
|
+
# Arguments:
|
78
|
+
# name: (String)
|
79
|
+
#
|
80
|
+
# Example:
|
81
|
+
# >> Freshener.load_by_name :rubygems
|
82
|
+
# => nil
|
83
|
+
#
|
84
|
+
# Raises:
|
85
|
+
# FreshenerNotInstalled: When the specified freshener is not installed.
|
86
|
+
# FreshenerLoadError: When the specified freshener could not be loaded.
|
87
|
+
#
|
88
|
+
def self.load_by_name(name)
|
89
|
+
begin
|
90
|
+
require File.join(Freshen::FRESHENERS_DIR, "#{name}.rb")
|
91
|
+
rescue LoadError
|
92
|
+
raise Freshen::FreshenerLoadError.new(name)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# Check that the specified fresheners are installed.
|
97
|
+
#
|
98
|
+
# Arguments:
|
99
|
+
# fresheners: (Splat)
|
100
|
+
#
|
101
|
+
# Example:
|
102
|
+
# >> Freshener.installed? :rubygems
|
103
|
+
# => true
|
104
|
+
#
|
105
|
+
def self.installed?(*fresheners)
|
106
|
+
fresheners.each do |name|
|
107
|
+
return false unless File.file? File.join(Freshen::FRESHENERS_DIR, "#{name}.rb")
|
108
|
+
end
|
109
|
+
|
110
|
+
true
|
111
|
+
end
|
112
|
+
|
113
|
+
# Ensure that the specified fresheners are installed.
|
114
|
+
#
|
115
|
+
# Arguments:
|
116
|
+
# >> Freshener.ensure_installed! :rubygems
|
117
|
+
# => nil
|
118
|
+
#
|
119
|
+
def self.ensure_installed!(*fresheners)
|
120
|
+
fresheners.each do |name|
|
121
|
+
unless installed? name
|
122
|
+
raise Freshen::FreshenerNotInstalled.new(name)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# Mark certain class methods as private
|
128
|
+
private_class_method :load_by_name
|
129
|
+
|
130
|
+
# Whether or not we the freshener needs
|
131
|
+
# freshening up.
|
132
|
+
#
|
133
|
+
# Example:
|
134
|
+
# >> rubygems = Rubygems.new
|
135
|
+
# >> rubygems.needs_freshening?
|
136
|
+
# => true
|
137
|
+
#
|
138
|
+
def needs_freshening?
|
139
|
+
true
|
140
|
+
end
|
141
|
+
|
142
|
+
# Freshen up the freshener!
|
143
|
+
#
|
144
|
+
# Example:
|
145
|
+
# >> rubygems = Rubygems.new
|
146
|
+
# >> rubygems.freshen
|
147
|
+
# => nil
|
148
|
+
#
|
149
|
+
def freshen
|
150
|
+
raise Freshen::UpdateMethodNotImplementedError.new(self)
|
151
|
+
end
|
152
|
+
end
|
metadata
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: freshen
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nialto Services
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-08-20 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.19'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.19.1
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0.19'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.19.1
|
33
|
+
description: Freshen up installed components on your system (OS X and Linux only)
|
34
|
+
email:
|
35
|
+
- support@nialtoservices.co.uk
|
36
|
+
executables:
|
37
|
+
- freshen
|
38
|
+
extensions: []
|
39
|
+
extra_rdoc_files: []
|
40
|
+
files:
|
41
|
+
- LICENSE
|
42
|
+
- README.md
|
43
|
+
- bin/freshen
|
44
|
+
- freshen.gemspec
|
45
|
+
- lib/freshen.rb
|
46
|
+
- lib/freshen/cli.rb
|
47
|
+
- lib/freshen/errors.rb
|
48
|
+
- lib/freshen/executable.rb
|
49
|
+
- lib/freshen/helpers.rb
|
50
|
+
- lib/freshen/helpers/module.rb
|
51
|
+
- lib/freshen/helpers/string.rb
|
52
|
+
- lib/freshen/helpers/time.rb
|
53
|
+
- lib/freshen/system.rb
|
54
|
+
- lib/freshen/variables.rb
|
55
|
+
- lib/freshenary.rb
|
56
|
+
- lib/freshener.rb
|
57
|
+
homepage: http://rubygems.org/gems/freshen
|
58
|
+
licenses:
|
59
|
+
- MIT
|
60
|
+
metadata: {}
|
61
|
+
post_install_message:
|
62
|
+
rdoc_options: []
|
63
|
+
require_paths:
|
64
|
+
- lib
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 2.0.0
|
70
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
requirements: []
|
76
|
+
rubyforge_project:
|
77
|
+
rubygems_version: 2.4.8
|
78
|
+
signing_key:
|
79
|
+
specification_version: 4
|
80
|
+
summary: Update installed components
|
81
|
+
test_files: []
|