Module: Overcommit::GitRepo

Defined in:
lib/overcommit/git_repo.rb

Overview

Provide a set of utilities for certain interactions with git.

Constant Summary collapse

DIFF_HUNK_REGEX =

Regular expression used to extract diff ranges from hunks of diff output.

/
  ^@@\s
  [^\s]+\s           # Ignore old file range
  \+(\d+)(?:,(\d+))? # Extract range of hunk containing start line and number of lines
  \s@@.*$
/x

Class Method Summary collapse

Class Method Details

.all_filesArray<String>

Returns the names of all files that are tracked by git.

Returns:

  • (Array<String>)

    list of absolute file paths



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

def all_files
  `git ls-files`.
    split(/\n/).
    map { |relative_file| File.expand_path(relative_file) }.
    reject { |file| File.directory?(file) } # Exclude submodule directories
end

.extract_modified_lines(file_path, options) ⇒ Set

Extract the set of modified lines from a given file.

Parameters:

  • file_path (String)
  • options (Hash)

Returns:

  • (Set)

    line numbers that have been modified in file



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/overcommit/git_repo.rb', line 19

def extract_modified_lines(file_path, options)
  lines = Set.new

  flags = '--cached' if options[:staged]
  refs = options[:refs]
  subcmd = options[:subcmd] || 'diff'

  `git #{subcmd} --no-ext-diff -U0 #{flags} #{refs} -- '#{file_path}'`.
    scan(DIFF_HUNK_REGEX) do |start_line, lines_added|
    lines_added = (lines_added || 1).to_i # When blank, one line was added
    cur_line = start_line.to_i

    lines_added.times do
      lines.add cur_line
      cur_line += 1
    end
  end

  lines
end

.initial_commit?true, false

Returns whether the current git branch is empty (has no commits).

Returns:

  • (true, false)


69
70
71
# File 'lib/overcommit/git_repo.rb', line 69

def initial_commit?
  !Overcommit::Utils.execute(%w[git rev-parse HEAD]).success?
end

.modified_files(options) ⇒ Array<String>

Returns the names of all files that have been modified from compared to HEAD.

Parameters:

  • options (Hash)

Returns:

  • (Array<String>)

    list of absolute file paths



45
46
47
48
49
50
51
52
53
54
55
# File 'lib/overcommit/git_repo.rb', line 45

def modified_files(options)
  flags = '--cached' if options[:staged]
  refs = options[:refs]
  subcmd = options[:subcmd] || 'diff'

  `git #{subcmd} --name-only -z --diff-filter=ACM --ignore-submodules=all #{flags} #{refs}`.
    split("\0").
    map(&:strip).
    reject(&:empty?).
    map { |relative_file| File.expand_path(relative_file) }
end

.restore_cherry_pick_stateObject

Restore any relevant files that were present when repo was in the middle of a cherry-pick.



126
127
128
129
130
131
132
133
134
# File 'lib/overcommit/git_repo.rb', line 126

def restore_cherry_pick_state
  if @cherry_head
    File.open(File.expand_path('CHERRY_PICK_HEAD',
                               Overcommit::Utils.git_dir), 'w') do |f|
      f.write("#{@cherry_head}\n")
    end
    @cherry_head = nil
  end
end

.restore_merge_stateObject

Restore any relevant files that were present when repo was in the middle of a merge.



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/overcommit/git_repo.rb', line 106

def restore_merge_state
  if @merge_head
    FileUtils.touch(File.expand_path('MERGE_MODE', Overcommit::Utils.git_dir))

    File.open(File.expand_path('MERGE_HEAD', Overcommit::Utils.git_dir), 'w') do |f|
      f.write("#{@merge_head}\n")
    end
    @merge_head = nil
  end

  if @merge_msg
    File.open(File.expand_path('MERGE_MSG', Overcommit::Utils.git_dir), 'w') do |f|
      f.write("#{@merge_msg}\n")
    end
    @merge_msg = nil
  end
end

.store_cherry_pick_stateObject

Store any relevant files that are present when repo is in the middle of a cherry-pick.

Restored via [#restore_cherry_pick_state].



94
95
96
97
98
99
100
101
102
# File 'lib/overcommit/git_repo.rb', line 94

def store_cherry_pick_state
  cherry_head = `git rev-parse CHERRY_PICK_HEAD 2> /dev/null`.chomp

  # Store the merge state if we're in the middle of resolving a merge
  # conflict. This is necessary since stashing removes the merge state.
  if cherry_head != 'CHERRY_PICK_HEAD'
    @cherry_head = cherry_head
  end
end

.store_merge_stateObject

Store any relevant files that are present when repo is in the middle of a merge.

Restored via [#restore_merge_state].



77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/overcommit/git_repo.rb', line 77

def store_merge_state
  merge_head = `git rev-parse MERGE_HEAD 2> /dev/null`.chomp

  # Store the merge state if we're in the middle of resolving a merge
  # conflict. This is necessary since stashing removes the merge state.
  if merge_head != 'MERGE_HEAD'
    @merge_head = merge_head
  end

  merge_msg_file = File.expand_path('MERGE_MSG', Overcommit::Utils.git_dir)
  @merge_msg = File.open(merge_msg_file).read if File.exist?(merge_msg_file)
end