summaryrefslogtreecommitdiff
path: root/lib/dependabot/git.rb
blob: 26869ed0018608101b6b410db68534c443824bdf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# frozen_string_literal: true

module Dependabot
  class Git
    attr_reader :repo

    def initialize(path)
      @repo = Rugged::Repository.discover(path)
    end

    def self.for(dependency)
      new(dependency.path.parent)
    end

    def checkout(branch:)
      repo.create_branch(branch, repo.head.name)
      repo.checkout(branch)
    end

    def push(remote: "origin", branch: "HEAD")
      repo.push(remote, ["refs/heads/#{branch}"], credentials: credentials_for(remote))
    rescue StandardError
      Dir.chdir(File.dirname(repo.path)) do
        system("git push #{remote} #{branch}", exception: true)
      end
    end

    def patch
      repo.index.diff.patch
    end

    def commit(message:, all: false)
      repo.status { |path, status| stage(path) if status.include?(:worktree_modified) } if all

      Rugged::Commit.create(repo, {
        message: message,
        parents: repo.empty? ? [] : [repo.head.target].compact,
        tree: repo.index.write_tree(repo),
        update_ref: "HEAD",
        author: { email: "dependabot[bot]@users.noreply.github.com", name: "dependabot[bot]" },
        committer: { email: "dependabot[bot]@users.noreply.github.com", name: "dependabot[bot]" },
      })
    end

    private

    def stage(path)
      repo.index.add(path)
    end

    def credentials_for(remote)
      Dependabot.logger.debug(repo.remotes[remote].url)
      if ssh?(repo.remotes[remote].url)
        Rugged::Credentials::SshKeyFromAgent.new(username: "git")
      else
        Rugged::Credentials::UserPassword.new(username: "x-access-token", password: Dependabot.github.token)
      end
    end

    def ssh?(url)
      url.include?("git@github.com:")
    end
  end
end