Module: PryGithub::GithubHelpers

Defined in:
lib/pry-github.rb

Instance Method Summary collapse

Instance Method Details

#find_git_root(dir) ⇒ Object

Raises:

  • (Pry::CommandError)


41
42
43
44
45
46
47
48
49
50
# File 'lib/pry-github.rb', line 41

def find_git_root(dir)
  git_root = nil
  Dir.chdir dir do
    git_root, _ = Open3.capture2e("git rev-parse --show-toplevel")
    git_root = git_root.chomp
  end

  raise Pry::CommandError, "No git repository found in #{dir}" if git_root =~ /fatal:/
  git_root
end

#find_github_remote(repo) ⇒ Object

Raises:

  • (Pry::CommandError)


52
53
54
55
56
57
58
# File 'lib/pry-github.rb', line 52

def find_github_remote(repo)
  remote_urls = repo.remotes.map { |remote| repo.config["remote.#{remote.name.split('/')[0]}.url"] }
  gh_url = remote_urls.find { |url| url =~ /github\.com/ }

  raise Pry::CommandError, "No GitHub remote found!" unless gh_url
  gh_url
end

#get_file_from_commit(path) ⇒ Object



13
14
15
16
17
18
19
20
21
22
23
# File 'lib/pry-github.rb', line 13

def get_file_from_commit(path)
  git_root = find_git_root(File.dirname(path))
  repo = Grit::Repo.new(git_root)
  head = repo.commits.first
  tree_names = relative_path(git_root, path).split("/")
  start_tree = head.tree
  blob_name = tree_names.last
  tree = tree_names[0..-2].inject(start_tree)  { |a, v|  a.trees.find { |t| t.basename == v } }
  blob = tree.blobs.find { |v| v.basename == blob_name }
  blob.data
end

#get_github_url(meth, url_type = "blob") ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/pry-github.rb', line 60

def get_github_url(meth, url_type="blob")
  file_name = meth.source_location.first
  code, start_line = method_code_from_head(meth)

  git_root = find_git_root(File.dirname(file_name))

  repo = Grit::Repo.new(git_root)
  gh_url = find_github_remote(repo)

  # ssh urls can't be parsed with URI.parse
  if gh_url[0..3] == "git@"
    gh_url = gh_url.gsub(":", "/")
    gh_url[0..3] = "https://"
  end

  uri = URI.parse(gh_url)
  https_url = "https://#{uri.host}#{uri.path}".gsub(".git", "")
  https_url += "/#{url_type}/#{repo.commit("HEAD").sha}"
  https_url += file_name.gsub(repo.working_dir, '')
  https_url += "#L#{start_line}-L#{start_line + code.lines.to_a.size}"

  uri = URI.parse(https_url)
  response = nil
  Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
    response = http.head(uri.path)
  end

  if response.code == "404"
    https_url = https_url.gsub(repo.commit("HEAD").sha, repo.head.name)
  end

  https_url
end

#method_code_from_head(meth) ⇒ Object

Raises:

  • (Pry::CommandError)


25
26
27
28
29
30
31
32
33
34
# File 'lib/pry-github.rb', line 25

def method_code_from_head(meth)
  code = get_file_from_commit(meth.source_location.first)
  search_line = meth.source.lines.first.strip
  _, start_line = code.lines.to_a.each_with_index.find { |v, i| v.strip == search_line }

  raise Pry::CommandError, "Can't find #{args[0]} in the repo. Perhaps it hasn't been committed yet." unless start_line

  start_line
  [Pry.new(:input => StringIO.new(code.lines.to_a[start_line..-1].join)).r(target), start_line + 1]
end

#relative_path(root, path) ⇒ Object



36
37
38
39
# File 'lib/pry-github.rb', line 36

def relative_path(root, path)
  path =~ /#{root}\/(.*)/
  $1
end