Class: Gemstar::GitRepo

Inherits:
Object
  • Object
show all
Defined in:
lib/gemstar/git_repo.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(specified_directory) ⇒ GitRepo

Returns a new instance of GitRepo.



8
9
10
11
12
13
14
15
16
# File 'lib/gemstar/git_repo.rb', line 8

def initialize(specified_directory)
  @specified_directory = specified_directory || Dir.pwd
  search_directory = if File.directory?(@specified_directory)
    @specified_directory
  else
    File.dirname(@specified_directory)
  end
  @tree_root_directory = find_git_root(search_directory)
end

Instance Attribute Details

#tree_root_directoryObject (readonly)

Returns the value of attribute tree_root_directory.



6
7
8
# File 'lib/gemstar/git_repo.rb', line 6

def tree_root_directory
  @tree_root_directory
end

Instance Method Details

#build_git_command(command, in_directory: @specified_directory) ⇒ Object



26
27
28
29
30
# File 'lib/gemstar/git_repo.rb', line 26

def build_git_command(command, in_directory: @specified_directory)
  git_command = [git_client]
  git_command += ["-C", in_directory] if in_directory
  git_command + command
end

#commit_before(time_expression, default_branch: "HEAD") ⇒ Object



66
67
68
69
70
71
# File 'lib/gemstar/git_repo.rb', line 66

def commit_before(time_expression, default_branch: "HEAD")
  sha = run_git_command(["rev-list", "-1", "--before", time_expression, default_branch])
  raise "No commit before #{time_expression} on #{default_branch}" if sha.empty?

  sha
end

#commit_info(revision) ⇒ Object



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

def commit_info(revision)
  return nil if tree_root_directory.nil? || tree_root_directory.empty?

  format = "%H%x1f%h%x1f%aI%x1f%s"
  output = try_git_command(["show", "-s", "--pretty=format:#{format}", revision], in_directory: tree_root_directory)
  return nil if output.nil? || output.empty?

  parse_commit_log_line(output)
end

#commits_between(from_revision, to_revision = "HEAD") ⇒ Object



109
110
111
112
113
114
115
116
117
118
# File 'lib/gemstar/git_repo.rb', line 109

def commits_between(from_revision, to_revision = "HEAD")
  return [] if tree_root_directory.nil? || tree_root_directory.empty?

  range = "#{from_revision}..#{to_revision || "HEAD"}"
  format = "%H%x1f%h%x1f%aI%x1f%s"
  output = try_git_command(["log", "--reverse", "--pretty=format:#{format}", range], in_directory: tree_root_directory)
  return [] if output.nil? || output.empty?

  output.lines.filter_map { |line| parse_commit_log_line(line) }
end

#find_git_root(directory) ⇒ Object



18
19
20
# File 'lib/gemstar/git_repo.rb', line 18

def find_git_root(directory)
  try_git_command(%W[rev-parse --show-toplevel], in_directory: directory)
end

#get_full_path(path) ⇒ Object



78
79
80
# File 'lib/gemstar/git_repo.rb', line 78

def get_full_path(path)
  run_git_command(["ls-files", "--full-name", "--", path])
end

#git_clientObject



22
23
24
# File 'lib/gemstar/git_repo.rb', line 22

def git_client
  "git"
end

#log_for_paths(paths, limit: 20, reverse: false) ⇒ Object



97
98
99
100
101
102
103
104
105
106
107
# File 'lib/gemstar/git_repo.rb', line 97

def log_for_paths(paths, limit: 20, reverse: false)
  return "" if tree_root_directory.nil? || tree_root_directory.empty? || paths.empty?

  format = "%H%x1f%h%x1f%aI%x1f%s"
  command = ["log"]
  command += ["-n", limit.to_s] if limit
  command << "--reverse" if reverse
  command += ["--pretty=format:#{format}", "--", *paths]

  run_git_command(command, in_directory: tree_root_directory)
end

#origin_repo_urlObject



90
91
92
93
94
95
# File 'lib/gemstar/git_repo.rb', line 90

def origin_repo_url
  remote = try_git_command(["remote", "get-url", "origin"])
  return nil if remote.nil? || remote.empty?

  normalize_remote_url(remote)
end

#relative_path(path) ⇒ Object



82
83
84
85
86
87
88
# File 'lib/gemstar/git_repo.rb', line 82

def relative_path(path)
  return nil if tree_root_directory.nil? || tree_root_directory.empty?

  Pathname.new(File.expand_path(path)).relative_path_from(Pathname.new(tree_root_directory)).to_s
rescue ArgumentError
  nil
end

#resolve_commit(revish, default_branch: "HEAD") ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/gemstar/git_repo.rb', line 53

def resolve_commit(revish, default_branch: "HEAD")
  # If it looks like a pure date (or you want to support "date only"),
  # map it to "latest commit before date on default_branch".
  if revish =~ /\d{4}-\d{2}-\d{2}/ || revish =~ /\d{1,2}:\d{2}/i
    return commit_before(revish, default_branch:)
  end

  # Otherwise let Git parse whatever the user typed.
  sha = run_git_command(%W[rev-parse --verify #{revish}^{commit}])
  raise "Unknown revision: #{revish}" if sha.empty?
  sha
end

#run_git_command(command, in_directory: @specified_directory, strip: true) ⇒ Object



32
33
34
35
36
37
38
39
40
# File 'lib/gemstar/git_repo.rb', line 32

def run_git_command(command, in_directory: @specified_directory, strip: true)
  git_command = build_git_command(command, in_directory:)

  puts %[run_git_command (joined): #{git_command.join(" ")}] if Gemstar.debug?

  output = IO.popen(git_command, err: [:child, :out],
    &:read)
  strip ? output.strip : output
end

#show_blob_at(revish, path) ⇒ Object



73
74
75
76
# File 'lib/gemstar/git_repo.rb', line 73

def show_blob_at(revish, path)
  commit = resolve_commit(revish)
  run_git_command(["show", "#{commit}:#{path}"])
end

#try_git_command(command, in_directory: @specified_directory, strip: true) ⇒ Object



42
43
44
45
46
47
48
49
50
51
# File 'lib/gemstar/git_repo.rb', line 42

def try_git_command(command, in_directory: @specified_directory, strip: true)
  git_command = build_git_command(command, in_directory:)

  puts %[try_git_command (joined): #{git_command.join(" ")}] if Gemstar.debug?

  output, status = Open3.capture2e(*git_command)
  return nil unless status.success?

  strip ? output.strip : output
end