BigW Consortium Gitlab

commits.rb 4.24 KB
Newer Older
1 2 3
require 'mime/types'

module API
4
  # Projects commits API
5 6 7 8 9 10 11 12 13 14
  class Commits < Grape::API
    before { authenticate! }
    before { authorize! :download_code, user_project }

    resource :projects do
      # Get a project repository commits
      #
      # Parameters:
      #   id (required) - The ID of a project
      #   ref_name (optional) - The name of a repository branch or tag, if not given the default branch is used
15 16
      #   since (optional) - Only commits after or in this date will be returned
      #   until (optional) - Only commits before or in this date will be returned
17 18 19
      # Example Request:
      #   GET /projects/:id/repository/commits
      get ":id/repository/commits" do
20 21
        datetime_attributes! :since, :until

22 23 24
        page = (params[:page] || 0).to_i
        per_page = (params[:per_page] || 20).to_i
        ref = params[:ref_name] || user_project.try(:default_branch) || 'master'
25 26
        after = params[:since]
        before = params[:until]
27

28
        commits = user_project.repository.commits(ref, limit: per_page, offset: page * per_page, after: after, before: before)
29 30 31 32 33 34 35 36 37 38 39 40
        present commits, with: Entities::RepoCommit
      end

      # Get a specific commit of a project
      #
      # Parameters:
      #   id (required) - The ID of a project
      #   sha (required) - The commit hash or name of a repository branch or tag
      # Example Request:
      #   GET /projects/:id/repository/commits/:sha
      get ":id/repository/commits/:sha" do
        sha = params[:sha]
41
        commit = user_project.commit(sha)
42 43 44 45 46 47 48 49 50 51 52 53 54
        not_found! "Commit" unless commit
        present commit, with: Entities::RepoCommitDetail
      end

      # Get the diff for a specific commit of a project
      #
      # Parameters:
      #   id (required) - The ID of a project
      #   sha (required) - The commit or branch name
      # Example Request:
      #   GET /projects/:id/repository/commits/:sha/diff
      get ":id/repository/commits/:sha/diff" do
        sha = params[:sha]
55
        commit = user_project.commit(sha)
56
        not_found! "Commit" unless commit
57
        commit.raw_diffs.to_a
58
      end
59 60 61 62 63 64 65 66 67 68

      # Get a commit's comments
      #
      # Parameters:
      #   id (required) - The ID of a project
      #   sha (required) - The commit hash
      # Examples:
      #   GET /projects/:id/repository/commits/:sha/comments
      get ':id/repository/commits/:sha/comments' do
        sha = params[:sha]
69
        commit = user_project.commit(sha)
70
        not_found! 'Commit' unless commit
71
        notes = Note.where(commit_id: commit.id).order(:created_at)
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
        present paginate(notes), with: Entities::CommitNote
      end

      # Post comment to commit
      #
      # Parameters:
      #   id (required) - The ID of a project
      #   sha (required) - The commit hash
      #   note (required) - Text of comment
      #   path (optional) - The file path
      #   line (optional) - The line number
      #   line_type (optional) - The type of line (new or old)
      # Examples:
      #   POST /projects/:id/repository/commits/:sha/comments
      post ':id/repository/commits/:sha/comments' do
        required_attributes! [:note]

        sha = params[:sha]
90
        commit = user_project.commit(sha)
91 92 93 94 95 96 97 98
        not_found! 'Commit' unless commit
        opts = {
          note: params[:note],
          noteable_type: 'Commit',
          commit_id: commit.id
        }

        if params[:path] && params[:line] && params[:line_type]
99
          commit.raw_diffs(all_diffs: true).each do |diff|
100
            next unless diff.new_path == params[:path]
101
            lines = Gitlab::Diff::Parser.new.parse(diff.diff.each_line)
102 103 104 105 106 107 108 109

            lines.each do |line|
              next unless line.new_pos == params[:line].to_i && line.type == params[:line_type]
              break opts[:line_code] = Gitlab::Diff::LineCode.generate(diff.new_path, line.new_pos, line.old_pos)
            end

            break if opts[:line_code]
          end
110 111

          opts[:type] = LegacyDiffNote.name if opts[:line_code]
112 113 114 115 116 117 118
        end

        note = ::Notes::CreateService.new(user_project, current_user, opts).execute

        if note.save
          present note, with: Entities::CommitNote
        else
119
          render_api_error!("Failed to save note #{note.errors.messages}", 400)
120 121
        end
      end
122 123 124
    end
  end
end