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



54
55
56
57
58
# File 'lib/overcommit/git_repo.rb', line 54

def all_files
  `git ls-files`.
    split(/\n/).
    map { |relative_file| File.expand_path(relative_file) }
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
# File 'lib/overcommit/git_repo.rb', line 19

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

  flags = '--cached' if options[:staged]

  `git diff --no-ext-diff -U0 #{flags} -- #{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)


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

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



43
44
45
46
47
48
49
# File 'lib/overcommit/git_repo.rb', line 43

def modified_files(options)
  flags = '--cached' if options[:staged]

  `git diff --name-only -z --diff-filter=ACM --ignore-submodules=all #{flags}`.
    split("\0").
    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.



119
120
121
122
123
124
125
126
127
# File 'lib/overcommit/git_repo.rb', line 119

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.



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/overcommit/git_repo.rb', line 99

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].



87
88
89
90
91
92
93
94
95
# File 'lib/overcommit/git_repo.rb', line 87

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].



70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/overcommit/git_repo.rb', line 70

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