@ysfe/c-gdc
Version:
命令行工具: 提供按group批量 clone gitlab repo 能力
138 lines (128 loc) • 4.67 kB
text/typescript
import Axios from 'axios'
import simpleGit from 'simple-git'
import { prompt } from 'enquirer'
import * as fs from 'fs'
import path from 'path'
const axios = Axios.create({
baseURL: 'http://gitlab.yslocal.com',
withCredentials: true,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
Host: 'gitlab.yslocal.com'
}
})
/** 导出服务 */
export default class CommandGitDeepClone {
opt!: { Cookie: string }
async command() {
// if don't has options, exec user input
await this.inputGitUser()
// ! login 实现太难, 直接贴 cookie 吧
// pull git group
let groups = await this.pullAllGroup()
// filter should clone group
groups = await this.filterCloneGroup(groups)
// pull all projects info
const projects = await this.pullProject(groups)
// cloen
console.log('> 共计:', projects.length, '个项目')
this.clones(projects)
}
async filterCloneGroup(groups: Array<string>): Promise<Array<string>> {
const { isConfirm } = (await prompt({
type: 'select',
name: 'isConfirm',
message: 'clones project from all group?',
choices: ['yes', 'no']
})) as any
if (isConfirm !== 'yes') {
try {
const { selected } = (await prompt({
type: 'multiselect',
name: 'selected',
message: 'Pick your favorite colors',
choices: groups
})) as any
groups = selected
} catch (error) {
//
}
}
return groups
}
/** if can't get params in command, that get git user in readline */
async inputGitUser() {
const query = []
let cookie: any
if (!this.opt?.Cookie) {
query.push({
type: 'input',
name: 'Cookie',
message: 'gitlab session (登录后, 从cookie中查看)'
})
const response: { Cookie: string } = await prompt(query)
cookie = response.Cookie
} else {
cookie = this.opt.Cookie
}
// input
this.opt = { Cookie: cookie.includes('=') ? cookie : '_gitlab_session=' + cookie }
}
/** pull git group from your gitlab */
async pullAllGroup(): Promise<Array<string>> {
const { data } = await axios.get('/dashboard/groups.json', {
headers: { Cookie: this.opt.Cookie }
})
const groups = data.map((item: any) => {
return item['relative_path']?.replace(/^\//, '')
})
return groups
}
async pullProject(groups: Array<string>, pageIndex: number = 1): Promise<Array<string>> {
console.log('fetching...')
let projects: Array<string> = []
for (const group of groups) {
const p = path.normalize(`/groups/${group}/-/children.json${pageIndex > 1 ? '?page=' + pageIndex : ''}`)
console.log('> pull', p)
const { data, headers } = await axios.get(p, {
headers: { Cookie: this.opt.Cookie }
})
for (const project of data) {
const { type, relative_path } = project
if (type === 'group') {
const children = await this.pullProject([relative_path])
projects = [...projects, ...children]
} else {
projects.push(relative_path)
}
}
if (headers['x-total-pages'] > 1 && pageIndex < headers['x-total-pages']) {
const children = await this.pullProject(groups, pageIndex + 1)
projects = [...projects, ...children]
}
}
return projects
}
/** 执行 clone */
async clones(projects: Array<string>) {
let p
try {
const inp = (await prompt({
type: 'input',
name: 'p',
message: '输入一个本地地址, 用来clone 这些仓库:'
})) as any
p = inp.p
} catch (error) {
//
}
if (!fs.existsSync(p)) return console.log(`> path not exist:`, p)
if (!fs.statSync(p).isDirectory()) return console.log(`> path not a directory:`, p)
for (const pro of projects) {
const repo = `http://gitlab.yslocal.com${pro}`
if (fs.existsSync(p + pro)) continue
await simpleGit().clone(repo, p + pro)
console.log('> cloned', repo)
}
}
}