lolcommits 0.5.7 → 0.5.8.pre1

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.
Files changed (42) hide show
  1. checksums.yaml +8 -8
  2. data/.rubocop.yml +1 -0
  3. data/.rubocop_todo.yml +16 -161
  4. data/.travis.yml +11 -4
  5. data/Gemfile +2 -2
  6. data/Rakefile +24 -32
  7. data/bin/lolcommits +62 -125
  8. data/features/bugs.feature +24 -9
  9. data/features/lolcommits.feature +136 -145
  10. data/features/plugins.feature +16 -33
  11. data/features/step_definitions/lolcommits_steps.rb +91 -71
  12. data/features/support/env.rb +18 -48
  13. data/features/support/path_helpers.rb +9 -8
  14. data/lib/lolcommits.rb +3 -10
  15. data/lib/lolcommits/capturer.rb +10 -2
  16. data/lib/lolcommits/capturer/capture_linux.rb +1 -1
  17. data/lib/lolcommits/capturer/capture_linux_animated.rb +12 -13
  18. data/lib/lolcommits/capturer/capture_mac_animated.rb +12 -13
  19. data/lib/lolcommits/cli/fatals.rb +77 -0
  20. data/lib/lolcommits/cli/launcher.rb +29 -0
  21. data/lib/lolcommits/cli/process_runner.rb +48 -0
  22. data/lib/lolcommits/cli/timelapse_gif.rb +45 -0
  23. data/lib/lolcommits/configuration.rb +30 -133
  24. data/lib/lolcommits/git_info.rb +58 -28
  25. data/lib/lolcommits/installation.rb +11 -21
  26. data/lib/lolcommits/platform.rb +134 -0
  27. data/lib/lolcommits/plugin.rb +2 -2
  28. data/lib/lolcommits/plugins/dot_com.rb +15 -15
  29. data/lib/lolcommits/plugins/lol_protonet.rb +68 -0
  30. data/lib/lolcommits/plugins/lol_twitter.rb +12 -15
  31. data/lib/lolcommits/plugins/lol_yammer.rb +4 -6
  32. data/lib/lolcommits/plugins/lolsrv.rb +8 -11
  33. data/lib/lolcommits/plugins/loltext.rb +7 -7
  34. data/lib/lolcommits/plugins/tranzlate.rb +70 -70
  35. data/lib/lolcommits/plugins/uploldz.rb +8 -8
  36. data/lib/lolcommits/runner.rb +36 -35
  37. data/lib/lolcommits/version.rb +1 -1
  38. data/lolcommits.gemspec +11 -10
  39. data/test/lolcommits_test.rb +35 -0
  40. data/test/plugins_test.rb +52 -0
  41. metadata +41 -20
  42. data/test/test_lolcommits.rb +0 -78
@@ -3,50 +3,80 @@ module Lolcommits
3
3
  class GitInfo
4
4
  include Methadone::CLILogging
5
5
  attr_accessor :sha, :message, :repo_internal_path, :repo, :url,
6
- :author_name, :author_email
6
+ :author_name, :author_email, :branch
7
7
 
8
- GIT_URL_REGEX = /.*[:]([\/\w\-]*).git/
8
+ GIT_URL_REGEX = %r{.*[:]([\/\w\-]*).git}
9
9
 
10
10
  def initialize
11
- debug 'GitInfo: attempting to read local repository'
12
- g = Git.open('.')
13
- debug 'GitInfo: reading commits logs'
14
- commit = g.log.first
15
- debug "GitInfo: most recent commit is '#{commit}'"
16
-
17
- self.message = commit.message.split("\n").first
18
- self.sha = commit.sha[0..10]
19
- self.repo_internal_path = g.repo.path
20
-
21
- if g.remote.url
22
- self.url = remote_https_url(g.remote.url)
23
- match = g.remote.url.match(GIT_URL_REGEX)
24
- end
25
-
26
- if match
27
- self.repo = match[1]
28
- elsif !g.repo.path.empty?
29
- self.repo = g.repo.path.split(File::SEPARATOR)[-2]
30
- end
31
-
32
- if commit.author
33
- self.author_name = commit.author.name
34
- self.author_email = commit.author.email
35
- end
36
-
37
11
  debug 'GitInfo: parsed the following values from commit:'
38
12
  debug "GitInfo: \t#{message}"
39
13
  debug "GitInfo: \t#{sha}"
40
14
  debug "GitInfo: \t#{repo_internal_path}"
41
15
  debug "GitInfo: \t#{repo}"
16
+ debug "GitInfo: \t#{branch}"
42
17
  debug "GitInfo: \t#{author_name}" if author_name
43
18
  debug "GitInfo: \t#{author_email}" if author_email
44
19
  end
45
20
 
21
+ def branch
22
+ @branch ||= repository.current_branch
23
+ end
24
+
25
+ def message
26
+ @message ||= begin
27
+ message = last_commit.message || ''
28
+ message.split("\n").first
29
+ end
30
+ end
31
+
32
+ def sha
33
+ @sha ||= last_commit.sha[0..10]
34
+ end
35
+
36
+ def repo_internal_path
37
+ @repo_internal_path ||= repository.repo.path
38
+ end
39
+
40
+ def url
41
+ @url ||= begin
42
+ remote_https_url(repository.remote.url) if repository.remote
43
+ end
44
+ end
45
+
46
+ def repo
47
+ @repo ||= begin
48
+ if repository.remote && repository.remote.url
49
+ match = repository.remote.url.match(GIT_URL_REGEX)
50
+ end
51
+
52
+ if match
53
+ match[1]
54
+ elsif !repository.repo.path.empty?
55
+ repository.repo.path.split(File::SEPARATOR)[-2]
56
+ end
57
+ end
58
+ end
59
+
60
+ def author_name
61
+ @author_name ||= last_commit.author.name if last_commit.author
62
+ end
63
+
64
+ def author_email
65
+ @author_email ||= last_commit.author.email if last_commit.author
66
+ end
67
+
46
68
  private
47
69
 
48
70
  def remote_https_url(url)
49
71
  url.gsub(':', '/').gsub(/^git@/, 'https://').gsub(/\.git$/, '') + '/commit/'
50
72
  end
73
+
74
+ def repository(path = '.')
75
+ @repository ||= Git.open(path)
76
+ end
77
+
78
+ def last_commit
79
+ @commit ||= repository.log.first
80
+ end
51
81
  end
52
82
  end
@@ -11,15 +11,13 @@ module Lolcommits
11
11
  # IF --ENABLE, DO ENABLE
12
12
  #
13
13
  def self.do_enable
14
- if not File.directory?('.git')
14
+ unless File.directory?('.git')
15
15
  fatal "You don't appear to be in the base directory of a git project."
16
16
  exit 1
17
17
  end
18
18
 
19
19
  # its possible a hooks dir doesnt exist, so create it if so
20
- if not File.directory?(HOOK_DIR)
21
- Dir.mkdir(HOOK_DIR)
22
- end
20
+ Dir.mkdir(HOOK_DIR) unless File.directory?(HOOK_DIR)
23
21
 
24
22
  # should add a shebang (or not) adding will rewrite hook file
25
23
  add_shebang = false
@@ -40,9 +38,7 @@ module Lolcommits
40
38
  end
41
39
 
42
40
  File.open(HOOK_PATH, add_shebang ? 'w' : 'a') do |f|
43
- if add_shebang
44
- f.write("#!/bin/sh\n")
45
- end
41
+ f.write("#!/bin/sh\n") if add_shebang
46
42
  f.write(hook_script)
47
43
  end
48
44
 
@@ -62,7 +58,7 @@ module Lolcommits
62
58
  if lolcommits_hook_exists?
63
59
  remove_existing_hook!
64
60
  info "uninstalled lolcommits hook (from #{HOOK_PATH})"
65
- elsif File.exists?(HOOK_PATH)
61
+ elsif File.exist?(HOOK_PATH)
66
62
  info "couldn't find an lolcommits hook (at #{HOOK_PATH})"
67
63
  if File.read(HOOK_PATH) =~ /lolcommit/
68
64
  info "warning: an older-style lolcommit hook may still exist, edit #{HOOK_PATH} to remove it manually"
@@ -72,11 +68,9 @@ module Lolcommits
72
68
  end
73
69
  end
74
70
 
75
- protected
76
-
77
- def self.hook_script(add_shebang = true)
78
- ruby_path = Lolcommits::Configuration.command_which('ruby', true)
79
- imagick_path = Lolcommits::Configuration.command_which('identify', true)
71
+ def self.hook_script(_add_shebang = true)
72
+ ruby_path = Lolcommits::Platform.command_which('ruby', true)
73
+ imagick_path = Lolcommits::Platform.command_which('identify', true)
80
74
  locale_export = "export LANG=\"#{ENV['LANG']}\"\n"
81
75
  hook_export = "export PATH=\"#{ruby_path}:#{imagick_path}:$PATH\"\n"
82
76
  capture_cmd = 'lolcommits --capture'
@@ -91,7 +85,7 @@ EOS
91
85
 
92
86
  # does a git hook exist at all?
93
87
  def self.hook_file_exists?
94
- File.exists?(HOOK_PATH)
88
+ File.exist?(HOOK_PATH)
95
89
  end
96
90
 
97
91
  # does a git hook exist with lolcommits commands?
@@ -102,7 +96,7 @@ EOS
102
96
 
103
97
  # does the git hook file have a good shebang?
104
98
  def self.good_shebang?
105
- File.read(HOOK_PATH).lines.first =~ /^\#\!\/bin\/.*sh/
99
+ File.read(HOOK_PATH).lines.first =~ %r{^\#\!\/bin\/.*sh}
106
100
  end
107
101
 
108
102
  def self.remove_existing_hook!
@@ -111,15 +105,11 @@ EOS
111
105
  skip = false
112
106
 
113
107
  hook.lines.each do |line|
114
- if !skip && (line =~ /lolcommits.*\(begin\)/)
115
- skip = true
116
- end
108
+ skip = true if !skip && (line =~ /lolcommits.*\(begin\)/)
117
109
 
118
110
  out << line unless skip
119
111
 
120
- if skip && (line =~ /lolcommits.*\(end\)/)
121
- skip = false
122
- end
112
+ skip = false if skip && (line =~ /lolcommits.*\(end\)/)
123
113
  end
124
114
 
125
115
  out.close
@@ -0,0 +1,134 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'mini_magick'
3
+
4
+ module Lolcommits
5
+ class Platform
6
+ # A convenience name for the platform. Mainly used for metaprogramming.
7
+ # @return String
8
+ def self.platform
9
+ if platform_fakeplatform? then ENV['LOLCOMMITS_FAKEPLATFORM']
10
+ elsif platform_fakecapture? then 'Fake'
11
+ elsif platform_mac? then 'Mac'
12
+ elsif platform_linux? then 'Linux'
13
+ elsif platform_windows? then 'Windows'
14
+ elsif platform_cygwin? then 'Cygwin'
15
+ else
16
+ fail 'Unknown / Unsupported Platform.'
17
+ end
18
+ end
19
+
20
+ # Are we on a Mac platform?
21
+ # @return Boolean
22
+ def self.platform_mac?
23
+ RUBY_PLATFORM.to_s.downcase.include?('darwin')
24
+ end
25
+
26
+ # Are we on a Linux platform?
27
+ # @return Boolean
28
+ def self.platform_linux?
29
+ RUBY_PLATFORM.to_s.downcase.include?('linux')
30
+ end
31
+
32
+ # Are we on a Windows platform?
33
+ # @return Boolean
34
+ def self.platform_windows?
35
+ !RUBY_PLATFORM.match(/(win|w)32/)
36
+ end
37
+
38
+ # Are we on a Cygwin platform?
39
+ # @return Boolean
40
+ def self.platform_cygwin?
41
+ RUBY_PLATFORM.to_s.downcase.include?('cygwin')
42
+ end
43
+
44
+ # Are we currently faking webcam capture for test purposes?
45
+ # @return Boolean
46
+ def self.platform_fakecapture?
47
+ (ENV['LOLCOMMITS_FAKECAPTURE'] == '1' || false)
48
+ end
49
+
50
+ # Are we currently overriding and faking the platform entirely?
51
+ # @todo possibly make this a private method?
52
+ # @return Boolean
53
+ def self.platform_fakeplatform?
54
+ ENV['LOLCOMMITS_FAKEPLATFORM']
55
+ end
56
+
57
+ # Is the platform capable of capturing animated GIFs from webcam?
58
+ # @return Boolean
59
+ def self.can_animate?
60
+ # FIXME: this is currently matching against string instead of
61
+ # simply returning platform_mac? || platform_linux?
62
+ # This is not ideal... but otherwise overriding platform via
63
+ # LOLCOMMITS_FAKEPLATFORM when running cucumber tests won't work.
64
+ # We should come up with a better solution.
65
+ %w(Mac Linux).include? platform
66
+ end
67
+
68
+ # Is a valid install of imagemagick present on the system?
69
+ # @return Boolean
70
+ def self.valid_imagemagick_installed?
71
+ return false unless command_which('identify')
72
+ return false unless command_which('mogrify')
73
+ # you'd expect the below to work on its own, but it only handles old versions
74
+ # and will throw an exception if IM is not installed in PATH
75
+ MiniMagick.valid_version_installed?
76
+ rescue
77
+ return false
78
+ end
79
+
80
+ # Is a valid install of ffmpeg present on the system?
81
+ #
82
+ # @note For now, this just checks for presence, any version should work.
83
+ # @return Boolean
84
+ def self.valid_ffmpeg_installed?
85
+ command_which('ffmpeg')
86
+ end
87
+
88
+ # Cross-platform way of finding an executable in the $PATH.
89
+ #
90
+ # Idea taken from http://bit.ly/qDaTbY, if only_path is true, only the path
91
+ # is returned (not the path and command)
92
+ #
93
+ # @example
94
+ # command_which('ruby') #=> /usr/bin/ruby
95
+ #
96
+ # @return Boolean
97
+ def self.command_which(cmd, only_path = false)
98
+ exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
99
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
100
+ exts.each do |ext|
101
+ exe = "#{path}/#{cmd}#{ext}"
102
+ return only_path ? path : exe if File.executable? exe
103
+ end
104
+ end
105
+ nil
106
+ end
107
+
108
+ # Is `git config color.ui` set to 'always'?
109
+ #
110
+ # Due to a bug in the ruby-git library, git config for color.ui cannot be
111
+ # set to 'always' or it won't read properly.
112
+ #
113
+ # This helper method let's us check for that error condition so we can
114
+ # alert the user in the CLI tool.
115
+ #
116
+ # @return Boolean
117
+ def self.git_config_color_always?
118
+ `git config color.ui`.chomp =~ /always/
119
+ end
120
+
121
+ # Returns a list of system camera devices in a format suitable to display
122
+ # to the user.
123
+ #
124
+ # @note Currently only functions on Mac.
125
+ # @return String
126
+ def self.device_list
127
+ # TODO: handle other platforms here (linux/windows)
128
+ if Platform.platform_mac?
129
+ capturer = Lolcommits::CaptureMacAnimated.new
130
+ `#{capturer.executable_path} -l`
131
+ end
132
+ end
133
+ end
134
+ end
@@ -46,7 +46,7 @@ module Lolcommits
46
46
  # ask for plugin options
47
47
  def configure_options!
48
48
  puts "Configuring plugin: #{self.class.name}\n"
49
- options.reduce(Hash.new) do |acc, option|
49
+ options.reduce({}) do |acc, option|
50
50
  print "#{option}: "
51
51
  val = parse_user_input(STDIN.gets.strip)
52
52
  # check enabled option isn't a String
@@ -103,7 +103,7 @@ module Lolcommits
103
103
 
104
104
  # uniform debug logging for plugins
105
105
  def debug(msg)
106
- super("Plugin: #{self.class.to_s}: " + msg)
106
+ super("Plugin: #{self.class}: " + msg)
107
107
  end
108
108
 
109
109
  # identifying plugin name (for config, listing)
@@ -7,27 +7,27 @@ module Lolcommits
7
7
 
8
8
  def initialize(runner)
9
9
  super
10
- self.options.concat(['api_key', 'api_secret', 'repo_id'])
10
+ options.concat(%w(api_key api_secret repo_id))
11
11
  end
12
12
 
13
13
  def run_postcapture
14
14
  return unless valid_configuration?
15
15
 
16
16
  t = Time.now.to_i.to_s
17
- resp = HTTMultiParty.post("#{BASE_URL}/git_commits.json",
18
- :body => {
19
- :git_commit => {
20
- :sha => self.runner.sha,
21
- :repo_external_id => configuration['repo_id'],
22
- :image => File.open(self.runner.main_image),
23
- :raw => File.open(self.runner.snapshot_loc)
24
- },
25
-
26
- :key => configuration['api_key'],
27
- :t => t,
28
- :token => Digest::SHA1.hexdigest(configuration['api_secret'] + t)
29
- }
30
- )
17
+ HTTMultiParty.post(
18
+ "#{BASE_URL}/git_commits.json",
19
+ :body => {
20
+ :git_commit => {
21
+ :sha => runner.sha,
22
+ :repo_external_id => configuration['repo_id'],
23
+ :image => File.open(runner.main_image),
24
+ :raw => File.open(runner.snapshot_loc)
25
+ },
26
+
27
+ :key => configuration['api_key'],
28
+ :t => t,
29
+ :token => Digest::SHA1.hexdigest(configuration['api_secret'] + t)
30
+ })
31
31
  rescue => e
32
32
  log_error(e, "ERROR: HTTMultiParty POST FAILED #{e.class} - #{e.message}")
33
33
  end
@@ -0,0 +1,68 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'rest_client'
3
+
4
+ module Lolcommits
5
+ class LolProtonet < Plugin
6
+ def initialize(runner)
7
+ super
8
+ options.concat(%w(api_token api_endpoint))
9
+ end
10
+
11
+ def run_postcapture
12
+ return unless valid_configuration?
13
+
14
+ debug "Posting capture to #{configuration['endpoint']}"
15
+ RestClient.post(
16
+ api_url,
17
+ {
18
+ :files => [File.new(runner.main_image)],
19
+ :message => message
20
+ },
21
+ 'X-Protonet-Token' => configuration['api_token']
22
+ )
23
+ end
24
+
25
+ def api_url
26
+ configuration['api_endpoint']
27
+ end
28
+
29
+ def message
30
+ "commited some #{random_adjective} #{random_object} to #{runner.git_info.repo}@#{runner.sha} (#{runner.git_info.branch}) "
31
+ end
32
+
33
+ def random_object
34
+ objects = %w(screws bolts exceptions errors cookies)
35
+
36
+ objects.sample
37
+ end
38
+
39
+ def random_adjective
40
+ adjectives = ['awesome', 'great', 'interesting', 'cool', 'EPIC', 'gut', 'good', 'pansy',
41
+ 'powerful', 'boring', 'quirky', 'untested', 'german', 'iranian', 'neutral', 'crazy', 'well tested',
42
+ 'jimmy style', 'nasty', 'bibliographical (we received complaints about the original wording)',
43
+ 'bombdiggidy', 'narly', 'spiffy', 'smashing', 'xing style',
44
+ 'leo apotheker style', 'black', 'white', 'yellow', 'shaggy', 'tasty', 'mind bending', 'JAY-Z',
45
+ 'Kanye (the best ever)', '* Toby Keith was here *', 'splendid', 'stupendulous',
46
+ '(freedom fries!)', '[vote RON PAUL]', '- these are not my glasses -', 'typical pansy',
47
+ '- ze goggles zey do nothing! -', 'almost working', 'legen- wait for it -', '-dairy!',
48
+ ' - Tavonius would be proud of this - ', 'Meg FAILMAN!', '- very brofessional of you -',
49
+ 'heartbleeding', 'juciy', 'supercalifragilisticexpialidocious', 'failing', 'loving'
50
+ ]
51
+ adjectives.sample
52
+ end
53
+
54
+ def configured?
55
+ !configuration['enabled'].nil? &&
56
+ configuration['api_token'] &&
57
+ configuration['api_endpoint']
58
+ end
59
+
60
+ def self.name
61
+ 'lolprotonet'
62
+ end
63
+
64
+ def self.runner_order
65
+ :postcapture
66
+ end
67
+ end
68
+ end