lolcommits 0.5.7 → 0.5.8.pre1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/.rubocop.yml +1 -0
- data/.rubocop_todo.yml +16 -161
- data/.travis.yml +11 -4
- data/Gemfile +2 -2
- data/Rakefile +24 -32
- data/bin/lolcommits +62 -125
- data/features/bugs.feature +24 -9
- data/features/lolcommits.feature +136 -145
- data/features/plugins.feature +16 -33
- data/features/step_definitions/lolcommits_steps.rb +91 -71
- data/features/support/env.rb +18 -48
- data/features/support/path_helpers.rb +9 -8
- data/lib/lolcommits.rb +3 -10
- data/lib/lolcommits/capturer.rb +10 -2
- data/lib/lolcommits/capturer/capture_linux.rb +1 -1
- data/lib/lolcommits/capturer/capture_linux_animated.rb +12 -13
- data/lib/lolcommits/capturer/capture_mac_animated.rb +12 -13
- data/lib/lolcommits/cli/fatals.rb +77 -0
- data/lib/lolcommits/cli/launcher.rb +29 -0
- data/lib/lolcommits/cli/process_runner.rb +48 -0
- data/lib/lolcommits/cli/timelapse_gif.rb +45 -0
- data/lib/lolcommits/configuration.rb +30 -133
- data/lib/lolcommits/git_info.rb +58 -28
- data/lib/lolcommits/installation.rb +11 -21
- data/lib/lolcommits/platform.rb +134 -0
- data/lib/lolcommits/plugin.rb +2 -2
- data/lib/lolcommits/plugins/dot_com.rb +15 -15
- data/lib/lolcommits/plugins/lol_protonet.rb +68 -0
- data/lib/lolcommits/plugins/lol_twitter.rb +12 -15
- data/lib/lolcommits/plugins/lol_yammer.rb +4 -6
- data/lib/lolcommits/plugins/lolsrv.rb +8 -11
- data/lib/lolcommits/plugins/loltext.rb +7 -7
- data/lib/lolcommits/plugins/tranzlate.rb +70 -70
- data/lib/lolcommits/plugins/uploldz.rb +8 -8
- data/lib/lolcommits/runner.rb +36 -35
- data/lib/lolcommits/version.rb +1 -1
- data/lolcommits.gemspec +11 -10
- data/test/lolcommits_test.rb +35 -0
- data/test/plugins_test.rb +52 -0
- metadata +41 -20
- data/test/test_lolcommits.rb +0 -78
@@ -12,7 +12,7 @@ module Lolcommits
|
|
12
12
|
tmpdir = Dir.mktmpdir
|
13
13
|
|
14
14
|
# Default delay is 1s
|
15
|
-
delay =
|
15
|
+
delay = capture_delay != 0 ? capture_delay : 1
|
16
16
|
|
17
17
|
# There's no way to give a capture delay in mplayer, but a number of frame
|
18
18
|
# mplayer's "delay" is actually a number of frames at 25 fps
|
@@ -8,21 +8,20 @@ module Lolcommits
|
|
8
8
|
|
9
9
|
# capture the raw video with ffmpeg video4linux2
|
10
10
|
system_call "ffmpeg -v quiet -y -f video4linux2 -video_size 320x240 -i #{capture_device_string} -t #{capture_duration} #{video_location} > /dev/null"
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
return unless File.exist?(video_location)
|
12
|
+
# convert raw video to png frames with ffmpeg
|
13
|
+
system_call "ffmpeg #{capture_delay_string} -v quiet -i #{video_location} -t #{animated_duration} #{frames_location}/%09d.png > /dev/null"
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
# use fps to set delay and number of frames to skip (for lower filesized gifs)
|
16
|
+
fps = video_fps(video_location)
|
17
|
+
skip = frame_skip(fps)
|
18
|
+
delay = frame_delay(fps, skip)
|
19
|
+
debug "Capturer: anaimated gif choosing every #{skip} frames with a frame delay of #{delay}"
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
end
|
21
|
+
# create the looping animated gif from frames (picks nth frame with seq)
|
22
|
+
seq_command = "seq -f #{frames_location}/%09g.png 1 #{skip} #{Dir["#{frames_location}/*"].length}"
|
23
|
+
# convert to animated gif with delay and gif optimisation
|
24
|
+
system_call "convert -layers OptimizeTransparency -delay #{delay} -loop 0 `#{seq_command}` -coalesce #{snapshot_location} > /dev/null"
|
26
25
|
end
|
27
26
|
|
28
27
|
private
|
@@ -8,21 +8,20 @@ module Lolcommits
|
|
8
8
|
|
9
9
|
# capture the raw video with videosnap
|
10
10
|
system_call "#{executable_path} -s 240 #{capture_device_string}#{capture_delay_string}-t #{animated_duration} --no-audio #{video_location} > /dev/null"
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
return unless File.exist?(video_location)
|
12
|
+
# convert raw video to png frames with ffmpeg
|
13
|
+
system_call "ffmpeg -v quiet -i #{video_location} -t #{animated_duration} #{frames_location}/%09d.png"
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
# use fps to set delay and number of frames to skip (for lower filesized gifs)
|
16
|
+
fps = video_fps(video_location)
|
17
|
+
skip = frame_skip(fps)
|
18
|
+
delay = frame_delay(fps, skip)
|
19
|
+
debug "Capturer: anaimated gif choosing every #{skip} frames with a frame delay of #{delay}"
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
end
|
21
|
+
# create the looping animated gif from frames (picks nth frame with seq)
|
22
|
+
seq_command = "seq -f #{frames_location}/%09g.png 1 #{skip} #{Dir["#{frames_location}/*"].length}"
|
23
|
+
# convert to animated gif with delay and gif optimisation
|
24
|
+
system_call "convert -layers OptimizeTransparency -delay #{delay} -loop 0 `#{seq_command}` -coalesce #{snapshot_location}"
|
26
25
|
end
|
27
26
|
|
28
27
|
def executable_path
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require 'lolcommits/platform'
|
3
|
+
require 'methadone'
|
4
|
+
|
5
|
+
module Lolcommits
|
6
|
+
module CLI
|
7
|
+
# Helper methods for failing on error conditions in the lolcommits CLI.
|
8
|
+
module Fatals
|
9
|
+
include Lolcommits
|
10
|
+
include Methadone::CLILogging
|
11
|
+
|
12
|
+
# Check for platform related conditions that could prevent lolcommits from
|
13
|
+
# working properly.
|
14
|
+
#
|
15
|
+
# Die with an informative error message if any occur.
|
16
|
+
def self.die_on_fatal_platform_conditions!
|
17
|
+
# make sure the capture binaries are in a good state
|
18
|
+
if Platform.platform_mac?
|
19
|
+
%w(imagesnap videosnap).each do |executable|
|
20
|
+
next if File.executable? File.join(Configuration::LOLCOMMITS_ROOT, 'vendor', 'ext', executable, executable)
|
21
|
+
fatal "Couldn't properly execute #{executable} for some reason, "\
|
22
|
+
'please file a bug?!'
|
23
|
+
exit 1
|
24
|
+
end
|
25
|
+
elsif Platform.platform_linux?
|
26
|
+
unless Platform.command_which('mplayer')
|
27
|
+
fatal "Couldn't find mplayer in your PATH!"
|
28
|
+
exit 1
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# make sure we can find the Impact truetype font
|
33
|
+
unless File.readable? File.join(Configuration::LOLCOMMITS_ROOT, 'vendor', 'fonts', 'Impact.ttf')
|
34
|
+
fatal "Couldn't properly read Impact font from gem package, "\
|
35
|
+
'please file a bug?!'
|
36
|
+
exit 1
|
37
|
+
end
|
38
|
+
|
39
|
+
# make sure imagemagick is around and good to go
|
40
|
+
unless Platform.valid_imagemagick_installed?
|
41
|
+
fatal 'FATAL: ImageMagick does not appear to be properly installed!'\
|
42
|
+
'(or version is too old)'
|
43
|
+
exit 1
|
44
|
+
end
|
45
|
+
|
46
|
+
# check for a error condition with git config affecting ruby-git
|
47
|
+
if Platform.git_config_color_always?
|
48
|
+
fatal 'Due to a bug in the ruby-git library, git config for color.ui'\
|
49
|
+
" cannot be set to 'always'."
|
50
|
+
fatal "Try setting it to 'auto' instead!"
|
51
|
+
exit 1
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Die with an informative error message if ffmpeg is not installed.
|
56
|
+
# This is only used for certain functions (such as animation), so only run
|
57
|
+
# this when you know the user wants to perform one of them.
|
58
|
+
def self.die_if_no_valid_ffmpeg_installed!
|
59
|
+
unless Platform.valid_ffmpeg_installed?
|
60
|
+
fatal 'FATAL: ffmpeg does not appear to be properly installed!'
|
61
|
+
exit 1
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# If we are not in a git repo, we can't do git related things!
|
66
|
+
# Die with an informative error message in that case.
|
67
|
+
def self.die_if_not_git_repo!
|
68
|
+
debug 'Checking for valid git repo'
|
69
|
+
Git.open('.') # FIXME: should be extracted to GitInfo class
|
70
|
+
rescue ArgumentError
|
71
|
+
# ruby-git throws an argument error if path isnt for a valid git repo.
|
72
|
+
fatal "Erm? Can't do that since we're not in a valid git repository!"
|
73
|
+
exit 1
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require 'launchy'
|
3
|
+
|
4
|
+
module Lolcommits
|
5
|
+
module CLI
|
6
|
+
# Helper class for wrapping the opening of files on the desktop in a
|
7
|
+
# cross-platform way.
|
8
|
+
#
|
9
|
+
# Right now this is mostly just a wrapper for Launchy, in case we want
|
10
|
+
# to factor out it's dependency later or swap it out.
|
11
|
+
class Launcher
|
12
|
+
def self.open_image(path)
|
13
|
+
open_with_launchy(path)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.open_folder(path)
|
17
|
+
open_with_launchy(path)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Opens with Launchy, which knows how to open pretty much anything
|
21
|
+
# local files, urls, etc.
|
22
|
+
#
|
23
|
+
# Private so we replace it later easier if we want.
|
24
|
+
def self.open_with_launchy(thing)
|
25
|
+
Launchy.open(thing)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module Lolcommits
|
4
|
+
module CLI
|
5
|
+
# Helper class for forking lolcommits process to the background (or not).
|
6
|
+
class ProcessRunner
|
7
|
+
# Initializes a new process runner.
|
8
|
+
#
|
9
|
+
# @param config [Lolcommits::Configuration]
|
10
|
+
def initialize(config)
|
11
|
+
@configuration = config
|
12
|
+
end
|
13
|
+
|
14
|
+
# Forks the lolcommits process if requested.
|
15
|
+
#
|
16
|
+
# Writes the PID of the lolcommits process to the filesystem when
|
17
|
+
# backgrounded, for monitoring purposes.
|
18
|
+
#
|
19
|
+
# @param please [Boolean] whether or not to fork lolcommits process
|
20
|
+
# @yield the main event loop for lolcommits
|
21
|
+
def fork_me?(please, &block)
|
22
|
+
if please
|
23
|
+
$stdout.sync = true
|
24
|
+
write_pid fork {
|
25
|
+
yield block
|
26
|
+
delete_pid
|
27
|
+
}
|
28
|
+
else
|
29
|
+
yield block
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def write_pid(pid)
|
36
|
+
File.open(pid_file, 'w') { |f| f.write(pid) }
|
37
|
+
end
|
38
|
+
|
39
|
+
def delete_pid
|
40
|
+
File.delete(pid_file) if File.exist?(pid_file)
|
41
|
+
end
|
42
|
+
|
43
|
+
def pid_file
|
44
|
+
File.join(@configuration.loldir, 'lolcommits.pid')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require 'lolcommits/cli/fatals'
|
3
|
+
|
4
|
+
require 'mini_magick'
|
5
|
+
|
6
|
+
module Lolcommits
|
7
|
+
module CLI
|
8
|
+
# Creates an animated timeline GIF of lolcommits history.
|
9
|
+
class TimelapseGif
|
10
|
+
# param config [Lolcommits::Configuration]
|
11
|
+
def initialize(config)
|
12
|
+
@configuration = config
|
13
|
+
end
|
14
|
+
|
15
|
+
# Runs the history timeline animator task thingy
|
16
|
+
# param args [String] the arg passed to the gif command on CLI (optional)
|
17
|
+
def run(args = nil)
|
18
|
+
Fatals.die_if_not_git_repo!
|
19
|
+
|
20
|
+
case args
|
21
|
+
when 'today'
|
22
|
+
lolimages = @configuration.jpg_images_today
|
23
|
+
filename = "#{Date.today}.gif"
|
24
|
+
else
|
25
|
+
lolimages = @configuration.jpg_images
|
26
|
+
filename = 'archive.gif'
|
27
|
+
end
|
28
|
+
|
29
|
+
if lolimages.empty?
|
30
|
+
warn 'No lolcommits have been captured for this time yet.'
|
31
|
+
exit 1
|
32
|
+
end
|
33
|
+
|
34
|
+
puts '*** Generating animated gif.'
|
35
|
+
|
36
|
+
gif = MiniMagick::Image.new File.join @configuration.archivedir, filename
|
37
|
+
|
38
|
+
# This is for ruby 1.8.7, *lolimages just doesn't work with ruby 187
|
39
|
+
gif.run_command('convert', *['-delay', '50', '-loop', '0', lolimages, "#{gif.path}"].flatten)
|
40
|
+
|
41
|
+
puts "*** #{gif.path} generated."
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
|
+
|
2
3
|
module Lolcommits
|
3
4
|
class Configuration
|
4
5
|
LOLCOMMITS_BASE = ENV['LOLCOMMITS_DIR'] || File.join(ENV['HOME'], '.lolcommits')
|
@@ -7,20 +8,17 @@ module Lolcommits
|
|
7
8
|
|
8
9
|
def initialize(attributes = {})
|
9
10
|
attributes.each do |attr, val|
|
10
|
-
|
11
|
+
send("#{attr}=", val)
|
11
12
|
end
|
12
13
|
end
|
13
14
|
|
14
15
|
def read_configuration
|
15
|
-
|
16
|
-
|
17
|
-
else
|
18
|
-
nil
|
19
|
-
end
|
16
|
+
return unless File.exist?(configuration_file)
|
17
|
+
YAML.load(File.open(configuration_file))
|
20
18
|
end
|
21
19
|
|
22
20
|
def configuration_file
|
23
|
-
"#{
|
21
|
+
"#{loldir}/config.yml"
|
24
22
|
end
|
25
23
|
|
26
24
|
def loldir
|
@@ -32,51 +30,40 @@ module Lolcommits
|
|
32
30
|
|
33
31
|
def archivedir
|
34
32
|
dir = File.join(loldir, 'archive')
|
35
|
-
|
36
|
-
FileUtils.mkdir_p dir
|
37
|
-
end
|
33
|
+
FileUtils.mkdir_p dir unless File.directory? dir
|
38
34
|
dir
|
39
35
|
end
|
40
36
|
|
41
37
|
def most_recent
|
42
|
-
Dir.glob(File.join
|
38
|
+
Dir.glob(File.join loldir, '*.{jpg,gif}').max_by { |f| File.mtime(f) }
|
43
39
|
end
|
44
40
|
|
45
41
|
def jpg_images
|
46
|
-
Dir.glob(File.join
|
42
|
+
Dir.glob(File.join loldir, '*.jpg').sort_by { |f| File.mtime(f) }
|
47
43
|
end
|
48
44
|
|
49
45
|
def jpg_images_today
|
50
|
-
jpg_images.select { |f| Date.parse(File.mtime(f).to_s)
|
46
|
+
jpg_images.select { |f| Date.parse(File.mtime(f).to_s) == Date.today }
|
51
47
|
end
|
52
48
|
|
53
49
|
def raw_image(image_file_type = 'jpg')
|
54
|
-
File.join
|
50
|
+
File.join loldir, "tmp_snapshot.#{image_file_type}"
|
55
51
|
end
|
56
52
|
|
57
53
|
def main_image(commit_sha, image_file_type = 'jpg')
|
58
|
-
File.join
|
54
|
+
File.join loldir, "#{commit_sha}.#{image_file_type}"
|
59
55
|
end
|
60
56
|
|
61
57
|
def video_loc
|
62
|
-
File.join(
|
58
|
+
File.join(loldir, 'tmp_video.mov')
|
63
59
|
end
|
64
60
|
|
65
61
|
def frames_loc
|
66
|
-
File.join(
|
67
|
-
end
|
68
|
-
|
69
|
-
def puts_devices
|
70
|
-
# TODO: handle other platforms here (linux/windows)
|
71
|
-
if self.class.platform_mac?
|
72
|
-
capturer = Lolcommits::CaptureMacAnimated.new
|
73
|
-
puts `#{capturer.executable_path} -l`
|
74
|
-
puts "Specify a device with --device=\"{device name}\" or set the LOLCOMMITS_DEVICE env variable"
|
75
|
-
end
|
62
|
+
File.join(loldir, 'tmp_frames')
|
76
63
|
end
|
77
64
|
|
78
65
|
def puts_plugins
|
79
|
-
puts "Available plugins: #{Lolcommits::
|
66
|
+
puts "Available plugins: #{Lolcommits::Runner.plugins.map(&:name).join(', ')}"
|
80
67
|
end
|
81
68
|
|
82
69
|
def ask_for_plugin_name
|
@@ -86,10 +73,8 @@ module Lolcommits
|
|
86
73
|
end
|
87
74
|
|
88
75
|
def find_plugin(plugin_name)
|
89
|
-
Lolcommits::
|
90
|
-
if plugin.name == plugin_name
|
91
|
-
return plugin.new(nil)
|
92
|
-
end
|
76
|
+
Lolcommits::Runner.plugins.each do |plugin|
|
77
|
+
return plugin.new(nil) if plugin.name == plugin_name
|
93
78
|
end
|
94
79
|
|
95
80
|
puts "Unable to find plugin: '#{plugin_name}'"
|
@@ -97,30 +82,27 @@ module Lolcommits
|
|
97
82
|
end
|
98
83
|
|
99
84
|
def do_configure!(plugin_name)
|
100
|
-
if plugin_name.to_s.strip.empty?
|
101
|
-
plugin_name = ask_for_plugin_name
|
102
|
-
end
|
85
|
+
plugin_name = ask_for_plugin_name if plugin_name.to_s.strip.empty?
|
103
86
|
|
104
87
|
plugin = find_plugin(plugin_name)
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
end
|
88
|
+
return unless plugin
|
89
|
+
config = read_configuration || {}
|
90
|
+
plugin_config = plugin.configure_options!
|
91
|
+
# having a plugin_config, means configuring went OK
|
92
|
+
if plugin_config
|
93
|
+
# save plugin and print config
|
94
|
+
config[plugin_name] = plugin_config
|
95
|
+
save(config)
|
96
|
+
puts self
|
97
|
+
puts "\nSuccessfully configured plugin: #{plugin_name}"
|
98
|
+
else
|
99
|
+
puts "\nAborted plugin configuration for: #{plugin_name}"
|
118
100
|
end
|
119
101
|
end
|
120
102
|
|
121
103
|
def save(config)
|
122
104
|
config_file_contents = config.to_yaml
|
123
|
-
File.open(
|
105
|
+
File.open(configuration_file, 'w') do |f|
|
124
106
|
f.write(config_file_contents)
|
125
107
|
end
|
126
108
|
end
|
@@ -131,24 +113,6 @@ module Lolcommits
|
|
131
113
|
|
132
114
|
# class methods
|
133
115
|
|
134
|
-
def self.platform
|
135
|
-
if platform_fakeplatform?
|
136
|
-
ENV['LOLCOMMITS_FAKEPLATFORM']
|
137
|
-
elsif platform_fakecapture?
|
138
|
-
'Fake'
|
139
|
-
elsif platform_mac?
|
140
|
-
'Mac'
|
141
|
-
elsif platform_linux?
|
142
|
-
'Linux'
|
143
|
-
elsif platform_windows?
|
144
|
-
'Windows'
|
145
|
-
elsif platform_cygwin?
|
146
|
-
'Cygwin'
|
147
|
-
else
|
148
|
-
fail 'Unknown / Unsupported Platform.'
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
116
|
def self.loldir_for(basename)
|
153
117
|
loldir = File.join(LOLCOMMITS_BASE, basename)
|
154
118
|
|
@@ -167,72 +131,5 @@ module Lolcommits
|
|
167
131
|
end
|
168
132
|
loldir
|
169
133
|
end
|
170
|
-
|
171
|
-
def self.platform_mac?
|
172
|
-
RUBY_PLATFORM.to_s.downcase.include?('darwin')
|
173
|
-
end
|
174
|
-
|
175
|
-
def self.platform_linux?
|
176
|
-
RUBY_PLATFORM.to_s.downcase.include?('linux')
|
177
|
-
end
|
178
|
-
|
179
|
-
def self.platform_windows?
|
180
|
-
!!RUBY_PLATFORM.match(/(win|w)32/)
|
181
|
-
end
|
182
|
-
|
183
|
-
def self.platform_cygwin?
|
184
|
-
RUBY_PLATFORM.to_s.downcase.include?('cygwin')
|
185
|
-
end
|
186
|
-
|
187
|
-
def self.platform_fakecapture?
|
188
|
-
(ENV['LOLCOMMITS_FAKECAPTURE'] == '1' || false)
|
189
|
-
end
|
190
|
-
|
191
|
-
def self.platform_fakeplatform?
|
192
|
-
ENV['LOLCOMMITS_FAKEPLATFORM']
|
193
|
-
end
|
194
|
-
|
195
|
-
def self.valid_imagemagick_installed?
|
196
|
-
return false unless self.command_which('identify')
|
197
|
-
return false unless self.command_which('mogrify')
|
198
|
-
# you'd expect the below to work on its own, but it only handles old versions
|
199
|
-
# and will throw an exception if IM is not installed in PATH
|
200
|
-
MiniMagick.valid_version_installed?
|
201
|
-
rescue
|
202
|
-
puts "FATAL: ImageMagick >= #{MiniMagick.minimum_image_magick_version} required (http://imagemagick.org)"
|
203
|
-
puts 'Please check the following command works and returns a valid version number'
|
204
|
-
puts '=> mogrify --version'
|
205
|
-
exit 1
|
206
|
-
end
|
207
|
-
|
208
|
-
def self.valid_ffmpeg_installed?
|
209
|
-
self.command_which('ffmpeg')
|
210
|
-
end
|
211
|
-
|
212
|
-
def self.git_config_color_always?
|
213
|
-
`git config color.ui`.chomp =~ /always/
|
214
|
-
end
|
215
|
-
|
216
|
-
def self.can_animate?
|
217
|
-
['Mac', 'Linux'].include? platform
|
218
|
-
end
|
219
|
-
|
220
|
-
# Cross-platform way of finding an executable in the $PATH.
|
221
|
-
# idea taken from http://bit.ly/qDaTbY, if only_path is true, only the path
|
222
|
-
# is returned (not the path and command)
|
223
|
-
#
|
224
|
-
# which('ruby') #=> /usr/bin/ruby
|
225
|
-
def self.command_which(cmd, only_path = false)
|
226
|
-
exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
|
227
|
-
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
|
228
|
-
exts.each do |ext|
|
229
|
-
exe = "#{path}/#{cmd}#{ext}"
|
230
|
-
if File.executable? exe
|
231
|
-
return only_path ? path : exe
|
232
|
-
end
|
233
|
-
end
|
234
|
-
end
|
235
|
-
nil
|
236
|
-
end
|
237
134
|
end
|
238
135
|
end
|