diff --git a/Gemfile b/Gemfile index 175ca330c..3da6f273d 100644 --- a/Gemfile +++ b/Gemfile @@ -135,4 +135,4 @@ gem 'doorkeeper' gem 'doorkeeper-jwt' -gem 'gitea-client', '~> 0.8.2' \ No newline at end of file +gem 'gitea-client', '~> 0.10.2' \ No newline at end of file diff --git a/app/controllers/admins/dashboards_controller.rb b/app/controllers/admins/dashboards_controller.rb index 3971971ff..dccff054b 100644 --- a/app/controllers/admins/dashboards_controller.rb +++ b/app/controllers/admins/dashboards_controller.rb @@ -1,10 +1,33 @@ class Admins::DashboardsController < Admins::BaseController def index - @active_user_count = User.where(last_login_on: today).count - @weekly_active_user_count = User.where(last_login_on: current_week).count - @month_active_user_count = User.where(last_login_on: current_month).count + # 用户活跃数 + day_user_ids = CommitLog.where(created_at: today).pluck(:project_id).uniq + weekly_user_ids = CommitLog.where(created_at: current_week).pluck(:project_id).uniq + month_user_ids = CommitLog.where(created_at: current_month).pluck(:project_id).uniq + @active_user_count = User.where(last_login_on: today).or(User.where(id: day_user_ids)).count + @weekly_active_user_count = User.where(last_login_on: current_week).or(User.where(id: weekly_user_ids)).count + @month_active_user_count = User.where(last_login_on: current_month).or(User.where(id: month_user_ids)).count + user_ids = User.where(created_on: pre_week).pluck(:id).uniq + weekly_keep_user_count = User.where(id: user_ids).where(last_login_on: current_week).count + @weekly_keep_rate = format("%.2f", user_ids.size > 0 ? weekly_keep_user_count.to_f / user_ids.size : 0) - @new_user_count = User.where(created_on: current_month).count + # 新用户注册数 + @day_new_user_count = User.where(created_on: today).count + @weekly_new_user_count = User.where(created_on: current_week).count + @month_new_user_count = User.where(created_on: current_month).count + + # 活跃项目数 + day_project_ids = (CommitLog.where(created_at: today).pluck(:project_id).uniq + Issue.where(created_on: today).pluck(:project_id).uniq).uniq + weekly_project_ids = (CommitLog.where(created_at: current_week).pluck(:project_id).uniq + Issue.where(created_on: current_week).pluck(:project_id).uniq).uniq + month_project_ids = (CommitLog.where(created_at: current_month).pluck(:project_id).uniq + Issue.where(created_on: current_month).pluck(:project_id).uniq).uniq + @day_active_project_count = Project.where(updated_on: today).or(Project.where(id: day_project_ids)).count + @weekly_active_project_count = Project.where(updated_on: current_week).or(Project.where(id: weekly_project_ids)).count + @month_active_project_count = Project.where(updated_on: current_month).or(Project.where(id: month_project_ids)).count + + # 新增项目数 + @day_new_project_count = Project.where(created_on: today).count + @weekly_new_project_count = Project.where(created_on: current_week).count + @month_new_project_count = Project.where(created_on: current_month).count end def month_active_user @@ -16,7 +39,6 @@ class Admins::DashboardsController < Admins::BaseController { value: count['professional'].to_i, name: '专业人士' }, { value: count[nil].to_i, name: '未选职业' }, ] - render_ok(data: data) end @@ -42,10 +64,14 @@ class Admins::DashboardsController < Admins::BaseController end def current_week - 7.days.ago.beginning_of_day..Time.now.end_of_day + 7.days.ago.end_of_day..Time.now.end_of_day end def current_month - 30.days.ago.beginning_of_day..Time.now.end_of_day + 30.days.ago.end_of_day..Time.now.end_of_day + end + + def pre_week + 14.days.ago.end_of_day..7.days.ago.end_of_day end end \ No newline at end of file diff --git a/app/controllers/api/v1/base_controller.rb b/app/controllers/api/v1/base_controller.rb index d97123f45..a66bfc528 100644 --- a/app/controllers/api/v1/base_controller.rb +++ b/app/controllers/api/v1/base_controller.rb @@ -19,9 +19,29 @@ class Api::V1::BaseController < ApplicationController # User.find(doorkeeper_token.resource_owner_id) if doorkeeper_token # end # end + + def limit + params.fetch(:limit, 15) + end + def page + params.fetch(:page, 1) + end + # 具有对仓库的管理权限 def require_manager_above @project = load_project return render_forbidden unless current_user.admin? && @project.manager?(current_user) end + + # 具有对仓库的操作权限 + def require_operate_above + @project = load_project + return render_forbidden unless current_user.admin? && @project.operator?(current_user) + end + + # 具有对仓库的访问权限 + def require_public_and_member_above + @project = load_project + return render_forbidden unless @project.is_public || (current_user.admin? && @project.member?(current_user)) + end end \ No newline at end of file diff --git a/app/controllers/api/v1/projects/branches_controller.rb b/app/controllers/api/v1/projects/branches_controller.rb new file mode 100644 index 000000000..bc4919616 --- /dev/null +++ b/app/controllers/api/v1/projects/branches_controller.rb @@ -0,0 +1,18 @@ +class Api::V1::Projects::BranchesController < Api::V1::BaseController + before_action :require_public_and_member_above, only: [:all] + + def all + @result_object = Api::V1::Projects::Branches::AllListService.call(@project, current_user&.gitea_token) + end + + before_action :require_operate_above, only: [:create] + + def create + @result_object = Api::V1::Projects::Branches::CreateService.call(@project, branch_params, current_user&.gitea_token) + end + + private + def branch_params + params.require(:branch).permit(:new_branch_name, :old_branch_name) + end +end \ No newline at end of file diff --git a/app/controllers/api/v1/projects/commits_controller.rb b/app/controllers/api/v1/projects/commits_controller.rb new file mode 100644 index 000000000..a1545ae6f --- /dev/null +++ b/app/controllers/api/v1/projects/commits_controller.rb @@ -0,0 +1,12 @@ +class Api::V1::Projects::CommitsController < Api::V1::BaseController + before_action :require_public_and_member_above, only: [:index, :diff] + + def index + @result_object = Api::V1::Projects::Commits::ListService.call(@project, {page: page, limit: limit, sha: params[:sha]}, current_user&.gitea_token) + puts @result_object + end + + def diff + @result_object = Api::V1::Projects::Commits::DiffService.call(@project, params[:sha], current_user&.gitea_token) + end +end \ No newline at end of file diff --git a/app/controllers/api/v1/projects/contents_controller.rb b/app/controllers/api/v1/projects/contents_controller.rb new file mode 100644 index 000000000..a4e65051e --- /dev/null +++ b/app/controllers/api/v1/projects/contents_controller.rb @@ -0,0 +1,13 @@ +class Api::V1::Projects::ContentsController < Api::V1::BaseController + before_action :require_operate_above, only: [:batch] + + def batch + @result_object = Api::V1::Projects::Contents::BatchCreateService.call(@project, batch_content_params, current_user&.gitea_token) + puts @result_object + end + + private + def batch_content_params + params.require(:content).permit(:author_email, :author_name, :author_timeunix, :branch, :committer_email, :committer_name, :committer_timeunix, :message, :new_branch, files: [ :action_type, :content, :encoding, :file_path]) + end +end \ No newline at end of file diff --git a/app/controllers/api/v1/projects/git_controller.rb b/app/controllers/api/v1/projects/git_controller.rb new file mode 100644 index 000000000..f30dce1a9 --- /dev/null +++ b/app/controllers/api/v1/projects/git_controller.rb @@ -0,0 +1,12 @@ +class Api::V1::Projects::GitController < Api::V1::BaseController + before_action :require_public_and_member_above, only: [:trees, :blobs] + + def trees + @result_object = Api::V1::Projects::Git::TreesService.call(@project, params[:sha], {recursive: params[:recursive], page: page, limit: limit}, current_user&.gitea_token) + end + + def blobs + @result_object = Api::V1::Projects::Git::BlobsService.call(@project, params[:sha], current_user&.gitea_token) + end + +end \ No newline at end of file diff --git a/app/controllers/api/v1/projects_controller.rb b/app/controllers/api/v1/projects_controller.rb index 05a3750ca..bc51362ae 100644 --- a/app/controllers/api/v1/projects_controller.rb +++ b/app/controllers/api/v1/projects_controller.rb @@ -1,5 +1,5 @@ class Api::V1::ProjectsController < Api::V1::BaseController - before_action :load_project, only: [:show] + before_action :require_public_and_member_above, only: [:show, :compare, :blame] def index render_ok @@ -8,4 +8,13 @@ class Api::V1::ProjectsController < Api::V1::BaseController def show @result_object = Api::V1::Projects::GetService.call(@project, current_user.gitea_token) end + + def compare + @result_object = Api::V1::Projects::CompareService.call(@project, params[:from], params[:to], current_user&.gitea_token) + end + + def blame + @result_object = Api::V1::Projects::BlameService.call(@project, params[:sha], params[:filepath], current_user&.gitea_token) + puts @result_object + end end \ No newline at end of file diff --git a/app/controllers/concerns/api/project_helper.rb b/app/controllers/concerns/api/project_helper.rb index 0b444c488..52967e784 100644 --- a/app/controllers/concerns/api/project_helper.rb +++ b/app/controllers/concerns/api/project_helper.rb @@ -8,7 +8,7 @@ module Api::ProjectHelper @project, @owner = Project.find_with_namespace(namespace, repo) if @project - logger.info "###########:project not founded" + logger.info "###########:project founded" @project else logger.info "###########:project not found" diff --git a/app/docs/slate/source/includes/_repositories.md b/app/docs/slate/source/includes/_repositories.md index f0a64a60d..ae74dac7f 100644 --- a/app/docs/slate/source/includes/_repositories.md +++ b/app/docs/slate/source/includes/_repositories.md @@ -409,21 +409,21 @@ await octokit.request('GET /api/yystopf/csfjkkj/tags.json') ``` -## 仓库分支列表 -仓库分支列表 +## 仓库所有分支列表 +仓库所有分支列表 > 示例: ```shell -curl -X GET http://localhost:3000/api/yystopf/csfjkkj/branches.json +curl -X GET http://localhost:3000/api/v1/yystopf/csfjkkj/branches/all.json ``` ```javascript -await octokit.request('GET /api/yystopf/csfjkkj/branches.json') +await octokit.request('GET /api/v1/yystopf/csfjkkj/branches/all.json') ``` ### HTTP 请求 -`GET /api/:owner/:repo/branches.json` +`GET /api/v1/:owner/:repo/branches/all.json` ### 请求参数: 参数 | 必选 | 默认 | 类型 | 字段说明 @@ -466,6 +466,98 @@ await octokit.request('GET /api/yystopf/csfjkkj/branches.json') ] ``` +## 仓库创建分支 +为仓库创建一个新的分支 + +> 示例: + +```shell +curl -X POST \ +-d "new_branch_name=ceshi_branch_1" \ +-d "old_branch_name=master" \ +http://localhost:3000/api/v1/yystopf/csfjkkj/branches.json +``` + +```javascript +await octokit.request('POST /api/v1/yystopf/csfjkkj/branches.json') +``` + +### HTTP 请求 +`POST /api/v1/:owner/:repo/branches.json` + +### 请求参数: +参数 | 必选 | 默认 | 类型 | 字段说明 +--------- | ------- | ------- | -------- | ---------- +|owner |是| |string |用户登录名 | +|repo |是| |string |项目标识identifier | +|new_branch_name|是||string| 新分支名称| +|old_branch_name|否||string| 来源分支名称| + +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|name |string|分支名称| +|commit.id |string|提交ID| +|commit.message |string|提交信息| +|commit.author.id |string|提交作者ID| +|commit.author.login |string|提交作者标识| +|commit.author.name |string|提交作者名称| +|commit.author.type |string|提交作者类型| +|commit.committer.id |string|提交者ID| +|commit.committer.login |string|提交者标识| +|commit.committer.name |string|提交者名称| +|commit.committer.type |string|提交者类型| +|commit.committer.image_url|string|提交者头像| +|commit.time_ago |string|分支最新提交时间距现在时间差| +|commit.timestamp |string|分支最新提交时间| +|protected |bool |是否为保护分支| +|user_can_push |bool |当前用户是否能提交| +|user_can_merge |bool |当前用户是否能合并| +|commit_id |string|提交ID| +|commit_time_from_now |string|分支最新提交时间距现在时间差| +|commit_time |string|分支最新提交时间| +|http_url |string|分支http地址| +|zip_url |string|分支zip包下载地址| +|tar_url |string|分支tar包下载地址| + +> 返回的JSON示例: + +```json +{ + "name": "new_branch_8", + "commit": { + "id": "80dd40214a58622312393b2ae693756a4781fab2", + "message": "x拟增\n\nSigned-off-by: yystopf ", + "author": { + "id": "2", + "login": "yystopf", + "name": "heh", + "type": "User", + "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png" + }, + "committer": { + "id": "2", + "login": "yystopf", + "name": "heh", + "type": "User", + "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png" + }, + "time_ago": "1天前", + "timestamp": "2022-07-13T09:54:15Z" + }, + "protected": false, + "user_can_push": true, + "user_can_merge": true, + "commit_id": "80dd40214a58622312393b2ae693756a4781fab2", + "commit_time_from_now": "1天前", + "commit_time": "2022-07-13T09:54:15Z", + "default_branch": "master", + "http_url": "http://127.0.0.1:10081/yystopf/ceshi_hook.git", + "zip_url": "http://localhost:3000/api/yystopf/ceshi_hook/archive/new_branch_8.zip", + "tar_url": "http://localhost:3000/api/yystopf/ceshi_hook/archive/new_branch_8.tar.gz" +} +``` + ## 仓库贡献者列表 仓库贡献者列表 @@ -1001,6 +1093,138 @@ await octokit.request('GET /api/yystopf/ceshi/files.json') ] ``` +## 提交文件到仓库 +提交文件到仓库,支持批量 + +> 示例: + +```shell +curl -X POST \ +-d "files[][action_type]=create" \ +-d "files[][content]=jfksj" \ +-d "files[][encoding]=text" \ +-d "files[][file_path]=heihei8" \ +-d "author_email=yystopf@163.com" \ +-d "author_name=yystopf" \ +-d "author_timeunix=1658214400" \ +-d "committer_email=yystopf@163.com" \ +-d "committer_name=yystopf" \ +-d "committer_timeunix=1658214400" \ +-d "branch=develop" \ +-d "new_branch=develop_ceshi" \ +-d "message=测试提交" \ +http://localhost:3000/api/v1/yystopf/ceshi/contents/batch.json +``` + +```javascript +await octokit.request('POST /api/v1/yystopf/ceshi/contents/batch.json') +``` + +### HTTP 请求 +`POST /api/v1/:owner/:repo/contents/batch` + +### 请求参数: +参数 | 必选 | 默认 | 类型 | 字段说明 +--------- | ------- | ------- | -------- | ---------- +|owner |是| |string |用户登录名 | +|repo |是| |string |项目标识identifier | +|files.action_type |是| |string|操作类型 create: 创建 update: 更新 delete: 删除| +|files.content |是| |string|文件内容| +|files.encoding |是| |string|文件编码方式 text 文本 base64 加密| +|files.file_path |是| |string|文件路径| +|author_email |是| |string|作者邮箱| +|author_name |是| |string|作者名称| +|author_timeunix |是| |int|编码时间,精确到秒| +|committer_email |是| |string|提交者邮箱| +|committer_name |是| |string|提交者名称| +|committer_timeunix|是| |int|提交时间戳,精确到秒| +|branch |是| |string|提交分支| +|new_branch |否| |string|如果需要创建新分支,这个需要填| +|message |是| |string|提交信息| + +> 请求的JSON示例: + +```json +{ + "files": [ + { + "action_type": "create", + "content": "jfksj", + "encoding": "text", + "file_path": "heihei7" + } + ], + "author_email": "yystopf@163.com", + "author_name": "yystopf", + "author_timeunix": 1658214400, + "committer_email": "yystopf@163.com", + "committer_name": "yystopf", + "committer_timeunix": 1658214400, + "branch": "hh_ceshi", + "message": "测试提交" +} +``` + +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|commit.sha |string |提交ID| +|commit.author |object |作者| +|commit.committer |object |提交者| +|commit.commit_message|string |提交信息| +|commit.parent_shas |array |父节点commit ID| +|commit.authored_time|int |编码时间| +|commit.commited_time|int |提交时间| +|contents.name |string |文件名称| +|contents.path |string |文件路径| +|contents.sha |string |文件标识| +|contents.type |string |文件类型| +|contents.size |int |文件大小| +|contents.url |string |文件地址| +|contents.encoding |string |编码类型 text 文本 base64 加密 | +|contents.content |string |文件内容| + + +> 返回的JSON示例: + +```json +{ + "commit": { + "sha": "7c1e25f9b974e4b7a3816bd7f5e49b441078e999", + "author": { + "id": "2", + "login": "yystopf", + "name": "heh", + "type": "User", + "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png" + }, + "committer": { + "id": "2", + "login": "yystopf", + "name": "heh", + "type": "User", + "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png" + }, + "commit_message": "测试提交\n", + "parent_shas": [ + "9aec816d0f3600082ca77893290a14bd29d805fe" + ], + "authored_time": 1658214400, + "commited_time": 1658214400 + }, + "contents": [ + { + "name": "heihei7", + "path": "heihei7", + "sha": "f0acac8efb3021b0f6a7b13b42d033d86e076a4b", + "type": "file", + "size": 5, + "encoding": "base64", + "content": "amZrc2o=" + } + ] +} +``` ## 获取仓库代码目录 获取仓库代码目录 @@ -1214,71 +1438,665 @@ await octokit.request('GET /api/yystopf/csfjkkj/readme.json') Success Data. -## 获取仓库贡献者 -获取仓库贡献者 + +## 获取文件树列表 +根据分支、标签、commit ID获取仓库文件树列表 > 示例: ```shell curl -X GET \ --d "ref=master" \ --d "filepath=lib" \ -http://localhost:3000/api/yystopf/csfjkkj/contributors.json +-d "recursive=true" \ +-d "page=1" \ +-d "limit=1" \ +http://localhost:3000/api/v1/yystopf/csfjkkj/git/trees/80dd40214a58622312393b2ae693756a4781fab2.json ``` ```javascript -await octokit.request('GET /api/yystopf/csfjkkj/contributors.json') +await octokit.request('GET /api/v1/yystopf/csfjkkj/git/trees/80dd40214a58622312393b2ae693756a4781fab2.json') ``` ### HTTP 请求 -`GET /api/:owner/:repo/contributors.json` +`GET /api/v1/:owner/:repo/git/trees/:sha.json` ### 请求参数: 参数 | 必选 | 默认 | 类型 | 字段说明 --------- | ------- | ------- | -------- | ---------- -|owner |是| |string |用户登录名 | -|repo |是| |string |项目标识identifier | -|ref |否| | string |分支名称、tag名称或是提交记录id,默认为整个仓库 | -|filepath |否| | string |子目录名称,默认为空 | - +|owner |是| | string |用户登录名 | +|repo |是| | string |项目标识identifier | +|sha |是| | string |分支名称、tag名称或是提交记录id | +|recursive|否| | bool |是否显示目录| +|page |否|1 | int |页码| +|limit |否|15| int |分页个数| ### 返回字段说明: 参数 | 类型 | 字段说明 --------- | ----------- | ----------- -|total_count |integer|贡献者数量| -|contributions |integer|贡献数量| -|login |string |用户登录名 | -|type |string|用户类型 | -|name |string|用户昵称| -|image_url |string|用户头像| +|total_count |int |文件树数量| +|sha |string |查询分支、标签、commit_id最后一次提交的ID | +|entries.name |string |文件树名称| +|entries.mode |string |文件树权限| +|entries.type |string |文件树类型, file:文件,dir: 文件夹| +|entries.size |int |文件树大小| +|entries.sha |string |文件树commit_ID| > 返回的JSON示例: ```json { - "contributors": [ + "total_count": 13, + "sha": "80dd40214a58622312393b2ae693756a4781fab2", + "entries": [ { - "contributions": 5, - "login": "testforge2", - "type": "User", - "name": "testforge2", - "image_url": "system/lets/letter_avatars/2/T/236_177_85/120.png" - }, - { - "contributions": 79, - "login": "yystopf", - "type": "User", - "name": "yystopf", - "image_url": "system/lets/letter_avatars/2/Y/241_125_89/120.png" + "name": "README.md", + "mode": "100644", + "type": "file", + "size": 14, + "sha": "b2f7b457fd8ca55f2274032cbb2abcb7dd8cd57e" } - ], - "total_count": 2 + ] } ``` +## 获取仓库blobs内容 +根据commit ID获取仓库blobs内容 + +> 示例: + +```shell +curl -X GET http://localhost:3000/api/v1/yystopf/csfjkkj/git/blobs/80dd40214a58622312393b2ae693756a4781fab2.json +``` + +```javascript +await octokit.request('GET /api/v1/yystopf/csfjkkj/git/blobs/80dd40214a58622312393b2ae693756a4781fab2.json') +``` + +### HTTP 请求 +`GET /api/v1/:owner/:repo/git/blobs/:sha.json` + +### 请求参数: +参数 | 必选 | 默认 | 类型 | 字段说明 +--------- | ------- | ------- | -------- | ---------- +|owner|是| | string |用户登录名 | +|repo |是| | string |项目标识identifier | +|sha |是| | string |提交记录id | +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|sha |string |提交ID | +|size |int |blobs大小| +|encoding |string |内容编码模式| +|content |string |blobs内容| + +> 返回的JSON示例: + +```json +{ + "sha": "80dd40214a58622312393b2ae693756a4781fab2", + "size": 247, + "encoding": "base64", + "content": "dHJlZSAyN2JjYjI2ZDQ5YmU1M2RmOGZmYTk5NDc3MjRkYmI3YzIzZWI4MjY4CnBhcmVudCA3ZTRkOGJiM2MyOGUyNGQ0Y2Q2YjIwNWYyZWVkMzI1MTNlOTM3NTI0CmF1dGhvciB5eXN0b3BmIDx5eXN0b3BmQDE2My5jb20+IDE2NTc3MDYwNTUgKzAwMDAKY29tbWl0dGVyIHl5c3RvcGYgPHl5c3RvcGZAMTYzLmNvbT4gMTY1NzcwNjA1NSArMDAwMAoKeOaLn+WingoKU2lnbmVkLW9mZi1ieTogeXlzdG9wZiA8eXlzdG9wZkAxNjMuY29tPg==" +} +``` + + +## 获取仓库提交列表 +根据分支名、标签、commit ID来获取提交列表 + +> 示例: + +```shell +curl -X GET \ +-d "sha=master" \ +-d "page=1" \ +-d "limit=1" \ +http://localhost:3000/api/v1/yystopf/csfjkkj/commits.json +``` + +```javascript +await octokit.request('GET /api/v1/yystopf/csfjkkj/commits.json') +``` + +### HTTP 请求 +`GET /api/v1/:owner/:repo/commits.json` + +### 请求参数: +参数 | 必选 | 默认 | 类型 | 字段说明 +--------- | ------- | ------- | -------- | ---------- +|owner|是| | string |用户登录名 | +|repo |是| | string |项目标识identifier | +|sha |否| | string |分支名、标签名或Commit ID| +|page |否| | int |页码| +|limit|否| | int |每页数量| +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|total_count|int|提交总数| +|commits.sha|string|提交ID| +|commits.author|object|提交作者| +|commits.committer|object|提交者| +|commits.commit_message|string|提交信息| +|commits.parent_shas|array|提交父节点ID| +|commits.files|array|提交文件| +|commits.commit_date|string|提交日期| +|commits.commit_time|string|提交时间| +|commits.branch|string|提交分支| + + +> 返回的JSON示例: + +```json +{ + "total_count": 12, + "commits": [ + { + "sha": "86c62a1e91c07b58b8aa6c89b94856d89c0f7e55", + "author": { + "id": null, + "login": "viletyy", + "name": "viletyy", + "type": null, + "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png" + }, + "committer": { + "id": null, + "login": "viletyy", + "name": "viletyy", + "type": null, + "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png" + }, + "commit_message": "fix\n", + "parent_shas": [ + "411e4d259785241f1bd14faf99ca24fd1b802f2a" + ], + "files": [ + "hd.txt" + ], + "commit_date": "2022-07-05", + "commit_time": "2022-07-05 11:00:45", + "branch": "hh_ceshi" + } + ] +} +``` + + +## 获取单个提交的blame信息 +根据commit ID获取blame信息 + +> 示例: + +```shell +curl -X GET http://localhost:3000/api/v1/yystopf/csfjkkj/commits/80dd40214a58622312393b2ae693756a4781fab2/diff.json +``` + +```javascript +await octokit.request('GET /api/v1/yystopf/csfjkkj/commits/80dd40214a58622312393b2ae693756a4781fab2/diff.json') +``` + +### HTTP 请求 +`GET /api/v1/:owner/:repo/commits/:sha/diff.json` + +### 请求参数: +参数 | 必选 | 默认 | 类型 | 字段说明 +--------- | ------- | ------- | -------- | ---------- +|owner|是| | string |用户登录名 | +|repo |是| | string |项目标识identifier | +|sha |是| | string |提交记录id | +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|file_nums|int|文件数量| +|total_addition|int|新增行数| +|total_deletion|int|删除行数| +|files.name|string|文件名称| +|files.oldname|string|文件修改前名称| +|files.addition|int|文件新增行数| +|files.deletion|int|文件删除行数| +|files.type|int|文件类型 1: 新增 2: 更改 3: 删除 4: 重命名 5: 复制| +|files.is_created|bool|是否为新建文件| +|files.is_deleted|bool|是否为删除文件| +|files.is_bin|bool|是否为二进制文件| +|files.is_lfs_file|bool|| +|files.is_renamed|bool|是否重命名| +|files.is_ambiguous|bool|| +|files.is_submodule|bool|是否为子模块| +|files.sections.file_name|string|文件名称| +|files.sections.name|string|| +|files.sections.lines.left_index|int|| +|files.sections.lines.right_index|int|| +|files.sections.lines.match|int|| +|files.sections.lines.type|int|| +|files.sections.lines.content|string|| +|files.sections.lines.section_path|string|| +|files.sections.lines.section_last_left_index|int|| +|files.sections.lines.section_last_right_index|int|| +|files.sections.lines.section_left_index|int|| +|files.sections.lines.section_right_index|int|| +|files.sections.lines.section_left_hunk_size|int|| +|files.sections.lines.section_right_hunk_size|int|| + + + +> 返回的JSON示例: + +```json +{ + "file_nums": 1, + "total_addition": 1, + "total_deletion": 0, + "files": [ + { + "name": "xinzeng3", + "oldname": "xinzeng3", + "addition": 1, + "deletion": 0, + "type": 1, + "is_created": true, + "is_deleted": false, + "is_bin": false, + "is_lfs_file": false, + "is_renamed": false, + "is_ambiguous": false, + "is_submodule": false, + "sections": [ + { + "file_name": "xinzeng3", + "name": "", + "lines": [ + { + "left_index": 0, + "right_index": 0, + "match": 0, + "type": 4, + "content": "@@ -0,0 +1 @@", + "section_path": "xinzeng3", + "section_last_left_index": 0, + "section_last_right_index": 0, + "section_left_index": 0, + "section_right_index": 1, + "section_left_hunk_size": 0, + "section_right_hunk_size": 0 + }, + { + "left_index": 0, + "right_index": 1, + "match": -1, + "type": 2, + "content": "+1111122222" + } + ] + } + ], + "is_incomplete": false, + "is_incomplete_line_too_long": false, + "is_protected": false + } + ] +} +``` + + +## 获取单个文件的blame信息 +根据分支、标签、commitID获取某个文件的blame信息 + +> 示例: + +```shell +curl -X GET \ +-d "sha=master" \ +-d "filepath=hd.txt" \ +http://localhost:3000/api/v1/yystopf/csfjkkj/blame.json +``` + +```javascript +await octokit.request('GET /api/v1/yystopf/csfjkkj/blame.json') +``` + +### HTTP 请求 +`GET /api/v1/:owner/:repo/blame.json` + +### 请求参数: +参数 | 必选 | 默认 | 类型 | 字段说明 +--------- | ------- | ------- | -------- | ---------- +|owner |是| | string |用户登录名 | +|repo |是| | string |项目标识identifier | +|sha |是| | string |分支、标签或提交记录id | +|filepath|是| | string |文件路径| +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|file_size|int|文件大小| +|file_name|string|文件名称| +|num_lines|int|文件总行数| +|blame_parts.commit|object|提交| +|blame_parts.current_number|int|当前行数| +|blame_parts.effect_line|int|影响的行数| +|blame_parts.lines|array|行内容| + +> 返回的JSON示例: + +```json +{ + "file_size": 32, + "file_name": "hd.txt", + "num_lines": 12, + "blame_parts": [ + { + "commit": { + "sha": "40f76e80bf5bc41fcc94c28ca8a6eab506c15215", + "author": { + "id": null, + "login": "viletyy", + "name": "viletyy", + "type": null, + "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png" + }, + "committer": { + "id": null, + "login": "viletyy", + "name": "viletyy", + "type": null, + "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png" + }, + "commit_message": "fix\n", + "authored_time": "2022-07-04 18:41:25", + "committed_time": "2022-07-04 18:41:25", + "created_time": "2022-07-04 18:41:25" + }, + "current_number": 1, + "effect_line": 5, + "lines": [ + "dkfj", + "s", + "324", + "234", + "2" + ] + }, + { + "commit": { + "sha": "86c62a1e91c07b58b8aa6c89b94856d89c0f7e55", + "author": { + "id": null, + "login": "viletyy", + "name": "viletyy", + "type": null, + "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png" + }, + "committer": { + "id": null, + "login": "viletyy", + "name": "viletyy", + "type": null, + "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png" + }, + "commit_message": "fix\n", + "authored_time": "2022-07-05 11:00:45", + "committed_time": "2022-07-05 11:00:45", + "created_time": "2022-07-05 11:00:45" + }, + "current_number": 6, + "effect_line": 1, + "lines": [ + "dd" + ] + }, + { + "commit": { + "sha": "40f76e80bf5bc41fcc94c28ca8a6eab506c15215", + "author": { + "id": null, + "login": "viletyy", + "name": "viletyy", + "type": null, + "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png" + }, + "committer": { + "id": null, + "login": "viletyy", + "name": "viletyy", + "type": null, + "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png" + }, + "commit_message": "fix\n", + "authored_time": "2022-07-04 18:41:25", + "committed_time": "2022-07-04 18:41:25", + "created_time": "2022-07-04 18:41:25" + }, + "current_number": 7, + "effect_line": 3, + "lines": [ + "23", + "4", + "23" + ] + }, + { + "commit": { + "sha": "86c62a1e91c07b58b8aa6c89b94856d89c0f7e55", + "author": { + "id": null, + "login": "viletyy", + "name": "viletyy", + "type": null, + "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png" + }, + "committer": { + "id": null, + "login": "viletyy", + "name": "viletyy", + "type": null, + "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png" + }, + "commit_message": "fix\n", + "authored_time": "2022-07-05 11:00:45", + "committed_time": "2022-07-05 11:00:45", + "created_time": "2022-07-05 11:00:45" + }, + "current_number": 10, + "effect_line": 1, + "lines": [ + "s1" + ] + }, + { + "commit": { + "sha": "40f76e80bf5bc41fcc94c28ca8a6eab506c15215", + "author": { + "id": null, + "login": "viletyy", + "name": "viletyy", + "type": null, + "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png" + }, + "committer": { + "id": null, + "login": "viletyy", + "name": "viletyy", + "type": null, + "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png" + }, + "commit_message": "fix\n", + "authored_time": "2022-07-04 18:41:25", + "committed_time": "2022-07-04 18:41:25", + "created_time": "2022-07-04 18:41:25" + }, + "current_number": 11, + "effect_line": 1, + "lines": [ + "" + ] + } + ] +} +``` + +## 获取比较提交blame +根据分支名、标签、commit ID来获取代码对比blame + +> 示例: + +```shell +curl -X GET \ +-d "from=hh_ceshi" \ +-d "to=master" \ +http://localhost:3000/api/v1/yystopf/csfjkkj/compare.json +``` + +```javascript +await octokit.request('GET /api/v1/yystopf/csfjkkj/compare.json') +``` + +### HTTP 请求 +`GET /api/v1/:owner/:repo/compare.json` + +### 请求参数: +参数 | 必选 | 默认 | 类型 | 字段说明 +--------- | ------- | ------- | -------- | ---------- +|owner|是| | string |用户登录名 | +|repo |是| | string |项目标识identifier | +|from |是| | string |源分支、标签、commitID | +|to|是||string|目标分支、标签、commitID| +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|commits_count|int|提交数量| +|commits.branch|string|提交分支| +|commits.author|object|提交作者| +|commits.committer|object|提交者| +|commits.commit_message|string|提交信息| +|commits.sha|string|提交ID| +|commits.parent_shas|array|提交父节点ID| +|diff.file_nums|int|文件数量| +|diff.total_addition|int|新增行数| +|diff.total_deletion|int|删除行数| +|diff.files.name|string|文件名称| +|diff.files.oldname|string|文件修改前名称| +|diff.files.addition|int|文件新增行数| +|diff.files.deletion|int|文件删除行数| +|diff.files.type|int|文件类型 1: 新增 2: 更改 3: 删除 4: 重命名 5: 复制| +|diff.files.is_created|bool|是否为新建文件| +|diff.files.is_deleted|bool|是否为删除文件| +|diff.files.is_bin|bool|是否为二进制文件| +|diff.files.is_lfs_file|bool|| +|diff.files.is_renamed|bool|是否重命名| +|diff.files.is_ambiguous|bool|| +|diff.files.is_submodule|bool|是否为子模块| +|diff.files.sections.file_name|string|文件名称| +|diff.files.sections.name|string|| +|diff.files.sections.lines.left_index|int|| +|diff.files.sections.lines.right_index|int|| +|diff.files.sections.lines.match|int|| +|diff.files.sections.lines.type|int|| +|diff.files.sections.lines.content|string|| +|diff.files.sections.lines.section_path|string|| +|diff.files.sections.lines.section_last_left_index|int|| +|diff.files.sections.lines.section_last_right_index|int|| +|diff.files.sections.lines.section_left_index|int|| +|diff.files.sections.lines.section_right_index|int|| +|diff.files.sections.lines.section_left_hunk_size|int|| +|diff.files.sections.lines.section_right_hunk_size|int|| + + + +> 返回的JSON示例: + +```json +{ + "commits_count": 1, + "last_commit_sha": "80dd40214a58622312393b2ae693756a4781fab2", + "commits": [ + { + "author": { + "id": "2", + "login": "yystopf", + "name": "heh", + "type": "User", + "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png" + }, + "committer": { + "id": "2", + "login": "yystopf", + "name": "heh", + "type": "User", + "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png" + }, + "branch": "", + "commit_message": "x拟增\n\nSigned-off-by: yystopf ", + "sha": "7e4d8bb3c28e24d4cd6b205f2eed32513e937524", + "parent_shas": null + } + ], + "diff": { + "file_nums": 1, + "total_addition": 1, + "total_deletion": 0, + "files": [ + { + "name": "ceshi123", + "oldname": "ceshi123", + "addition": 1, + "deletion": 0, + "type": 1, + "is_created": true, + "is_deleted": false, + "is_bin": false, + "is_lfs_file": false, + "is_renamed": false, + "is_ambiguous": false, + "is_submodule": false, + "sections": [ + { + "file_name": "ceshi123", + "name": "", + "lines": [ + { + "left_index": 0, + "right_index": 0, + "match": 0, + "type": 4, + "content": "@@ -0,0 +1 @@", + "section_path": "ceshi123", + "section_last_left_index": 0, + "section_last_right_index": 0, + "section_left_index": 0, + "section_right_index": 1, + "section_left_hunk_size": 0, + "section_right_hunk_size": 0 + }, + { + "left_index": 0, + "right_index": 1, + "match": -1, + "type": 2, + "content": "+1111122222" + } + ] + } + ], + "is_incomplete": false, + "is_incomplete_line_too_long": false, + "is_protected": false + } + ] + } +} +``` + ## 获取仓库webhooks列表 获取仓库webhooks列表 diff --git a/app/helpers/repositories_helper.rb b/app/helpers/repositories_helper.rb index 06437dcb5..f7029c1cd 100644 --- a/app/helpers/repositories_helper.rb +++ b/app/helpers/repositories_helper.rb @@ -10,7 +10,7 @@ module RepositoriesHelper end def download_type(str) - default_type = %w(xlsx xls ppt pptx pdf zip 7z rar exe pdb obj idb RData rdata doc docx mpp vsdx dot otf eot ttf woff woff2 mp4 mov wmv flv mpeg avi avchd webm mkv) + default_type = %w(xlsx xls ppt pptx pdf zip 7z rar exe pdb obj idb RData rdata doc docx mpp vsdx dot otf eot ttf woff woff2 mp4 mov wmv flv mpeg avi avchd webm mkv apk) default_type.include?(str&.downcase) || str.blank? end diff --git a/app/services/api/v1/projects/blame_service.rb b/app/services/api/v1/projects/blame_service.rb new file mode 100644 index 000000000..d419fec14 --- /dev/null +++ b/app/services/api/v1/projects/blame_service.rb @@ -0,0 +1,38 @@ +class Api::V1::Projects::BlameService < ApplicationService + include ActiveModel::Model + + attr_reader :project, :sha, :filepath, :owner, :repo, :token + attr_accessor :gitea_data + + validates :sha, :filepath, presence: true + + def initialize(project, sha, filepath, token=nil) + @project = project + @owner = project&.owner.login + @repo = project&.identifier + @sha = sha + @filepath = filepath + @token = token + end + + def call + raise Error, errors.full_messages.join(",") unless valid? + load_gitea_data + + gitea_data + end + + private + def request_params + { + access_token: token, + sha: sha, + filepath: filepath + } + end + + def load_gitea_data + @gitea_data = $gitea_client.get_repos_blame_by_owner_repo(owner, repo, {query: request_params}) + raise Error, '获取项目blame失败!' unless @gitea_data.is_a?(Hash) + end +end \ No newline at end of file diff --git a/app/services/api/v1/projects/branches/all_list_service.rb b/app/services/api/v1/projects/branches/all_list_service.rb new file mode 100644 index 000000000..182495cdf --- /dev/null +++ b/app/services/api/v1/projects/branches/all_list_service.rb @@ -0,0 +1,30 @@ +class Api::V1::Projects::Branches::AllListService < ApplicationService + + attr_accessor :project, :token, :owner, :repo + attr_accessor :gitea_data + + def initialize(project, token=nil) + @project = project + @owner = project&.owner.login + @repo = project&.identifier + @token = token + end + + def call + load_gitea_data + + gitea_data + end + + private + def request_params + { + access_token: token + } + end + + def load_gitea_data + @gitea_data = $gitea_client.get_repos_branch_name_set_by_owner_repo(owner, repo, {query: request_params}) rescue nil + raise Error, '获取所有分支失败!' unless @gitea_data.is_a?(Hash) + end +end \ No newline at end of file diff --git a/app/services/api/v1/projects/branches/create_service.rb b/app/services/api/v1/projects/branches/create_service.rb new file mode 100644 index 000000000..2837dfcf4 --- /dev/null +++ b/app/services/api/v1/projects/branches/create_service.rb @@ -0,0 +1,51 @@ +class Api::V1::Projects::Branches::CreateService < ApplicationService + include ActiveModel::Model + + attr_accessor :project, :token, :owner, :repo, :old_branch_name, :new_branch_name + attr_accessor :gitea_data + + validates :new_branch_name, :old_branch_name, presence: true + + def initialize(project, params, token=nil) + @project = project + @owner = project&.owner.login + @repo = project&.identifier + @new_branch_name = params[:new_branch_name] + @old_branch_name = params[:old_branch_name] + @token = token + end + + def call + raise Error, errors.full_messages.join(",") unless valid? + + check_new_branch_exist + excute_data_to_gitea + + gitea_data + end + + private + def request_params + { + access_token: token + } + end + + def request_body + { + new_branch_name: new_branch_name, + old_branch_name: old_branch_name, + } + end + + def excute_data_to_gitea + @gitea_data = $gitea_client.post_repos_branches_by_owner_repo(owner, repo, {body: request_body.to_json, query: request_params}) rescue nil + raise Error, '创建分支失败!' unless @gitea_data.is_a?(Hash) + end + + def check_new_branch_exist + result = $gitea_client.get_repos_branch_name_set_by_owner_repo(owner, repo, {query: request_params}) rescue nil + raise Error, '查询分支名称失败!' unless result.is_a?(Hash) + raise Error, '分支已存在!' if result['branch_name'].include?(@new_branch_name) + end +end \ No newline at end of file diff --git a/app/services/api/v1/projects/commits/diff_service.rb b/app/services/api/v1/projects/commits/diff_service.rb new file mode 100644 index 000000000..71dd155a0 --- /dev/null +++ b/app/services/api/v1/projects/commits/diff_service.rb @@ -0,0 +1,36 @@ +class Api::V1::Projects::Commits::DiffService < ApplicationService + include ActiveModel::Model + + attr_accessor :project, :sha, :token, :owner, :repo + attr_accessor :gitea_data + + validates :sha, presence: true + + def initialize(project, sha, token = nil) + @project = project + @sha = sha + @owner = project&.owner.login + @repo = project&.identifier + @token = token + end + + def call + raise Error, errors.full_messages.join(",") unless valid? + load_gitea_data + + gitea_data + end + + private + def request_params + { + access_token: token + } + end + + def load_gitea_data + @gitea_data = $gitea_client.get_repos_commits_diff_by_owner_repo_sha(owner, repo, sha, {query: request_params}) rescue nil + raise Error, '获取提交对比失败!' unless @gitea_data.is_a?(Hash) + end + +end \ No newline at end of file diff --git a/app/services/api/v1/projects/commits/list_service.rb b/app/services/api/v1/projects/commits/list_service.rb new file mode 100644 index 000000000..17818554c --- /dev/null +++ b/app/services/api/v1/projects/commits/list_service.rb @@ -0,0 +1,38 @@ +class Api::V1::Projects::Commits::ListService < ApplicationService + + attr_reader :project, :sha, :page, :limit, :owner, :repo, :token + attr_accessor :gitea_data + + def initialize(project, params, token=nil) + @project = project + @sha = params[:sha] + @page = params[:page] || 1 + @limit = params[:limit] || 15 + @owner = project&.owner.login + @repo = project&.identifier + @token = token + end + + def call + load_gitea_data + + gitea_data + end + + private + def request_params + param = { + access_token: token, + page: page, + limit: limit + } + param.merge!(sha: sha) if sha.present? + + param + end + + def load_gitea_data + @gitea_data = $gitea_client.get_repos_commits_by_owner_repo(owner, repo, {query: request_params}) rescue nil + raise Error, '获取提交列表失败!' unless @gitea_data.is_a?(Hash) + end +end \ No newline at end of file diff --git a/app/services/api/v1/projects/compare_service.rb b/app/services/api/v1/projects/compare_service.rb new file mode 100644 index 000000000..23a248305 --- /dev/null +++ b/app/services/api/v1/projects/compare_service.rb @@ -0,0 +1,34 @@ +class Api::V1::Projects::CompareService < ApplicationService + include ActiveModel::Model + attr_reader :project, :from, :to, :token, :owner, :repo + attr_accessor :gitea_data + + validates :from, :to, presence: true + + def initialize(project, from, to, token=nil) + @project = project + @owner = project&.owner.login + @repo = project&.identifier + @from = from + @to = to + @token = token + end + + def call + raise Error, errors.full_messages.join(",") unless valid? + load_gitea_data + raise Error, '获取对比信息失败!' unless gitea_data.is_a?(Hash) + gitea_data + end + + private + def request_params + { + access_token: token + } + end + + def load_gitea_data + @gitea_data = $gitea_client.get_repos_compare_by_owner_repo_from_to(owner, repo, from, to, {query: request_params}) rescue nil + end +end \ No newline at end of file diff --git a/app/services/api/v1/projects/contents/batch_create_service.rb b/app/services/api/v1/projects/contents/batch_create_service.rb new file mode 100644 index 000000000..d987f9318 --- /dev/null +++ b/app/services/api/v1/projects/contents/batch_create_service.rb @@ -0,0 +1,91 @@ +class Api::V1::Projects::Contents::BatchCreateService < ApplicationService + include ActiveModel::Model + + attr_reader :project, :owner, :repo, :token + attr_reader :files, :author_email, :author_name, :author_timeunix, :branch, :committer_email, :committer_name, :committer_timeunix, :message, :new_branch + attr_accessor :gitea_data + + validates :author_email, :committer_email, presence: true, format: { with: CustomRegexp::EMAIL } + validates :author_name, :committer_name, presence: true, format: { with: /\A(?!_)(?!.*?_$)[a-zA-Z0-9_-]{4,15}\z/ } + validates :author_timeunix, :committer_timeunix, presence: true + validates :branch, presence: true + validates :message, presence: true + + + def initialize(project, params, token=nil) + puts params + @project = project + @owner = project&.owner.login + @repo = project&.identifier + @token = token + @files = params[:files] + @author_email = params[:author_email] + @author_name = params[:author_name] + @author_timeunix = params[:author_timeunix] + @branch = params[:branch] + @committer_email = params[:committer_email] + @committer_name = params[:committer_name] + @committer_timeunix = params[:committer_timeunix] + @message = params[:message] + @new_branch = params[:new_branch] + end + + def call + raise Error, '请输入正确的文件参数Files' unless valid_files? + raise Error, errors.full_messages.join(", ") unless valid? + check_branch_exist + excute_data_to_gitea + + gitea_data + end + + private + def request_params + { + access_token: token + } + end + + def request_body + { + files: files, + header: { + author: { + email: author_email, + name: author_name + }, + committer: { + email: committer_email, + name: committer_name + }, + dates: { + author: Time.at(author_timeunix.to_i), + committer: Time.at(committer_timeunix.to_i) + }, + message: message, + new_branch: new_branch, + signoff: false + } + } + end + + def valid_files? + return false unless files.is_a?(Array) && !files.blank? + files.each do |file| + return false unless file.has_key?(:action_type) && file.has_key?(:content) && file.has_key?(:encoding) && file.has_key?(:file_path) + end + end + + def excute_data_to_gitea + @gitea_data = $gitea_client.post_repos_contents_batch_by_owner_repo(owner, repo, {body: request_body.to_json, query: request_params}) rescue nil + raise Error, '创建文件失败!' unless @gitea_data.is_a?(Hash) + end + + def check_branch_exist + result = $gitea_client.get_repos_branch_name_set_by_owner_repo(owner, repo, {query: request_params} ) rescue nil + raise Error, '查询分支名称失败!' unless result.is_a?(Hash) + raise Error, '分支不存在!' unless result['branch_name'].include?(branch) + raise Error, '分支已存在!' if result['branch_name'].include?(new_branch) && new_branch.nil? + end + +end \ No newline at end of file diff --git a/app/services/api/v1/projects/get_service.rb b/app/services/api/v1/projects/get_service.rb index 1244938ce..ebb0d1cfa 100644 --- a/app/services/api/v1/projects/get_service.rb +++ b/app/services/api/v1/projects/get_service.rb @@ -11,18 +11,20 @@ class Api::V1::Projects::GetService < ApplicationService end def call - $gitea_client.token = token unless token.blank? load_gitea_data load_gitea_branch_tag_count - $gitea_client.token = nil unless token.blank? - result_object rescue raise Error, "服务器错误,请联系系统管理员!" end private + def request_params + { + access_token: token + } + end def result_object { @@ -39,10 +41,10 @@ class Api::V1::Projects::GetService < ApplicationService end def load_gitea_data - @gitea_data = $gitea_client.get_repos_by_owner_repo(owner, repo) + @gitea_data = $gitea_client.get_repos_by_owner_repo(owner, repo, {query: request_params}) rescue nil end def load_gitea_branch_tag_count - @gitea_branch_tag_count = $gitea_client.get_repos_branch_tag_count_by_owner_repo(owner, repo) + @gitea_branch_tag_count = $gitea_client.get_repos_branch_tag_count_by_owner_repo(owner, repo, {query: request_params}) rescue nil end end \ No newline at end of file diff --git a/app/services/api/v1/projects/git/blobs_service.rb b/app/services/api/v1/projects/git/blobs_service.rb new file mode 100644 index 000000000..e2097d933 --- /dev/null +++ b/app/services/api/v1/projects/git/blobs_service.rb @@ -0,0 +1,34 @@ +class Api::V1::Projects::Git::BlobsService < ApplicationService + include ActiveModel::Model + + attr_accessor :project, :sha, :token, :owner, :repo + attr_accessor :gitea_data + + validates :sha, presence: :true + + + def initialize(project, sha, token=nil) + @project = project + @owner = project&.owner.login + @repo = project&.identifier + @sha = sha + @token = token + end + + def call + load_gitea_data + + gitea_data + end + + private + def request_params + { + access_token: token + } + end + + def load_gitea_data + @gitea_data = $gitea_client.get_repos_git_blobs_by_owner_repo_sha(owner, repo, sha, {query: request_params}) rescue nil + end +end \ No newline at end of file diff --git a/app/services/api/v1/projects/git/trees_service.rb b/app/services/api/v1/projects/git/trees_service.rb new file mode 100644 index 000000000..4d6f5d181 --- /dev/null +++ b/app/services/api/v1/projects/git/trees_service.rb @@ -0,0 +1,52 @@ +class Api::V1::Projects::Git::TreesService < ApplicationService + include ActiveModel::Model + + attr_accessor :project, :token, :sha, :recursive, :page, :limit, :owner, :repo + attr_accessor :gitea_data + + validates :sha, presence: :true + validates :recursive, inclusion: {in: [nil, '', true, false]} + + def initialize(project, sha, params, token=nil) + @project = project + @owner = project&.owner.login + @repo = project&.identifier + @token = token + @sha = sha + @recursive = params[:recursive] + @page = params[:page] || 1 + @limit = params[:limit] || 15 + end + + def call + raise Error, errors.full_messages.join(", ") unless valid? + $gitea_client.token = token unless token.blank? + load_gitea_data + + $gitea_client.token = nil unless token.blank? + gitea_data + end + + private + def request_query + if recursive.present? + { + recursive: recursive, + page: page, + per_page: limit, + access_token: token + } + else + { + page: page, + per_page: limit, + access_token: token + } + end + end + + def load_gitea_data + @gitea_data = $gitea_client.get_repos_git_trees_by_owner_repo_sha(owner, repo, sha, {query: request_query}) rescue nil + raise Error, '获取文件树列表失败!' unless @gitea_data.is_a?(Hash) + end +end \ No newline at end of file diff --git a/app/services/api/v1/projects/webhooks/create_service.rb b/app/services/api/v1/projects/webhooks/create_service.rb index 401ff9ff6..bef0a3405 100644 --- a/app/services/api/v1/projects/webhooks/create_service.rb +++ b/app/services/api/v1/projects/webhooks/create_service.rb @@ -26,12 +26,8 @@ class Api::V1::Projects::Webhooks::CreateService < ApplicationService def call raise Error, errors.full_messages.join(",") unless valid? begin - $gitea_client.token = token unless token.blank? - excute_data_to_gitea - $gitea_client.token = nil unless token.blank? - gitea_data rescue raise Error, "服务器错误,请联系系统管理员!" @@ -39,6 +35,12 @@ class Api::V1::Projects::Webhooks::CreateService < ApplicationService end private + def request_params + { + access_token: token + } + end + def request_body { active: active, @@ -55,6 +57,6 @@ class Api::V1::Projects::Webhooks::CreateService < ApplicationService end def excute_data_to_gitea - @gitea_data = $gitea_client.post_repos_hooks_by_owner_repo(owner, repo, {body: request_body.to_json}) + @gitea_data = $gitea_client.post_repos_hooks_by_owner_repo(owner, repo, {body: request_body.to_json, query: request_params}) rescue nil end end \ No newline at end of file diff --git a/app/services/api/v1/projects/webhooks/delete_service.rb b/app/services/api/v1/projects/webhooks/delete_service.rb index 5dd499e6d..8343a5b20 100644 --- a/app/services/api/v1/projects/webhooks/delete_service.rb +++ b/app/services/api/v1/projects/webhooks/delete_service.rb @@ -12,19 +12,21 @@ class Api::V1::Projects::Webhooks::DeleteService < ApplicationService end def call - $gitea_client.token = token unless token.blank? excute_data_to_gitea - $gitea_client.token = nil unless token.blank? - gitea_data rescue raise Error, "服务器错误,请联系系统管理员!" end private + def request_params + { + access_token: token + } + end def excute_data_to_gitea - @gitea_data = $gitea_client.delete_repos_hooks_by_owner_repo_id(owner, repo, id) + @gitea_data = $gitea_client.delete_repos_hooks_by_owner_repo_id(owner, repo, id, {query: request_params}) rescue nil end end \ No newline at end of file diff --git a/app/services/api/v1/projects/webhooks/get_service.rb b/app/services/api/v1/projects/webhooks/get_service.rb index 1ae5c54e2..5c6c79d3e 100644 --- a/app/services/api/v1/projects/webhooks/get_service.rb +++ b/app/services/api/v1/projects/webhooks/get_service.rb @@ -12,10 +12,8 @@ class Api::V1::Projects::Webhooks::GetService < ApplicationService end def call - $gitea_client.token = token unless token.blank? load_gitea_data - $gitea_client.token = nil unless token.blank? gitea_data rescue @@ -23,8 +21,13 @@ class Api::V1::Projects::Webhooks::GetService < ApplicationService end private + def request_params + { + access_token: token + } + end def load_gitea_data - @gitea_data = $gitea_client.get_repos_hooks_by_owner_repo_id(owner, repo, id) + @gitea_data = $gitea_client.get_repos_hooks_by_owner_repo_id(owner, repo, id, {query: request_params}) rescue nil end end \ No newline at end of file diff --git a/app/services/api/v1/projects/webhooks/hooktasks_service.rb b/app/services/api/v1/projects/webhooks/hooktasks_service.rb index 4dd90ee3e..6be9c67c8 100644 --- a/app/services/api/v1/projects/webhooks/hooktasks_service.rb +++ b/app/services/api/v1/projects/webhooks/hooktasks_service.rb @@ -23,8 +23,13 @@ class Api::V1::Projects::Webhooks::ListService < ApplicationService end private + def request_params + { + access_token: token + } + end def load_gitea_data - @gitea_data = $gitea_client.get_repos_hooks_hooktasks_by_owner_repo(owner, repo, id) + @gitea_data = $gitea_client.get_repos_hooks_hooktasks_by_owner_repo(owner, repo, id, {query: request_params}) rescue nil end end \ No newline at end of file diff --git a/app/services/api/v1/projects/webhooks/list_service.rb b/app/services/api/v1/projects/webhooks/list_service.rb index fb746de48..2a76d196c 100644 --- a/app/services/api/v1/projects/webhooks/list_service.rb +++ b/app/services/api/v1/projects/webhooks/list_service.rb @@ -11,19 +11,21 @@ class Api::V1::Projects::Webhooks::ListService < ApplicationService end def call - $gitea_client.token = token unless token.blank? load_gitea_data - $gitea_client.token = nil unless token.blank? - gitea_data rescue raise Error, "服务器错误,请联系系统管理员!" end private + def request_params + { + access_token: token + } + end def load_gitea_data - @gitea_data = $gitea_client.get_repos_hooks_by_owner_repo(owner, repo) + @gitea_data = $gitea_client.get_repos_hooks_by_owner_repo(owner, repo, {query: request_params}) rescue nil end end \ No newline at end of file diff --git a/app/services/api/v1/projects/webhooks/tests_service.rb b/app/services/api/v1/projects/webhooks/tests_service.rb index 3d8b99c97..3f9fe0642 100644 --- a/app/services/api/v1/projects/webhooks/tests_service.rb +++ b/app/services/api/v1/projects/webhooks/tests_service.rb @@ -12,19 +12,21 @@ class Api::V1::Projects::Webhooks::TestsService < ApplicationService end def call - $gitea_client.token = token unless token.blank? excute_data_to_gitea - $gitea_client.token = nil unless token.blank? - gitea_data rescue raise Error, "服务器错误,请联系系统管理员!" end private + def request_params + { + access_token: token + } + end def excute_data_to_gitea - @gitea_data = $gitea_client.post_repos_hooks_tests_by_owner_repo_id(owner, repo, id) + @gitea_data = $gitea_client.post_repos_hooks_tests_by_owner_repo_id(owner, repo, id, {query: request_params}) rescue nil end end \ No newline at end of file diff --git a/app/services/api/v1/projects/webhooks/update_service.rb b/app/services/api/v1/projects/webhooks/update_service.rb index 19ff4f32b..a632d6f2d 100644 --- a/app/services/api/v1/projects/webhooks/update_service.rb +++ b/app/services/api/v1/projects/webhooks/update_service.rb @@ -27,12 +27,8 @@ class Api::V1::Projects::Webhooks::UpdateService < ApplicationService def call raise Error, errors.full_messages.join(",") unless valid? begin - $gitea_client.token = token unless token.blank? - excute_data_to_gitea - $gitea_client.token = nil unless token.blank? - gitea_data rescue raise Error, "服务器错误,请联系系统管理员!" @@ -40,6 +36,12 @@ class Api::V1::Projects::Webhooks::UpdateService < ApplicationService end private + def request_params + { + access_token: token + } + end + def request_body { active: active, @@ -56,6 +58,6 @@ class Api::V1::Projects::Webhooks::UpdateService < ApplicationService end def excute_data_to_gitea - @gitea_data = $gitea_client.patch_repos_hooks_by_owner_repo_id(owner, repo, id, {body: request_body.to_json}) + @gitea_data = $gitea_client.patch_repos_hooks_by_owner_repo_id(owner, repo, id, {body: request_body.to_json, query: request_params}) rescue nil end end \ No newline at end of file diff --git a/app/views/admins/dashboards/index.html.erb b/app/views/admins/dashboards/index.html.erb index e02c307a5..2d86b4b6c 100644 --- a/app/views/admins/dashboards/index.html.erb +++ b/app/views/admins/dashboards/index.html.erb @@ -2,217 +2,57 @@ <% add_admin_breadcrumb('概览', admins_path) %> <% end %> -
-
-
- -
-
-
-
-
-
-
当日活跃用户
- <%= @active_user_count %> -
-
-
- -
-
-
- - - - -
-
-
-
-
-
-
-
-
7天内活跃用户数
- <%= @weekly_active_user_count %> -
-
-
- -
-
-
- - - - -
-
-
-
-
-
-
-
-
30天内活跃用户数
- <%= @month_active_user_count %> -
-
-
- -
-
-
- - - - -
-
-
-
-
-
-
-
-
30天内新增用户数
- <%= @new_user_count %> -
-
-
- -
-
-
- - - - -
-
-
-
-
-
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
指标名称当日数七日内30日内周用户留存率
+ + <%=@active_user_count %><%=@weekly_active_user_count %><%=@month_active_user_count %><%="#{@weekly_keep_rate.to_f * 100 }%" %>
+ + <%=@day_new_user_count %><%=@weekly_new_user_count %><%=@month_new_user_count %><%="--" %>
+ + <%=@day_active_project_count %><%=@weekly_active_project_count %><%=@month_active_project_count %><%="--" %>
+ + <%=@day_new_project_count %><%=@weekly_new_project_count %><%=@month_new_project_count %><%="--" %>
- -
-
-
-
- - - - - - - - -
-
- -
-
-
-
-
30天内新增用户
-
-
-
-
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - <%# 5.times do %> - - - - - - - - - <%# end %> - - - - - - - - - - - - - - - - - - - - - - - - - - - - <%# 5.times do %> - - - - - - - - - - - - - - - - - - - <%# end %> - - - - - - - \ No newline at end of file +
+
\ No newline at end of file diff --git a/app/views/api/v1/projects/_simple_gitea_diff_detail.json.jbuilder b/app/views/api/v1/projects/_simple_gitea_diff_detail.json.jbuilder new file mode 100644 index 000000000..5dff0b89d --- /dev/null +++ b/app/views/api/v1/projects/_simple_gitea_diff_detail.json.jbuilder @@ -0,0 +1,40 @@ +json.file_nums diff['NumFiles'] +json.total_addition diff['TotalAddition'] +json.total_deletion diff['TotalDeletion'] +json.files diff['Files'].each do |file| + json.name file['Name'] + json.oldname file['OldName'] + json.addition file['Addition'] + json.deletion file['Deletion'] + json.type file['Type'] + json.is_created file['IsCreated'] + json.is_deleted file['IsDeleted'] + json.is_bin file['IsBin'] + json.is_lfs_file file['IsLFSFile'] + json.is_renamed file['IsRenamed'] + json.is_ambiguous file['IsAmbiguous'] + json.is_submodule file['IsSubmodule'] + json.sections file['Sections'] do |section| + json.file_name section['FileName'] + json.name section['Name'] + json.lines section['Lines'] do |line| + json.left_index line['LeftIdx'] + json.right_index line['RightIdx'] + json.match line['Match'] + json.type line['Type'] + json.content line['Content'] + unless line['SectionInfo'].blank? + json.section_path line['SectionInfo']['Path'] + json.section_last_left_index line['SectionInfo']['LastLeftIdx'] + json.section_last_right_index line['SectionInfo']['LastRightIdx'] + json.section_left_index line['SectionInfo']['LeftIdx'] + json.section_right_index line['SectionInfo']['RightIdx'] + json.section_left_hunk_size line['SectionInfo']['LeftHunkSize'] + json.section_right_hunk_size line['SectionInfo']['RightHunkSize'] + end + end + end + json.is_incomplete file['IsIncomplete'] + json.is_incomplete_line_too_long file['IsIncompleteLineTooLong'] + json.is_protected file['IsProtected'] +end \ No newline at end of file diff --git a/app/views/api/v1/projects/blame.json.jbuilder b/app/views/api/v1/projects/blame.json.jbuilder new file mode 100644 index 000000000..8dfa6c8a4 --- /dev/null +++ b/app/views/api/v1/projects/blame.json.jbuilder @@ -0,0 +1,22 @@ +json.file_size @result_object['file_size'] +json.file_name @result_object['file_name'] +json.num_lines @result_object['num_lines'] +json.blame_parts @result_object['blame_parts'] do |part| + json.commit do + json.sha part['commit']['id'] + json.author do + json.partial! 'api/v1/users/commit_user', locals: { user: render_cache_commit_author(part['commit']['author']), name: part['commit']['author']['Name'] } + end + + json.committer do + json.partial! 'api/v1/users/commit_user', locals: { user: render_cache_commit_author(part['commit']['commiter']), name: part['commit']['commiter']['Name'] } + end + json.commit_message part['commit']['commit_message'] + json.authored_time render_unix_time(part['commit']['authored_time']) + json.committed_time render_unix_time(part['commit']['committed_time']) + json.created_time render_unix_time(part['commit']['created_time']) + end + json.current_number part['current_number'] + json.effect_line part['effect_line'] + json.lines part['lines'] +end \ No newline at end of file diff --git a/app/views/api/v1/projects/branches/_simple_detail.json.jbuilder b/app/views/api/v1/projects/branches/_simple_detail.json.jbuilder new file mode 100644 index 000000000..b1e407a9b --- /dev/null +++ b/app/views/api/v1/projects/branches/_simple_detail.json.jbuilder @@ -0,0 +1,4 @@ +json.name branch +json.http_url render_http_url(@project) +json.zip_url render_zip_url(@owner, @project.repository, branch) +json.tar_url render_tar_url(@owner, @project.repository, branch) \ No newline at end of file diff --git a/app/views/api/v1/projects/branches/_simple_gitea_detail.json.jbuilder b/app/views/api/v1/projects/branches/_simple_gitea_detail.json.jbuilder new file mode 100644 index 000000000..70fac8238 --- /dev/null +++ b/app/views/api/v1/projects/branches/_simple_gitea_detail.json.jbuilder @@ -0,0 +1,26 @@ +json.name branch['name'] +json.commit do + json.id branch['commit']['id'] + json.message branch['commit']['message'] + json.author do + + json.partial! 'api/v1/users/commit_user', locals: { user: render_cache_commit_author(branch['commit']['author']), name: branch['commit']['author']['name'] } + end + + json.committer do + json.partial! 'api/v1/users/commit_user', locals: { user: render_cache_commit_author(branch['commit']['committer']), name: branch['commit']['committer']['name'] } + end + json.time_ago time_from_now(branch['commit']['timestamp'].to_time) + json.timestamp branch['commit']['timestamp'] +end + +json.protected branch['protected'] +json.user_can_push branch['user_can_push'] +json.user_can_merge branch['user_can_merge'] +json.commit_id branch['commit_id'] +json.commit_time_from_now time_from_now(branch['commit_time'].to_time) +json.commit_time branch['commit_time'] +json.default_branch branch['default_branch'] +json.http_url render_http_url(@project) +json.zip_url render_zip_url(@owner, @project.repository, branch['name']) +json.tar_url render_tar_url(@owner, @project.repository, branch['name']) \ No newline at end of file diff --git a/app/views/api/v1/projects/branches/all.json.jbuilder b/app/views/api/v1/projects/branches/all.json.jbuilder new file mode 100644 index 000000000..d89b1ee16 --- /dev/null +++ b/app/views/api/v1/projects/branches/all.json.jbuilder @@ -0,0 +1,3 @@ +json.array! @result_object["branch_name"] do |branch| + json.partial! "api/v1/projects/branches/simple_detail", branch: branch +end \ No newline at end of file diff --git a/app/views/api/v1/projects/branches/create.json.jbuilder b/app/views/api/v1/projects/branches/create.json.jbuilder new file mode 100644 index 000000000..eed860b81 --- /dev/null +++ b/app/views/api/v1/projects/branches/create.json.jbuilder @@ -0,0 +1 @@ +json.partial! "api/v1/projects/branches/simple_gitea_detail", branch: @result_object diff --git a/app/views/api/v1/projects/commits/_simple_gitea_detail.json.jbuilder b/app/views/api/v1/projects/commits/_simple_gitea_detail.json.jbuilder new file mode 100644 index 000000000..36e3cc160 --- /dev/null +++ b/app/views/api/v1/projects/commits/_simple_gitea_detail.json.jbuilder @@ -0,0 +1,10 @@ +json.sha commit['sha'] +json.author do + json.partial! 'api/v1/users/commit_user', locals: { user: render_cache_commit_author(commit['author']), name: commit['author']['name'] } +end + +json.committer do + json.partial! 'api/v1/users/commit_user', locals: { user: render_cache_commit_author(commit['committer']), name: commit['committer']['name'] } +end +json.commit_message commit['message'] +json.parent_shas commit['parents'].map{|x|x['sha']} \ No newline at end of file diff --git a/app/views/api/v1/projects/commits/diff.json.jbuilder b/app/views/api/v1/projects/commits/diff.json.jbuilder new file mode 100644 index 000000000..8c280b7f5 --- /dev/null +++ b/app/views/api/v1/projects/commits/diff.json.jbuilder @@ -0,0 +1 @@ +json.partial! "api/v1/projects/simple_gitea_diff_detail", diff: @result_object \ No newline at end of file diff --git a/app/views/api/v1/projects/commits/index.json.jbuilder b/app/views/api/v1/projects/commits/index.json.jbuilder new file mode 100644 index 000000000..bd085535c --- /dev/null +++ b/app/views/api/v1/projects/commits/index.json.jbuilder @@ -0,0 +1,17 @@ +json.total_count @result_object[:total_data].to_i +json.commits @result_object[:data].each do |commit| + json.sha commit['sha'] + json.author do + json.partial! 'api/v1/users/commit_user', locals: { user: render_cache_commit_author(commit['commit']['author']), name: commit['commit']['author']['name'] } + end + + json.committer do + json.partial! 'api/v1/users/commit_user', locals: { user: render_cache_commit_author(commit['commit']['committer']), name: commit['commit']['committer']['name'] } + end + json.commit_message commit['commit']['message'] + json.parent_shas commit['parents'].map{|x|x['sha']} + json.files commit['files'].map{|f|f['filename']} + json.commit_date commit['commit_date'] + json.commit_time render_unix_time(commit['commit']['committer']['date']) + json.branch commit['branch'] +end \ No newline at end of file diff --git a/app/views/api/v1/projects/compare.json.jbuilder b/app/views/api/v1/projects/compare.json.jbuilder new file mode 100644 index 000000000..2d20c51e0 --- /dev/null +++ b/app/views/api/v1/projects/compare.json.jbuilder @@ -0,0 +1,18 @@ +json.commits_count @result_object['CommitsCount'] +json.last_commit_sha @result_object['LatestSha'] +json.commits @result_object['Commits'] do |commit| + json.author do + json.partial! 'api/v1/users/commit_user', locals: { user: render_cache_commit_author(commit['Author']), name: commit['Author']['Name'] } + end + + json.committer do + json.partial! 'api/v1/users/commit_user', locals: { user: render_cache_commit_author(commit['Committer']), name: commit['Committer']['Name'] } + end + json.branch commit['Branch'] + json.commit_message commit['CommitMessage'] + json.sha commit['Sha'] + json.parent_shas commit['Sha']['ParentShas'] +end +json.diff do + json.partial! "api/v1/projects/simple_gitea_diff_detail", diff: @result_object['Diff'] +end \ No newline at end of file diff --git a/app/views/api/v1/projects/contents/batch.json.jbuilder b/app/views/api/v1/projects/contents/batch.json.jbuilder new file mode 100644 index 000000000..a9ef08fa6 --- /dev/null +++ b/app/views/api/v1/projects/contents/batch.json.jbuilder @@ -0,0 +1,14 @@ +json.commit do + json.partial! "api/v1/projects/commits/simple_gitea_detail", commit: @result_object['commit'] + json.authored_time render_unix_time(@result_object['commit']['author']['date']) + json.commited_time render_unix_time(@result_object['commit']['committer']['date']) +end +json.contents @result_object['contents'].each do |content| + json.name content['name'] + json.path content['path'] + json.sha content['sha'] + json.type content['type'] + json.size content['size'] + json.encoding content['encoding'] + json.content content['content'] +end \ No newline at end of file diff --git a/app/views/api/v1/projects/git/blobs.json.jbuilder b/app/views/api/v1/projects/git/blobs.json.jbuilder new file mode 100644 index 000000000..e5397e925 --- /dev/null +++ b/app/views/api/v1/projects/git/blobs.json.jbuilder @@ -0,0 +1,4 @@ +json.sha @result_object['sha'] +json.size @result_object['size'] +json.encoding @result_object['encoding'] +json.content @result_object['content'] \ No newline at end of file diff --git a/app/views/api/v1/projects/git/trees.json.jbuilder b/app/views/api/v1/projects/git/trees.json.jbuilder new file mode 100644 index 000000000..0eb08f048 --- /dev/null +++ b/app/views/api/v1/projects/git/trees.json.jbuilder @@ -0,0 +1,9 @@ +json.total_count @result_object['total_count'] +json.sha @result_object['sha'] +json.entries @result_object['tree'].each do |entry| + json.name entry['path'] + json.mode entry['mode'] + json.type entry['type'] === 'blob' ? 'file' : 'dir' + json.size entry['size'] + json.sha entry['sha'] +end \ No newline at end of file diff --git a/app/views/api/v1/users/_commit_user.json.jbuilder b/app/views/api/v1/users/_commit_user.json.jbuilder new file mode 100644 index 000000000..83935709a --- /dev/null +++ b/app/views/api/v1/users/_commit_user.json.jbuilder @@ -0,0 +1,21 @@ +if user.present? + if user.is_a?(Hash) + json.id user["id"] + json.login user["login"] + json.name user["name"] + json.type user["type"] + json.image_url user["avatar_url"] + else + json.id user.id + json.login user.login + json.name user.real_name + json.type user&.type + json.image_url url_to_avatar(user) + end +else + json.id nil + json.login name + json.name name + json.type nil + json.image_url User::Avatar.get_letter_avatar_url(name) +end diff --git a/config/routes/api.rb b/config/routes/api.rb index 32acdabd4..81668804e 100644 --- a/config/routes/api.rb +++ b/config/routes/api.rb @@ -9,7 +9,12 @@ defaults format: :json do scope ':repo' do # projects - resource :projects, path: '/', only: [:show, :update, :edit, :destroy] + resource :projects, path: '/', only: [:show, :update, :edit, :destroy] do + collection do + get :compare + get :blame + end + end # projects文件夹下的 scope module: :projects do @@ -23,6 +28,21 @@ defaults format: :json do get :hooktasks end end + resources :branches, only:[:index, :create] do + collection do + get :all + end + end + resources :commits, only: [:index] + get '/commits/:sha/diff', to: 'commits#diff' + get '/git/blobs/:sha', to: 'git#blobs' + get '/git/trees/:sha', to: 'git#trees' + + resources :contents, only: [:index] do + collection do + post :batch + end + end end end diff --git a/public/docs/api.html b/public/docs/api.html index 21b6d7f41..80b1ebdcb 100644 --- a/public/docs/api.html +++ b/public/docs/api.html @@ -503,7 +503,10 @@ 仓库标签列表
  • - 仓库分支列表 + 仓库所有分支列表 +
  • +
  • + 仓库创建分支
  • 仓库贡献者列表 @@ -535,6 +538,9 @@
  • 获取仓库所有文件
  • +
  • + 提交文件到仓库 +
  • 获取仓库代码目录
  • @@ -545,7 +551,22 @@ 获取仓库README文件
  • - 获取仓库贡献者 + 获取文件树列表 +
  • +
  • + 获取仓库blobs内容 +
  • +
  • + 获取仓库提交列表 +
  • +
  • + 获取单个提交的blame信息 +
  • +
  • + 获取单个文件的blame信息 +
  • +
  • + 获取比较提交blame
  • 获取仓库webhooks列表 @@ -7818,16 +7839,16 @@ http://localhost:3000/api/ceshi1/ceshi_repo1/applied_transfer_projects/organizat } } ] -
  • 仓库分支列表

    -

    仓库分支列表

    +

    仓库所有分支列表

    +

    仓库所有分支列表

    示例:

    -
    curl -X GET http://localhost:3000/api/yystopf/csfjkkj/branches.json
    -
    await octokit.request('GET /api/yystopf/csfjkkj/branches.json')
    +
    curl -X GET http://localhost:3000/api/v1/yystopf/csfjkkj/branches/all.json
    +
    await octokit.request('GET /api/v1/yystopf/csfjkkj/branches/all.json')
     

    HTTP 请求

    -

    GET /api/:owner/:repo/branches.json

    +

    GET /api/v1/:owner/:repo/branches/all.json

    请求参数:

    @@ -7906,16 +7927,19 @@ http://localhost:3000/api/ceshi1/ceshi_repo1/applied_transfer_projects/organizat "tar_url": "http://localhost:3000/api/yystopf/hahahah/archive/touch-100.tar.gz" } ] -

    仓库贡献者列表

    -

    仓库贡献者列表

    +

    仓库创建分支

    +

    为仓库创建一个新的分支

    示例:

    -
    curl -X GET http://localhost:3000/api/yystopf/csfjkkj/contributors.json
    -
    await octokit.request('GET /api/yystopf/csfjkkj/contributors.json')
    +
    curl -X POST \
    +-d "new_branch_name=ceshi_branch_1" \
    +-d "old_branch_name=master" \
    +http://localhost:3000/api/v1/yystopf/csfjkkj/branches.json
    +
    await octokit.request('POST /api/v1/yystopf/csfjkkj/branches.json')
     

    HTTP 请求

    -

    GET /api/:owner/:repo/contributors.json

    +

    POST /api/v1/:owner/:repo/branches.json

    请求参数:

    @@ -7940,6 +7964,20 @@ http://localhost:3000/api/ceshi1/ceshi_repo1/applied_transfer_projects/organizat + + + + + + + + + + + + + +
    string 项目标识identifier
    new_branch_namestring新分支名称
    old_branch_namestring来源分支名称

    返回字段说明:

    @@ -7950,6 +7988,202 @@ http://localhost:3000/api/ceshi1/ceshi_repo1/applied_transfer_projects/organizat + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    namestring分支名称
    commit.idstring提交ID
    commit.messagestring提交信息
    commit.author.idstring提交作者ID
    commit.author.loginstring提交作者标识
    commit.author.namestring提交作者名称
    commit.author.typestring提交作者类型
    commit.committer.idstring提交者ID
    commit.committer.loginstring提交者标识
    commit.committer.namestring提交者名称
    commit.committer.typestring提交者类型
    commit.committer.image_urlstring提交者头像
    commit.time_agostring分支最新提交时间距现在时间差
    commit.timestampstring分支最新提交时间
    protectedbool是否为保护分支
    user_can_pushbool当前用户是否能提交
    user_can_mergebool当前用户是否能合并
    commit_idstring提交ID
    commit_time_from_nowstring分支最新提交时间距现在时间差
    commit_timestring分支最新提交时间
    http_urlstring分支http地址
    zip_urlstring分支zip包下载地址
    tar_urlstring分支tar包下载地址
    + +
    +

    返回的JSON示例:

    +
    +
    {
    +    "name": "new_branch_8",
    +    "commit": {
    +        "id": "80dd40214a58622312393b2ae693756a4781fab2",
    +        "message": "x拟增\n\nSigned-off-by: yystopf <yystopf@163.com>",
    +        "author": {
    +            "id": "2",
    +            "login": "yystopf",
    +            "name": "heh",
    +            "type": "User",
    +            "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
    +        },
    +        "committer": {
    +            "id": "2",
    +            "login": "yystopf",
    +            "name": "heh",
    +            "type": "User",
    +            "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
    +        },
    +        "time_ago": "1天前",
    +        "timestamp": "2022-07-13T09:54:15Z"
    +    },
    +    "protected": false,
    +    "user_can_push": true,
    +    "user_can_merge": true,
    +    "commit_id": "80dd40214a58622312393b2ae693756a4781fab2",
    +    "commit_time_from_now": "1天前",
    +    "commit_time": "2022-07-13T09:54:15Z",
    +    "default_branch": "master",
    +    "http_url": "http://127.0.0.1:10081/yystopf/ceshi_hook.git",
    +    "zip_url": "http://localhost:3000/api/yystopf/ceshi_hook/archive/new_branch_8.zip",
    +    "tar_url": "http://localhost:3000/api/yystopf/ceshi_hook/archive/new_branch_8.tar.gz"
    +}
    +

    仓库贡献者列表

    +

    仓库贡献者列表

    + +
    +

    示例:

    +
    +
    curl -X GET http://localhost:3000/api/yystopf/csfjkkj/contributors.json
    +
    await octokit.request('GET /api/yystopf/csfjkkj/contributors.json')
    +

    HTTP 请求

    +

    GET /api/:owner/:repo/contributors.json

    +

    请求参数:

    + + + + + + + + + + + + + + + + + + + + + + + +
    参数必选默认类型字段说明
    ownerstring用户登录名
    repostring项目标识identifier
    +

    返回字段说明:

    + + + + + + + + @@ -8006,9 +8240,9 @@ http://localhost:3000/api/ceshi1/ceshi_repo1/applied_transfer_projects/organizat
    curl -X GET http://localhost:3000/api/yystopf/csfjkkj/languages.json
     
    await octokit.request('GET /api/yystopf/csfjkkj/languages.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/:owner/:repo/languages.json

    -

    请求参数:

    +

    请求参数:

    参数类型字段说明
    list.contributions int 贡献者commit数量
    @@ -8033,7 +8267,7 @@ http://localhost:3000/api/ceshi1/ceshi_repo1/applied_transfer_projects/organizat
    参数项目标识identifier
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -8070,9 +8304,9 @@ http://localhost:3000/api/ceshi1/ceshi_repo1/applied_transfer_projects/organizat
    curl -X GET http://localhost:3000/api/jasder/jasder_test/edit.json
     
    await octokit.request('GET /api/jasder/jasder_test/edit.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/:owner/:repo/edit.json

    -

    请求参数:

    +

    请求参数:

    参数
    @@ -8097,7 +8331,7 @@ http://localhost:3000/api/ceshi1/ceshi_repo1/applied_transfer_projects/organizat
    参数项目标识identifier
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -8174,9 +8408,9 @@ http://localhost:3000/api/ceshi1/ceshi_repo1/applied_transfer_projects/organizat -d"private=true"\ http://localhost:3000/api/jasder/jasder_test.json
    await octokit.request('PATCH /api/jasder/jasder_test.json')
    -

    HTTP 请求

    +

    HTTP 请求

    PATCH /api/:owner/:repo

    -

    请求参数:

    +

    请求参数:

    参数
    @@ -8236,7 +8470,7 @@ http://localhost:3000/api/jasder/jasder_test.json
    参数项目是否私有, true:为私有,false: 公开,默认为公开
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -8301,9 +8535,9 @@ http://localhost:3000/api/jasder/jasder_test.json
    curl -X DELETE http://localhost:3000/api/jasder/jasder_test.json
     
    await octokit.request('DELETE /api/jasder/jasder_test.json')
    -

    HTTP 请求

    +

    HTTP 请求

    PATCH /api/:owner/:repo

    -

    请求参数:

    +

    请求参数:

    参数
    @@ -8328,7 +8562,7 @@ http://localhost:3000/api/jasder/jasder_test.json
    参数项目标识identifier
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -8369,83 +8603,8 @@ http://localhost:3000/api/jasder/jasder_test.json -d"user_id=12"\ http://localhost:3000/api/jasder/jasder_test/collaborators.json
    await octokit.request('POST /api/jasder/jasder_test/collaborators.json')
    -

    HTTP 请求

    -

    POST /api/:owner/:repo/collaborators.json

    -

    请求参数:

    -
    参数
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    参数必选默认类型字段说明
    ownerstring用户登录名
    repostring项目标识identifier
    user_idint用户id
    -

    返回字段说明:

    - - - - - - - - - - - - - - - - - -
    参数类型字段说明
    statusint返回状态, 0: 表示操作成功
    messagestring返回信息说明
    - -
    -

    返回的JSON示例:

    -
    -
    {
    -  "status": 0,
    -  "message": "success"
    -}
    -
    - -

    删除仓库成员

    -

    仓库中删除成员操作

    - -
    -

    示例:

    -
    -
    curl -X DELETE \
    --d "user_id=12" \
    -http://localhost:3000/api/jasder/jasder_test/collaborators.json
    -
    await octokit.request('DELETE /api/jasder/jasder_test/collaborators.json')
     

    HTTP 请求

    -

    DELETE /api/:owner/:repo/collaborators.json

    +

    POST /api/:owner/:repo/collaborators.json

    请求参数:

    @@ -8498,6 +8657,81 @@ http://localhost:3000/api/jasder/jasder_test/collaborators.json
    +
    +

    返回的JSON示例:

    +
    +
    {
    +  "status": 0,
    +  "message": "success"
    +}
    +
    + +

    删除仓库成员

    +

    仓库中删除成员操作

    + +
    +

    示例:

    +
    +
    curl -X DELETE \
    +-d "user_id=12" \
    +http://localhost:3000/api/jasder/jasder_test/collaborators.json
    +
    await octokit.request('DELETE /api/jasder/jasder_test/collaborators.json')
    +

    HTTP 请求

    +

    DELETE /api/:owner/:repo/collaborators.json

    +

    请求参数:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数必选默认类型字段说明
    ownerstring用户登录名
    repostring项目标识identifier
    user_idint用户id
    +

    返回字段说明:

    + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    statusint返回状态, 0: 表示操作成功
    messagestring返回信息说明
    +

    返回的JSON示例:

    @@ -8520,9 +8754,9 @@ http://localhost:3000/api/jasder/jasder_test/collaborators.json -d "role=Developer" \ http://localhost:3000/api/jasder/jasder_test/change_role.json
    await octokit.request('PUT /api/jasder/jasder_test/change_role.json')
    -

    HTTP 请求

    +

    HTTP 请求

    PUT /api/:owner/:repo/change_role.json

    -

    请求参数:

    +

    请求参数:

    @@ -8561,7 +8795,7 @@ http://localhost:3000/api/jasder/jasder_test/change_role.json
    参数取值范围:"Manager", "Developer", "Reporter";分别为项目管理人员(拥有所有操作权限)、项目开发人员(只拥有读写权限)、项目报告人员(只拥有读权限)
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -8603,9 +8837,9 @@ http://localhost:3000/api/jasder/jasder_test/change_role.json -d"limit=5"\ http://localhost:3000/api/jasder/jasder_test/collaborators.json
    await octokit.request('GET /api/jasder/jasder_test/collaborators.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/:owner/:repo/collaborators.json

    -

    请求参数:

    +

    请求参数:

    参数
    @@ -8644,7 +8878,7 @@ http://localhost:3000/api/jasder/jasder_test/collaborators.json
    参数每页多少条数据,默认15条
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -8732,9 +8966,9 @@ http://localhost:3000/api/jasder/jasder_test/collaborators.json -d"ref=develop"\ http://localhost:3000/api/yystopf/ceshi/files.json
    await octokit.request('GET /api/yystopf/ceshi/files.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/:owner/:repo/files

    -

    请求参数:

    +

    请求参数:

    参数
    @@ -8773,7 +9007,7 @@ http://localhost:3000/api/yystopf/ceshi/files.json
    参数分支名,默认为仓库默认分支
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -8845,6 +9079,292 @@ http://localhost:3000/api/yystopf/ceshi/files.json "html_url": "http://localhost:10080/yystopf/ceshi/src/branch/master/README.md" } ] +

    提交文件到仓库

    +

    提交文件到仓库,支持批量

    + +
    +

    示例:

    +
    +
    curl -X POST \
    +-d "files[][action_type]=create" \
    +-d "files[][content]=jfksj" \
    +-d "files[][encoding]=text" \
    +-d "files[][file_path]=heihei8" \
    +-d "author_email=yystopf@163.com" \
    +-d "author_name=yystopf" \
    +-d "author_timeunix=1658214400" \
    +-d "committer_email=yystopf@163.com" \
    +-d "committer_name=yystopf" \
    +-d "committer_timeunix=1658214400" \
    +-d "branch=develop" \
    +-d "new_branch=develop_ceshi" \
    +-d "message=测试提交" \
    +http://localhost:3000/api/v1/yystopf/ceshi/contents/batch.json
    +
    await octokit.request('POST /api/v1/yystopf/ceshi/contents/batch.json')
    +

    HTTP 请求

    +

    POST /api/v1/:owner/:repo/contents/batch

    +

    请求参数:

    +
    参数
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数必选默认类型字段说明
    ownerstring用户登录名
    repostring项目标识identifier
    files.action_typestring操作类型 create: 创建 update: 更新 delete: 删除
    files.contentstring文件内容
    files.encodingstring文件编码方式 text 文本 base64 加密
    files.file_pathstring文件路径
    author_emailstring作者邮箱
    author_namestring作者名称
    author_timeunixint编码时间,精确到秒
    committer_emailstring提交者邮箱
    committer_namestring提交者名称
    committer_timeunixint提交时间戳,精确到秒
    branchstring提交分支
    new_branchstring如果需要创建新分支,这个需要填
    messagestring提交信息
    + +
    +

    请求的JSON示例:

    +
    +
    {
    +    "files": [
    +        {
    +            "action_type": "create",
    +            "content": "jfksj",
    +            "encoding": "text",
    +            "file_path": "heihei7"
    +        }
    +    ],
    +    "author_email": "yystopf@163.com",
    +    "author_name": "yystopf",
    +    "author_timeunix": 1658214400,
    +    "committer_email": "yystopf@163.com",
    +    "committer_name": "yystopf",
    +    "committer_timeunix": 1658214400,
    +    "branch": "hh_ceshi",
    +    "message": "测试提交"
    +}
    +

    返回字段说明:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    commit.shastring提交ID
    commit.authorobject作者
    commit.committerobject提交者
    commit.commit_messagestring提交信息
    commit.parent_shasarray父节点commit ID
    commit.authored_timeint编码时间
    commit.commited_timeint提交时间
    contents.namestring文件名称
    contents.pathstring文件路径
    contents.shastring文件标识
    contents.typestring文件类型
    contents.sizeint文件大小
    contents.urlstring文件地址
    contents.encodingstring编码类型 text 文本 base64 加密
    contents.contentstring文件内容
    + +
    +

    返回的JSON示例:

    +
    +
    {
    +    "commit": {
    +        "sha": "7c1e25f9b974e4b7a3816bd7f5e49b441078e999",
    +        "author": {
    +            "id": "2",
    +            "login": "yystopf",
    +            "name": "heh",
    +            "type": "User",
    +            "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
    +        },
    +        "committer": {
    +            "id": "2",
    +            "login": "yystopf",
    +            "name": "heh",
    +            "type": "User",
    +            "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
    +        },
    +        "commit_message": "测试提交\n",
    +        "parent_shas": [
    +            "9aec816d0f3600082ca77893290a14bd29d805fe"
    +        ],
    +        "authored_time": 1658214400,
    +        "commited_time": 1658214400
    +    },
    +    "contents": [
    +        {
    +            "name": "heihei7",
    +            "path": "heihei7",
    +            "sha": "f0acac8efb3021b0f6a7b13b42d033d86e076a4b",
    +            "type": "file",
    +            "size": 5,
    +            "encoding": "base64",
    +            "content": "amZrc2o="
    +        }
    +    ]
    +}
     

    获取仓库代码目录

    获取仓库代码目录

    @@ -8855,9 +9375,9 @@ http://localhost:3000/api/yystopf/ceshi/files.json -d "ref=develop" \ http://localhost:3000//api/jasder/jasder_test/entries.json
    await octokit.request('GET /api/jasder/jasder_test/entries.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/:owner/:repo/entries.json

    -

    请求参数:

    +

    请求参数:

    @@ -8889,7 +9409,7 @@ http://localhost:3000//api/jasder/jasder_test/entries.json
    参数分支名称、tag名称或是提交记录id,默认为master分支
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -9003,9 +9523,9 @@ http://localhost:3000//api/jasder/jasder_test/entries.json -d"filepath=file"\ http://localhost:3000//api/jasder/jasder_test/sub_entries.json
    await octokit.request('GET /api/jasder/jasder_test/sub_entries.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/:owner/:repo/sub_entries.json

    -

    请求参数:

    +

    请求参数:

    参数
    @@ -9044,7 +9564,7 @@ http://localhost:3000//api/jasder/jasder_test/sub_entries.json
    参数分支名称、tag名称或是提交记录id,默认为master分支
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -9141,9 +9661,9 @@ http://localhost:3000//api/jasder/jasder_test/sub_entries.json -d"filepath=lib"\ http://localhost:3000/api/yystopf/csfjkkj/readme.json
    await octokit.request('GET /api/yystopf/csfjkkj/readme.json')
    -

    HTTP 请求

    +

    HTTP 请求

    GET /api/:owner/:repo/readme.json

    -

    请求参数:

    +

    请求参数:

    参数
    @@ -9182,7 +9702,7 @@ http://localhost:3000/api/yystopf/csfjkkj/readme.json
    参数子目录名称,默认为空
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -9243,20 +9763,21 @@ http://localhost:3000/api/yystopf/csfjkkj/readme.json -

    获取仓库贡献者

    -

    获取仓库贡献者

    +

    获取文件树列表

    +

    根据分支、标签、commit ID获取仓库文件树列表

    示例:

    curl -X GET \
    --d "ref=master" \
    --d "filepath=lib" \
    -http://localhost:3000/api/yystopf/csfjkkj/contributors.json
    -
    await octokit.request('GET /api/yystopf/csfjkkj/contributors.json')
    -

    HTTP 请求

    -

    GET /api/:owner/:repo/contributors.json

    -

    请求参数:

    +-d"recursive=true"\ +-d"page=1"\ +-d"limit=1"\ +http://localhost:3000/api/v1/yystopf/csfjkkj/git/trees/80dd40214a58622312393b2ae693756a4781fab2.json +
    await octokit.request('GET /api/v1/yystopf/csfjkkj/git/trees/80dd40214a58622312393b2ae693756a4781fab2.json')
    +

    HTTP 请求

    +

    GET /api/v1/:owner/:repo/git/trees/:sha.json

    +

    请求参数:

    参数
    @@ -9281,21 +9802,35 @@ http://localhost:3000/api/yystopf/csfjkkj/contributors.json - - + + - + - + - - + + + + + + + + + + + + + + + +
    参数项目标识identifier
    refsha string分支名称、tag名称或是提交记录id,默认为整个仓库分支名称、tag名称或是提交记录id
    filepathrecursive string子目录名称,默认为空bool是否显示目录
    page1int页码
    limit15int分页个数
    -

    返回字段说明:

    +

    返回字段说明:

    @@ -9305,33 +9840,38 @@ http://localhost:3000/api/yystopf/csfjkkj/contributors.json - - + + - - - - - - + - + - + - + - + - + - + - + + + + + + + + + + +
    参数
    total_countinteger贡献者数量int文件树数量
    contributionsinteger贡献数量
    loginsha string用户登录名查询分支、标签、commit_id最后一次提交的ID
    typeentries.name string用户类型文件树名称
    nameentries.mode string用户昵称文件树权限
    image_urlentries.type string用户头像文件树类型, file:文件,dir: 文件夹
    entries.sizeint文件树大小
    entries.shastring文件树commit_ID
    @@ -9339,23 +9879,1103 @@ http://localhost:3000/api/yystopf/csfjkkj/contributors.json

    返回的JSON示例:

    {
    -    "contributors": [
    +    "total_count": 13,
    +    "sha": "80dd40214a58622312393b2ae693756a4781fab2",
    +    "entries": [
             {
    -            "contributions": 5,
    -            "login": "testforge2",
    -            "type": "User",
    -            "name": "testforge2",
    -            "image_url": "system/lets/letter_avatars/2/T/236_177_85/120.png"
    +            "name": "README.md",
    +            "mode": "100644",
    +            "type": "file",
    +            "size": 14,
    +            "sha": "b2f7b457fd8ca55f2274032cbb2abcb7dd8cd57e"
    +        }
    +    ]
    +}
    +
    + +

    获取仓库blobs内容

    +

    根据commit ID获取仓库blobs内容

    + +
    +

    示例:

    +
    +
    curl -X GET http://localhost:3000/api/v1/yystopf/csfjkkj/git/blobs/80dd40214a58622312393b2ae693756a4781fab2.json
    +
    await octokit.request('GET /api/v1/yystopf/csfjkkj/git/blobs/80dd40214a58622312393b2ae693756a4781fab2.json')
    +

    HTTP 请求

    +

    GET /api/v1/:owner/:repo/git/blobs/:sha.json

    +

    请求参数:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数必选默认类型字段说明
    ownerstring用户登录名
    repostring项目标识identifier
    shastring提交记录id
    +

    返回字段说明:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    shastring提交ID
    sizeintblobs大小
    encodingstring内容编码模式
    contentstringblobs内容
    + +
    +

    返回的JSON示例:

    +
    +
    {
    +    "sha": "80dd40214a58622312393b2ae693756a4781fab2",
    +    "size": 247,
    +    "encoding": "base64",
    +    "content": "dHJlZSAyN2JjYjI2ZDQ5YmU1M2RmOGZmYTk5NDc3MjRkYmI3YzIzZWI4MjY4CnBhcmVudCA3ZTRkOGJiM2MyOGUyNGQ0Y2Q2YjIwNWYyZWVkMzI1MTNlOTM3NTI0CmF1dGhvciB5eXN0b3BmIDx5eXN0b3BmQDE2My5jb20+IDE2NTc3MDYwNTUgKzAwMDAKY29tbWl0dGVyIHl5c3RvcGYgPHl5c3RvcGZAMTYzLmNvbT4gMTY1NzcwNjA1NSArMDAwMAoKeOaLn+WingoKU2lnbmVkLW9mZi1ieTogeXlzdG9wZiA8eXlzdG9wZkAxNjMuY29tPg=="
    +}
    +
    + +

    获取仓库提交列表

    +

    根据分支名、标签、commit ID来获取提交列表

    + +
    +

    示例:

    +
    +
    curl -X GET \
    +-d "sha=master" \
    +-d "page=1" \
    +-d "limit=1" \
    +http://localhost:3000/api/v1/yystopf/csfjkkj/commits.json
    +
    await octokit.request('GET /api/v1/yystopf/csfjkkj/commits.json')
    +

    HTTP 请求

    +

    GET /api/v1/:owner/:repo/commits.json

    +

    请求参数:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数必选默认类型字段说明
    ownerstring用户登录名
    repostring项目标识identifier
    shastring分支名、标签名或Commit ID
    pageint页码
    limitint每页数量
    +

    返回字段说明:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    total_countint提交总数
    commits.shastring提交ID
    commits.authorobject提交作者
    commits.committerobject提交者
    commits.commit_messagestring提交信息
    commits.parent_shasarray提交父节点ID
    commits.filesarray提交文件
    commits.commit_datestring提交日期
    commits.commit_timestring提交时间
    commits.branchstring提交分支
    + +
    +

    返回的JSON示例:

    +
    +
    {
    +    "total_count": 12,
    +    "commits": [
    +        {
    +            "sha": "86c62a1e91c07b58b8aa6c89b94856d89c0f7e55",
    +            "author": {
    +                "id": null,
    +                "login": "viletyy",
    +                "name": "viletyy",
    +                "type": null,
    +                "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png"
    +            },
    +            "committer": {
    +                "id": null,
    +                "login": "viletyy",
    +                "name": "viletyy",
    +                "type": null,
    +                "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png"
    +            },
    +            "commit_message": "fix\n",
    +            "parent_shas": [
    +                "411e4d259785241f1bd14faf99ca24fd1b802f2a"
    +            ],
    +            "files": [
    +                "hd.txt"
    +            ],
    +            "commit_date": "2022-07-05",
    +            "commit_time": "2022-07-05 11:00:45",
    +            "branch": "hh_ceshi"
    +        }
    +    ]
    +}
    +
    + +

    获取单个提交的blame信息

    +

    根据commit ID获取blame信息

    + +
    +

    示例:

    +
    +
    curl -X GET http://localhost:3000/api/v1/yystopf/csfjkkj/commits/80dd40214a58622312393b2ae693756a4781fab2/diff.json
    +
    await octokit.request('GET /api/v1/yystopf/csfjkkj/commits/80dd40214a58622312393b2ae693756a4781fab2/diff.json')
    +

    HTTP 请求

    +

    GET /api/v1/:owner/:repo/commits/:sha/diff.json

    +

    请求参数:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数必选默认类型字段说明
    ownerstring用户登录名
    repostring项目标识identifier
    shastring提交记录id
    +

    返回字段说明:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    file_numsint文件数量
    total_additionint新增行数
    total_deletionint删除行数
    files.namestring文件名称
    files.oldnamestring文件修改前名称
    files.additionint文件新增行数
    files.deletionint文件删除行数
    files.typeint文件类型 1: 新增 2: 更改 3: 删除 4: 重命名 5: 复制
    files.is_createdbool是否为新建文件
    files.is_deletedbool是否为删除文件
    files.is_binbool是否为二进制文件
    files.is_lfs_filebool
    files.is_renamedbool是否重命名
    files.is_ambiguousbool
    files.is_submodulebool是否为子模块
    files.sections.file_namestring文件名称
    files.sections.namestring
    files.sections.lines.left_indexint
    files.sections.lines.right_indexint
    files.sections.lines.matchint
    files.sections.lines.typeint
    files.sections.lines.contentstring
    files.sections.lines.section_pathstring
    files.sections.lines.section_last_left_indexint
    files.sections.lines.section_last_right_indexint
    files.sections.lines.section_left_indexint
    files.sections.lines.section_right_indexint
    files.sections.lines.section_left_hunk_sizeint
    files.sections.lines.section_right_hunk_sizeint
    + +
    +

    返回的JSON示例:

    +
    +
    {
    +    "file_nums": 1,
    +    "total_addition": 1,
    +    "total_deletion": 0,
    +    "files": [
    +        {
    +            "name": "xinzeng3",
    +            "oldname": "xinzeng3",
    +            "addition": 1,
    +            "deletion": 0,
    +            "type": 1,
    +            "is_created": true,
    +            "is_deleted": false,
    +            "is_bin": false,
    +            "is_lfs_file": false,
    +            "is_renamed": false,
    +            "is_ambiguous": false,
    +            "is_submodule": false,
    +            "sections": [
    +                {
    +                    "file_name": "xinzeng3",
    +                    "name": "",
    +                    "lines": [
    +                        {
    +                            "left_index": 0,
    +                            "right_index": 0,
    +                            "match": 0,
    +                            "type": 4,
    +                            "content": "@@ -0,0 +1 @@",
    +                            "section_path": "xinzeng3",
    +                            "section_last_left_index": 0,
    +                            "section_last_right_index": 0,
    +                            "section_left_index": 0,
    +                            "section_right_index": 1,
    +                            "section_left_hunk_size": 0,
    +                            "section_right_hunk_size": 0
    +                        },
    +                        {
    +                            "left_index": 0,
    +                            "right_index": 1,
    +                            "match": -1,
    +                            "type": 2,
    +                            "content": "+1111122222"
    +                        }
    +                    ]
    +                }
    +            ],
    +            "is_incomplete": false,
    +            "is_incomplete_line_too_long": false,
    +            "is_protected": false
    +        }
    +    ]
    +}
    +
    + +

    获取单个文件的blame信息

    +

    根据分支、标签、commitID获取某个文件的blame信息

    + +
    +

    示例:

    +
    +
    curl -X GET \
    +-d "sha=master" \
    +-d "filepath=hd.txt" \
    +http://localhost:3000/api/v1/yystopf/csfjkkj/blame.json
    +
    await octokit.request('GET /api/v1/yystopf/csfjkkj/blame.json')
    +

    HTTP 请求

    +

    GET /api/v1/:owner/:repo/blame.json

    +

    请求参数:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数必选默认类型字段说明
    ownerstring用户登录名
    repostring项目标识identifier
    shastring分支、标签或提交记录id
    filepathstring文件路径
    +

    返回字段说明:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    file_sizeint文件大小
    file_namestring文件名称
    num_linesint文件总行数
    blame_parts.commitobject提交
    blame_parts.current_numberint当前行数
    blame_parts.effect_lineint影响的行数
    blame_parts.linesarray行内容
    + +
    +

    返回的JSON示例:

    +
    +
    {
    +    "file_size": 32,
    +    "file_name": "hd.txt",
    +    "num_lines": 12,
    +    "blame_parts": [
    +        {
    +            "commit": {
    +                "sha": "40f76e80bf5bc41fcc94c28ca8a6eab506c15215",
    +                "author": {
    +                    "id": null,
    +                    "login": "viletyy",
    +                    "name": "viletyy",
    +                    "type": null,
    +                    "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png"
    +                },
    +                "committer": {
    +                    "id": null,
    +                    "login": "viletyy",
    +                    "name": "viletyy",
    +                    "type": null,
    +                    "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png"
    +                },
    +                "commit_message": "fix\n",
    +                "authored_time": "2022-07-04 18:41:25",
    +                "committed_time": "2022-07-04 18:41:25",
    +                "created_time": "2022-07-04 18:41:25"
    +            },
    +            "current_number": 1,
    +            "effect_line": 5,
    +            "lines": [
    +                "dkfj",
    +                "s",
    +                "324",
    +                "234",
    +                "2"
    +            ]
             },
             {
    -            "contributions": 79,
    -            "login": "yystopf",
    -            "type": "User",
    -            "name": "yystopf",
    -            "image_url": "system/lets/letter_avatars/2/Y/241_125_89/120.png"
    +            "commit": {
    +                "sha": "86c62a1e91c07b58b8aa6c89b94856d89c0f7e55",
    +                "author": {
    +                    "id": null,
    +                    "login": "viletyy",
    +                    "name": "viletyy",
    +                    "type": null,
    +                    "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png"
    +                },
    +                "committer": {
    +                    "id": null,
    +                    "login": "viletyy",
    +                    "name": "viletyy",
    +                    "type": null,
    +                    "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png"
    +                },
    +                "commit_message": "fix\n",
    +                "authored_time": "2022-07-05 11:00:45",
    +                "committed_time": "2022-07-05 11:00:45",
    +                "created_time": "2022-07-05 11:00:45"
    +            },
    +            "current_number": 6,
    +            "effect_line": 1,
    +            "lines": [
    +                "dd"
    +            ]
    +        },
    +        {
    +            "commit": {
    +                "sha": "40f76e80bf5bc41fcc94c28ca8a6eab506c15215",
    +                "author": {
    +                    "id": null,
    +                    "login": "viletyy",
    +                    "name": "viletyy",
    +                    "type": null,
    +                    "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png"
    +                },
    +                "committer": {
    +                    "id": null,
    +                    "login": "viletyy",
    +                    "name": "viletyy",
    +                    "type": null,
    +                    "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png"
    +                },
    +                "commit_message": "fix\n",
    +                "authored_time": "2022-07-04 18:41:25",
    +                "committed_time": "2022-07-04 18:41:25",
    +                "created_time": "2022-07-04 18:41:25"
    +            },
    +            "current_number": 7,
    +            "effect_line": 3,
    +            "lines": [
    +                "23",
    +                "4",
    +                "23"
    +            ]
    +        },
    +        {
    +            "commit": {
    +                "sha": "86c62a1e91c07b58b8aa6c89b94856d89c0f7e55",
    +                "author": {
    +                    "id": null,
    +                    "login": "viletyy",
    +                    "name": "viletyy",
    +                    "type": null,
    +                    "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png"
    +                },
    +                "committer": {
    +                    "id": null,
    +                    "login": "viletyy",
    +                    "name": "viletyy",
    +                    "type": null,
    +                    "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png"
    +                },
    +                "commit_message": "fix\n",
    +                "authored_time": "2022-07-05 11:00:45",
    +                "committed_time": "2022-07-05 11:00:45",
    +                "created_time": "2022-07-05 11:00:45"
    +            },
    +            "current_number": 10,
    +            "effect_line": 1,
    +            "lines": [
    +                "s1"
    +            ]
    +        },
    +        {
    +            "commit": {
    +                "sha": "40f76e80bf5bc41fcc94c28ca8a6eab506c15215",
    +                "author": {
    +                    "id": null,
    +                    "login": "viletyy",
    +                    "name": "viletyy",
    +                    "type": null,
    +                    "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png"
    +                },
    +                "committer": {
    +                    "id": null,
    +                    "login": "viletyy",
    +                    "name": "viletyy",
    +                    "type": null,
    +                    "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png"
    +                },
    +                "commit_message": "fix\n",
    +                "authored_time": "2022-07-04 18:41:25",
    +                "committed_time": "2022-07-04 18:41:25",
    +                "created_time": "2022-07-04 18:41:25"
    +            },
    +            "current_number": 11,
    +            "effect_line": 1,
    +            "lines": [
    +                ""
    +            ]
    +        }
    +    ]
    +}
    +
    + +

    获取比较提交blame

    +

    根据分支名、标签、commit ID来获取代码对比blame

    + +
    +

    示例:

    +
    +
    curl -X GET \
    +-d "from=hh_ceshi" \
    +-d "to=master" \
    +http://localhost:3000/api/v1/yystopf/csfjkkj/compare.json
    +
    await octokit.request('GET /api/v1/yystopf/csfjkkj/compare.json')
    +

    HTTP 请求

    +

    GET /api/v1/:owner/:repo/compare.json

    +

    请求参数:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数必选默认类型字段说明
    ownerstring用户登录名
    repostring项目标识identifier
    fromstring源分支、标签、commitID
    tostring目标分支、标签、commitID
    +

    返回字段说明:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    commits_countint提交数量
    commits.branchstring提交分支
    commits.authorobject提交作者
    commits.committerobject提交者
    commits.commit_messagestring提交信息
    commits.shastring提交ID
    commits.parent_shasarray提交父节点ID
    diff.file_numsint文件数量
    diff.total_additionint新增行数
    diff.total_deletionint删除行数
    diff.files.namestring文件名称
    diff.files.oldnamestring文件修改前名称
    diff.files.additionint文件新增行数
    diff.files.deletionint文件删除行数
    diff.files.typeint文件类型 1: 新增 2: 更改 3: 删除 4: 重命名 5: 复制
    diff.files.is_createdbool是否为新建文件
    diff.files.is_deletedbool是否为删除文件
    diff.files.is_binbool是否为二进制文件
    diff.files.is_lfs_filebool
    diff.files.is_renamedbool是否重命名
    diff.files.is_ambiguousbool
    diff.files.is_submodulebool是否为子模块
    diff.files.sections.file_namestring文件名称
    diff.files.sections.namestring
    diff.files.sections.lines.left_indexint
    diff.files.sections.lines.right_indexint
    diff.files.sections.lines.matchint
    diff.files.sections.lines.typeint
    diff.files.sections.lines.contentstring
    diff.files.sections.lines.section_pathstring
    diff.files.sections.lines.section_last_left_indexint
    diff.files.sections.lines.section_last_right_indexint
    diff.files.sections.lines.section_left_indexint
    diff.files.sections.lines.section_right_indexint
    diff.files.sections.lines.section_left_hunk_sizeint
    diff.files.sections.lines.section_right_hunk_sizeint
    + +
    +

    返回的JSON示例:

    +
    +
    {
    +    "commits_count": 1,
    +    "last_commit_sha": "80dd40214a58622312393b2ae693756a4781fab2",
    +    "commits": [
    +        {
    +            "author": {
    +                "id": "2",
    +                "login": "yystopf",
    +                "name": "heh",
    +                "type": "User",
    +                "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
    +            },
    +            "committer": {
    +                "id": "2",
    +                "login": "yystopf",
    +                "name": "heh",
    +                "type": "User",
    +                "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
    +            },
    +            "branch": "",
    +            "commit_message": "x拟增\n\nSigned-off-by: yystopf <yystopf@163.com>",
    +            "sha": "7e4d8bb3c28e24d4cd6b205f2eed32513e937524",
    +            "parent_shas": null
             }
         ],
    -    "total_count": 2
    +    "diff": {
    +        "file_nums": 1,
    +        "total_addition": 1,
    +        "total_deletion": 0,
    +        "files": [
    +            {
    +                "name": "ceshi123",
    +                "oldname": "ceshi123",
    +                "addition": 1,
    +                "deletion": 0,
    +                "type": 1,
    +                "is_created": true,
    +                "is_deleted": false,
    +                "is_bin": false,
    +                "is_lfs_file": false,
    +                "is_renamed": false,
    +                "is_ambiguous": false,
    +                "is_submodule": false,
    +                "sections": [
    +                    {
    +                        "file_name": "ceshi123",
    +                        "name": "",
    +                        "lines": [
    +                            {
    +                                "left_index": 0,
    +                                "right_index": 0,
    +                                "match": 0,
    +                                "type": 4,
    +                                "content": "@@ -0,0 +1 @@",
    +                                "section_path": "ceshi123",
    +                                "section_last_left_index": 0,
    +                                "section_last_right_index": 0,
    +                                "section_left_index": 0,
    +                                "section_right_index": 1,
    +                                "section_left_hunk_size": 0,
    +                                "section_right_hunk_size": 0
    +                            },
    +                            {
    +                                "left_index": 0,
    +                                "right_index": 1,
    +                                "match": -1,
    +                                "type": 2,
    +                                "content": "+1111122222"
    +                            }
    +                        ]
    +                    }
    +                ],
    +                "is_incomplete": false,
    +                "is_incomplete_line_too_long": false,
    +                "is_protected": false
    +            }
    +        ]
    +    }
     }