Class: Mbeditor::GitController

Inherits:
ApplicationController show all
Defined in:
app/controllers/mbeditor/git_controller.rb

Overview

Thin controller for all Git-related endpoints added in the Git & Code Review system. All heavy logic lives in service objects under app/services/mbeditor/.

Endpoints


GET /mbeditor/git/diff ?file=<path> GET /mbeditor/git/blame ?file=<path> GET /mbeditor/git/file_history ?file=<path> GET /mbeditor/git/commit_graph GET /mbeditor/redmine/issue/:id

Instance Method Summary collapse

Instance Method Details

#blameObject

GET /mbeditor/git/blame?file=<path>



48
49
50
51
52
53
54
55
56
# File 'app/controllers/mbeditor/git_controller.rb', line 48

def blame
  file = require_file_param
  return unless file

  lines = GitBlameService.new(repo_path: workspace_root, file_path: file).call
  render json: { lines: lines }
rescue StandardError => e
  render json: { error: e.message }, status: :unprocessable_content
end

#combined_diffObject

GET /mbeditor/git/combined_diff?scope=local|branch Returns the raw unified diff text for all files in the given scope. scope=local → git diff HEAD (working tree vs HEAD) scope=branch → git diff <branch-base>..HEAD (same baseline as git_info)



92
93
94
95
96
97
98
# File 'app/controllers/mbeditor/git_controller.rb', line 92

def combined_diff
  scope = params[:scope] == 'branch' ? :branch : :local
  out = GitCombinedDiffService.new(repo_path: workspace_root, scope: scope).call
  render plain: out, content_type: "text/plain"
rescue StandardError
  render plain: "", content_type: "text/plain"
end

#commit_detailObject

GET /mbeditor/git/commit_detail?sha=<hash>



78
79
80
81
82
83
84
85
86
# File 'app/controllers/mbeditor/git_controller.rb', line 78

def commit_detail
  sha = params[:sha].to_s.strip
  return render json: { error: "sha required" }, status: :bad_request if sha.blank?
  return render json: { error: "Invalid sha" }, status: :bad_request unless sha.match?(/\A[0-9a-fA-F]{1,40}\z/)

  render json: GitCommitDetailService.new(repo_path: workspace_root, sha: sha).call
rescue StandardError => e
  render json: { error: e.message }, status: :unprocessable_content
end

#commit_graphObject

GET /mbeditor/git/commit_graph



70
71
72
73
74
75
# File 'app/controllers/mbeditor/git_controller.rb', line 70

def commit_graph
  commits = GitCommitGraphService.new(repo_path: workspace_root).call
  render json: { commits: commits }
rescue StandardError => e
  render json: { error: e.message }, status: :unprocessable_content
end

#diffObject



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
# File 'app/controllers/mbeditor/git_controller.rb', line 19

def diff
  file = require_file_param
  return unless file

  base = params[:base].presence
  head = params[:head].presence
  # 'WORKING' is a frontend sentinel meaning current on-disk working tree
  head = nil if head == 'WORKING'
  # Allow full/short SHA hashes plus common git ref formats: branch names,
  # HEAD, remote tracking refs, parent notation (sha^, sha~N) and tags.
  # @ is excluded to block reflog syntax like @{-1} or HEAD@{2}.
  valid_ref = /\A[a-zA-Z0-9._\-\/\^~]+\z/
  if [base, head].any? { |s| s && (s.length > 200 || !s.match?(valid_ref)) }
    return render json: { error: 'Invalid ref' }, status: :bad_request
  end

  result = GitDiffService.new(
    repo_path: workspace_root,
    file_path: file,
    base_sha: base,
    head_sha: head
  ).call

  render json: result
rescue StandardError => e
  render json: { error: e.message }, status: :unprocessable_content
end

#file_historyObject

GET /mbeditor/git/file_history?file=<path>



59
60
61
62
63
64
65
66
67
# File 'app/controllers/mbeditor/git_controller.rb', line 59

def file_history
  file = require_file_param
  return unless file

  commits = GitFileHistoryService.new(repo_path: workspace_root, file_path: file).call
  render json: { commits: commits }
rescue StandardError => e
  render json: { error: e.message }, status: :unprocessable_content
end

#redmine_issueObject

GET /mbeditor/redmine/issue/:id



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'app/controllers/mbeditor/git_controller.rb', line 101

def redmine_issue
  unless Mbeditor.configuration.redmine_enabled
    return render json: { error: 'Redmine integration is disabled.' }, status: :service_unavailable
  end

  return render json: { error: 'Invalid issue id' }, status: :bad_request unless params[:id].to_s.match?(/\A\d+\z/)

  result = RedmineService.new(issue_id: params[:id]).call
  render json: result
rescue RedmineDisabledError => e
  render json: { error: e.message }, status: :service_unavailable
rescue RedmineConfigError => e
  render json: { error: e.message }, status: :unprocessable_content
rescue StandardError => e
  render json: { error: e.message }, status: :unprocessable_content
end