feat(repos): 添加提交日志查询和分支查询
This commit is contained in:
24
src/repos/dtos/branches-list.model.ts
Normal file
24
src/repos/dtos/branches-list.model.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { ObjectType, Field } from '@nestjs/graphql';
|
||||
import {
|
||||
LogResult,
|
||||
DefaultLogFields,
|
||||
BranchSummary,
|
||||
BranchSummaryBranch,
|
||||
} from 'simple-git';
|
||||
|
||||
@ObjectType()
|
||||
export class Branch implements BranchSummaryBranch {
|
||||
current: boolean;
|
||||
name: string;
|
||||
commit: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
@ObjectType()
|
||||
export class BranchesList {
|
||||
detached: boolean;
|
||||
current: string;
|
||||
all: string[];
|
||||
@Field(() => [Branch])
|
||||
branches: Branch[];
|
||||
}
|
8
src/repos/dtos/list-branches.args.ts
Normal file
8
src/repos/dtos/list-branches.args.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { InputType } from '@nestjs/graphql';
|
||||
import { IsUUID } from 'class-validator';
|
||||
|
||||
@InputType()
|
||||
export class ListBranchesArgs {
|
||||
@IsUUID()
|
||||
projectId: string;
|
||||
}
|
12
src/repos/dtos/list-logs.args.ts
Normal file
12
src/repos/dtos/list-logs.args.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { InputType, ObjectType } from '@nestjs/graphql';
|
||||
import { IsOptional, IsString, IsUUID } from 'class-validator';
|
||||
|
||||
@InputType()
|
||||
export class ListLogsArgs {
|
||||
@IsUUID()
|
||||
projectId: string;
|
||||
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
branch?: string;
|
||||
}
|
21
src/repos/dtos/logs-list.model.ts
Normal file
21
src/repos/dtos/logs-list.model.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { ObjectType, Field } from '@nestjs/graphql';
|
||||
import { LogResult, DefaultLogFields } from 'simple-git';
|
||||
|
||||
@ObjectType()
|
||||
export class LogFields {
|
||||
hash: string;
|
||||
date: string;
|
||||
message: string;
|
||||
refs: string;
|
||||
body: string;
|
||||
author_name: string;
|
||||
author_email: string;
|
||||
}
|
||||
|
||||
@ObjectType()
|
||||
export class LogsList implements LogResult<DefaultLogFields> {
|
||||
@Field(() => [LogFields])
|
||||
all: LogFields[];
|
||||
total: number;
|
||||
latest: LogFields;
|
||||
}
|
11
src/repos/repos.module.ts
Normal file
11
src/repos/repos.module.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { Project } from '../projects/project.entity';
|
||||
import { ReposResolver } from './repos.resolver';
|
||||
import { ReposService } from './repos.service';
|
||||
|
||||
@Module({
|
||||
imports: [TypeOrmModule.forFeature([Project])],
|
||||
providers: [ReposResolver, ReposService],
|
||||
})
|
||||
export class ReposModule {}
|
18
src/repos/repos.resolver.spec.ts
Normal file
18
src/repos/repos.resolver.spec.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { ReposResolver } from './repos.resolver';
|
||||
|
||||
describe('ReposResolver', () => {
|
||||
let resolver: ReposResolver;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [ReposResolver],
|
||||
}).compile();
|
||||
|
||||
resolver = module.get<ReposResolver>(ReposResolver);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(resolver).toBeDefined();
|
||||
});
|
||||
});
|
26
src/repos/repos.resolver.ts
Normal file
26
src/repos/repos.resolver.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import { Args, Query, Resolver } from '@nestjs/graphql';
|
||||
import { ListLogsArgs } from './dtos/list-logs.args';
|
||||
import { ReposService } from './repos.service';
|
||||
import { LogsList } from './dtos/logs-list.model';
|
||||
import { ListBranchesArgs } from './dtos/list-branches.args';
|
||||
import { BranchesList } from './dtos/branches-list.model';
|
||||
|
||||
@Resolver()
|
||||
export class ReposResolver {
|
||||
con
|
||||
@Query(() => LogsList)
|
||||
async listLogs(@Args('listLogsArgs') dto: ListLogsArgs) {
|
||||
return await this.service.listLogs(dto);
|
||||
}
|
||||
@Query(() => BranchesList)
|
||||
async ListBranchesArgs(
|
||||
@Args('listBranchesArgs') dto: ListBranchesArgs,
|
||||
): Promise<BranchesList> {
|
||||
return await this.service.listBranches(dto).then((data) => {
|
||||
return {
|
||||
...data,
|
||||
branches: Object.values(data.branches),
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
48
src/repos/repos.service.spec.ts
Normal file
48
src/repos/repos.service.spec.ts
Normal file
@ -0,0 +1,48 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||
import { Project } from '../projects/project.entity';
|
||||
import { ReposService } from './repos.service';
|
||||
|
||||
describe('ReposService', () => {
|
||||
let service: ReposService;
|
||||
const repositoryMockFactory = jest.fn(() => ({
|
||||
findOneOrFail: jest.fn(
|
||||
(entity): Project => ({
|
||||
id: '1',
|
||||
// sshUrl: 'ssh://gitea@git.ivanli.cc:7018/ivan/test1.git',
|
||||
sshUrl: 'ssh://gitea@git.ivanli.cc:7018/Fennec/fennec-fe.git',
|
||||
name: 'test1',
|
||||
...entity,
|
||||
}),
|
||||
),
|
||||
}));
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [
|
||||
ReposService,
|
||||
{
|
||||
provide: getRepositoryToken(Project),
|
||||
useFactory: repositoryMockFactory,
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
service = module.get<ReposService>(ReposService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
describe('listLogs', () => {
|
||||
it('should be return logs', async () => {
|
||||
const result = await service.listLogs({ projectId: '1' });
|
||||
expect(result).toBeDefined();
|
||||
}, 10_000);
|
||||
});
|
||||
describe('listBranch', () => {
|
||||
it('should be return branches', async () => {
|
||||
const result = await service.listBranches({ projectId: '1' });
|
||||
expect(result).toBeDefined();
|
||||
}, 10_000);
|
||||
});
|
||||
});
|
41
src/repos/repos.service.ts
Normal file
41
src/repos/repos.service.ts
Normal file
@ -0,0 +1,41 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { F_OK } from 'constants';
|
||||
import { access, mkdir } from 'fs/promises';
|
||||
import { join } from 'path';
|
||||
import { gitP } from 'simple-git';
|
||||
import { Repository } from 'typeorm';
|
||||
import { Project } from '../projects/project.entity';
|
||||
import { ListBranchesArgs } from './dtos/list-branches.args';
|
||||
import { ListLogsArgs } from './dtos/list-logs.args';
|
||||
|
||||
@Injectable()
|
||||
export class ReposService {
|
||||
constructor(
|
||||
@InjectRepository(Project)
|
||||
private readonly projectRepository: Repository<Project>,
|
||||
) {}
|
||||
|
||||
async getGit(project: Project) {
|
||||
const workspacePath = join(__dirname, '../../workspaces', project.name);
|
||||
await access(workspacePath, F_OK).catch(() => mkdir(workspacePath));
|
||||
return gitP(workspacePath);
|
||||
}
|
||||
|
||||
async listLogs(dto: ListLogsArgs) {
|
||||
const project = await this.projectRepository.findOneOrFail({
|
||||
id: dto.projectId,
|
||||
});
|
||||
const git = await this.getGit(project);
|
||||
await git.fetch();
|
||||
return git.log();
|
||||
}
|
||||
|
||||
async listBranches(dto: ListBranchesArgs) {
|
||||
const project = await this.projectRepository.findOneOrFail({
|
||||
id: dto.projectId,
|
||||
});
|
||||
const git = await this.getGit(project);
|
||||
return git.branch();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user