main
rb 72 lines 2.76 KB
Raw
1 # frozen_string_literal: true
2
3 require "open3"
4
5 module Api
6 module V1
7 # Lists and creates the authenticated user's repositories hosted on sigit.si.
8 #
9 # This replaces the desktop app's old dependency on smbCloud platform
10 # projects: siGit is a git app, so it lists/creates the user's own sigit-si
11 # repos. Creating one is the "publish to sigit.si" target — an empty bare
12 # repo the desktop then pushes its local content to.
13 class ReposController < Api::BaseController
14 before_action :authenticate_token!
15
16 # GET /api/v1/repos
17 # Header: Authorization: Bearer <access_token>
18 def index
19 repos = current_user.repositories.order(updated_at: :desc)
20 render json: repos.map { |repo| repo_json(repo) }, status: :ok
21 end
22
23 # POST /api/v1/repos
24 # Params: name (required), is_private (default false), description
25 # Creates an empty bare repo for the user to push to.
26 def create
27 repo = current_user.repositories.new(
28 name: params[:name].to_s.strip,
29 is_private: ActiveModel::Type::Boolean.new.cast(params[:is_private]) || false,
30 description: params[:description],
31 default_branch: "main"
32 )
33 repo.disk_path = GitRepositoryService.repo_path(current_user.username, repo.name)
34
35 unless repo.save
36 return render_error(ERR_INVALID, repo.errors.full_messages.to_sentence,
37 status: :unprocessable_entity)
38 end
39
40 GitRepositoryService.create_bare_repo(current_user.username, repo.name)
41 # Point HEAD at the default branch so the first push lands on it.
42 Open3.capture3("git", "--git-dir", repo.disk_path,
43 "symbolic-ref", "HEAD", "refs/heads/#{repo.default_branch}")
44
45 render json: repo_json(repo), status: :created
46 rescue StandardError => e
47 Rails.logger.error("API repo create failed for #{params[:name].inspect}: #{e.message}")
48 repo&.destroy # roll back the row if the on-disk init blew up
49 render_error(ERR_UNKNOWN, "Failed to create the repository.", status: :internal_server_error)
50 end
51
52 private
53
54 def repo_json(repo)
55 {
56 id: repo.id,
57 name: repo.name,
58 full_name: repo.full_name,
59 description: repo.description,
60 default_branch: repo.default_branch,
61 kind: repo.kind,
62 is_private: repo.is_private,
63 stars_count: repo.stars_count,
64 initialized: repo.initialized?,
65 updated_at: repo.updated_at,
66 web_url: "#{request.base_url}/#{repo.full_name}",
67 clone_url: "#{request.base_url}/#{repo.full_name}.git"
68 }
69 end
70 end
71 end
72 end