Module: Overcommit::Utils

Defined in:
lib/overcommit/utils.rb

Overview

Utility functions for general use.

Class Method Summary collapse

Class Method Details

.broken_symlink?(file) ⇒ true, false

Returns whether a file is a broken symlink.

Returns:

  • (true, false)


136
137
138
139
140
# File 'lib/overcommit/utils.rb', line 136

def broken_symlink?(file)
  # JRuby's implementation of File.exist? returns true for broken
  # symlinks, so we need use File.size?
  File.symlink?(file) && File.size?(file).nil?
end

.camel_case(str) ⇒ Object

Converts a string containing underscores/hyphens/spaces into CamelCase.



68
69
70
# File 'lib/overcommit/utils.rb', line 68

def camel_case(str)
  str.split(/_|-| /).map { |part| part.sub(/^\w/) { |c| c.upcase } }.join
end

.convert_glob_to_absolute(glob) ⇒ String

Convert a glob pattern to an absolute path glob pattern rooted from the repository root directory.

Parameters:

  • glob (String)

Returns:

  • (String)


147
148
149
# File 'lib/overcommit/utils.rb', line 147

def convert_glob_to_absolute(glob)
  File.join(repo_root, glob)
end

.execute(args) ⇒ Object

Wrap external subshell calls. This is necessary in order to allow Overcommit to call other Ruby executables without requiring that they be specified in Overcommit’s Gemfile–a nasty consequence of using ‘bundle exec overcommit` while developing locally.



108
109
110
111
112
113
114
115
116
117
# File 'lib/overcommit/utils.rb', line 108

def execute(args)
  if args.include?('|')
    raise Overcommit::Exceptions::InvalidCommandArgs,
          'Cannot pipe commands with the `execute` helper'
  end

  with_environment 'RUBYOPT' => nil do
    Subprocess.spawn(args)
  end
end

.git_dir(repo_dir = repo_root) ⇒ String

Returns an absolute path to the .git directory for a repo.

Parameters:

  • repo_dir (String) (defaults to: repo_root)

    root directory of git repo

Returns:

  • (String)


38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/overcommit/utils.rb', line 38

def git_dir(repo_dir = repo_root)
  @git_dir ||=
    begin
      git_dir = File.expand_path('.git', repo_dir)

      # .git could also be a file that contains the location of the git directory
      unless File.directory?(git_dir)
        git_dir = File.read(git_dir)[/^gitdir: (.*)$/, 1]

        # Resolve relative paths
        unless git_dir.start_with?('/')
          git_dir = File.expand_path(git_dir, repo_dir)
        end
      end

      git_dir
    end
end

.in_path?(cmd) ⇒ true, false

Returns whether a command can be found given the current environment path.

Parameters:

  • cmd (String)

Returns:

  • (true, false)

    whether a command can be found given the current environment path.



89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/overcommit/utils.rb', line 89

def in_path?(cmd)
  # ENV['PATH'] doesn't include the repo root, but that is a valid
  # location for executables, so we want to add it to the list of places
  # we are checking for the executable.
  paths = [repo_root] + ENV['PATH'].split(File::PATH_SEPARATOR)
  exts  = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
  paths.each do |path|
    exts.each do |ext|
      exe = File.join(path, "#{cmd}#{ext}")
      return true if File.executable?(exe)
    end
  end
  false
end

.matches_path?(pattern, path) ⇒ Boolean

Return whether a pattern matches the given path.

Parameters:

  • pattern (String)
  • path (String)

Returns:

  • (Boolean)


155
156
157
158
159
160
# File 'lib/overcommit/utils.rb', line 155

def matches_path?(pattern, path)
  File.fnmatch?(pattern, path,
                File::FNM_PATHNAME | # Wildcard doesn't match separator
                File::FNM_DOTMATCH   # Wildcards match dotfiles
  )
end

.repo_rootString

Returns an absolute path to the root of the repository.

We do this ourselves rather than call ‘git rev-parse –show-toplevel` to solve an issue where the .git directory might not actually be valid in tests.

Returns:

  • (String)


19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/overcommit/utils.rb', line 19

def repo_root
  @repo_root ||=
    begin
      git_dir = Pathname.new(File.expand_path('.')).enum_for(:ascend).find do |path|
        File.exist?(File.join(path, '.git'))
      end

      unless git_dir
        raise Overcommit::Exceptions::InvalidGitRepo, 'no .git directory found'
      end

      git_dir.to_s
    end
end

.script_path(script) ⇒ Object



8
9
10
# File 'lib/overcommit/utils.rb', line 8

def script_path(script)
  File.join(OVERCOMMIT_HOME, 'libexec', script)
end

.snake_case(str) ⇒ Object

Shamelessly stolen from: stackoverflow.com/questions/1509915/converting-camel-case-to-underscore-case-in-ruby



59
60
61
62
63
64
65
# File 'lib/overcommit/utils.rb', line 59

def snake_case(str)
  str.gsub(/::/, '/').
      gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
      gsub(/([a-z\d])([A-Z])/, '\1_\2').
      tr('-', '_').
      downcase
end

.supported_hook_type_classesObject

Returns a list of supported hook classes (PreCommit, CommitMsg, etc.)



80
81
82
83
84
# File 'lib/overcommit/utils.rb', line 80

def supported_hook_type_classes
  supported_hook_types.map do |file|
    file.split('-').map(&:capitalize).join
  end
end

.supported_hook_typesObject

Returns a list of supported hook types (pre-commit, commit-msg, etc.)



73
74
75
76
77
# File 'lib/overcommit/utils.rb', line 73

def supported_hook_types
  Dir[File.join(OVERCOMMIT_HOME, 'lib', 'overcommit', 'hook', '*')].
    select { |file| File.directory?(file) }.
    map { |file| File.basename(file, '.rb').gsub('_', '-') }
end

.with_environment(env) ⇒ Object

Calls a block of code with a modified set of environment variables, restoring them once the code has executed.



121
122
123
124
125
126
127
128
129
130
131
# File 'lib/overcommit/utils.rb', line 121

def with_environment(env)
  old_env = {}
  env.each do |var, value|
    old_env[var] = ENV[var.to_s]
    ENV[var.to_s] = value
  end

  yield
ensure
  old_env.each { |var, value| ENV[var.to_s] = value }
end