mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
* [Code] use isomorphic-git to read git references
This commit is contained in:
parent
77e14c373c
commit
ca5f953581
9 changed files with 411 additions and 189 deletions
|
@ -79,7 +79,8 @@
|
|||
"resolutions": {
|
||||
"**/@types/node": "10.12.27",
|
||||
"**/@types/hapi": "^17.0.18",
|
||||
"**/typescript": "3.5.3"
|
||||
"**/typescript": "3.5.3",
|
||||
"**/isomorphic-git/**/base64-js": "^1.2.1"
|
||||
},
|
||||
"workspaces": {
|
||||
"packages": [
|
||||
|
|
|
@ -8,6 +8,7 @@ export interface CommitInfo {
|
|||
updated: Date;
|
||||
message: string;
|
||||
committer: string;
|
||||
author: string;
|
||||
id: string;
|
||||
parents: string[];
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ function prepareProject(url: string, p: string) {
|
|||
certificateCheck: () => 0,
|
||||
},
|
||||
},
|
||||
bare: 1,
|
||||
}).then(repo => {
|
||||
resolve(repo);
|
||||
});
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
// @ts-ignore
|
||||
import Git from '@elastic/nodegit';
|
||||
import assert from 'assert';
|
||||
import { execSync } from 'child_process';
|
||||
|
@ -34,8 +35,12 @@ describe('git_operations', () => {
|
|||
|
||||
try {
|
||||
const g = new GitOperations(serverOptions.repoPath);
|
||||
const defaultBranch = await g.getDefaultBranch(repoUri);
|
||||
const uri = path.join(repoUri, '.git');
|
||||
const defaultBranch = await g.getDefaultBranch(uri);
|
||||
assert.strictEqual(defaultBranch, 'trunk');
|
||||
const headRevision = await g.getHeadRevision(uri);
|
||||
const headCommit = await g.getCommitInfo(uri, 'HEAD');
|
||||
assert.strictEqual(headRevision, headCommit!.id);
|
||||
} finally {
|
||||
rimraf.sync(repoDir);
|
||||
}
|
||||
|
@ -43,13 +48,14 @@ describe('git_operations', () => {
|
|||
|
||||
async function prepareProject(repoPath: string) {
|
||||
mkdirp.sync(repoPath);
|
||||
const repo = await Git.Repository.init(repoPath, 0);
|
||||
const workDir = path.join(serverOptions.workspacePath, repoUri);
|
||||
const repo = await Git.Repository.init(workDir, 0);
|
||||
const content = '';
|
||||
fs.writeFileSync(path.join(repo.workdir(), '1'), content, 'utf8');
|
||||
fs.writeFileSync(path.join(workDir, '1'), content, 'utf8');
|
||||
const subFolder = 'src';
|
||||
fs.mkdirSync(path.join(repo.workdir(), subFolder));
|
||||
fs.writeFileSync(path.join(repo.workdir(), 'src/2'), content, 'utf8');
|
||||
fs.writeFileSync(path.join(repo.workdir(), 'src/3'), content, 'utf8');
|
||||
fs.mkdirSync(path.join(workDir, subFolder));
|
||||
fs.writeFileSync(path.join(workDir, 'src/2'), content, 'utf8');
|
||||
fs.writeFileSync(path.join(workDir, 'src/3'), content, 'utf8');
|
||||
|
||||
const index = await repo.refreshIndex();
|
||||
await index.addByPath('1');
|
||||
|
@ -68,12 +74,19 @@ describe('git_operations', () => {
|
|||
);
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`created commit ${commit.tostrS()}`);
|
||||
return repo;
|
||||
await Git.Clone.clone(workDir, repoPath, { bare: 1 });
|
||||
return Git.Repository.openBare(repoPath);
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
before(async () => {
|
||||
before(async function() {
|
||||
// @ts-ignore
|
||||
this.timeout(200000);
|
||||
await prepareProject(path.join(serverOptions.repoPath, repoUri));
|
||||
await cloneProject(
|
||||
'https://github.com/elastic/TypeScript-Node-Starter.git',
|
||||
path.join(serverOptions.repoPath, 'github.com/elastic/TypeScript-Node-Starter')
|
||||
);
|
||||
});
|
||||
const repoUri = 'github.com/test/test_repo';
|
||||
|
||||
|
@ -94,47 +107,47 @@ describe('git_operations', () => {
|
|||
assert.strictEqual('3', value.name);
|
||||
assert.strictEqual('src/3', value.path);
|
||||
} else {
|
||||
assert.fail('this repo should contains exactly 2 files');
|
||||
assert.fail('this repo should contains exactly 3 files');
|
||||
}
|
||||
count++;
|
||||
}
|
||||
const totalFiles = await g.countRepoFiles(repoUri, 'HEAD');
|
||||
assert.strictEqual(count, 3, 'this repo should contains exactly 2 files');
|
||||
assert.strictEqual(totalFiles, 3, 'this repo should contains exactly 2 files');
|
||||
assert.strictEqual(count, 3, 'this repo should contains exactly 3 files');
|
||||
assert.strictEqual(totalFiles, 3, 'this repo should contains exactly 3 files');
|
||||
});
|
||||
function cloneProject(url: string, p: string) {
|
||||
return new Promise(resolve => {
|
||||
if (!fs.existsSync(p)) {
|
||||
rimraf(p, error => {
|
||||
Git.Clone.clone(url, p, {
|
||||
bare: 1,
|
||||
fetchOpts: {
|
||||
callbacks: {
|
||||
certificateCheck: () => 0,
|
||||
},
|
||||
},
|
||||
}).then(repo => {
|
||||
resolve(repo);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
it('can resolve branches', async () => {
|
||||
const g = new GitOperations(serverOptions.repoPath);
|
||||
const c = await g.getCommitOr404('github.com/elastic/TypeScript-Node-Starter', 'master');
|
||||
assert.strictEqual(c.id, '261557d657fdfddf78119d15d38b1f6a7be005ed');
|
||||
const c1 = await g.getCommitOr404('github.com/elastic/TypeScript-Node-Starter', 'VS');
|
||||
assert.strictEqual(c1.id, 'ba73782df210e0a7744ac9b623d58081a1801738');
|
||||
// @ts-ignore
|
||||
}).timeout(100000);
|
||||
|
||||
it('get diff between arbitrary 2 revisions', async () => {
|
||||
function cloneProject(url: string, p: string) {
|
||||
return new Promise(resolve => {
|
||||
if (!fs.existsSync(p)) {
|
||||
rimraf(p, error => {
|
||||
Git.Clone.clone(url, p, {
|
||||
fetchOpts: {
|
||||
callbacks: {
|
||||
certificateCheck: () => 0,
|
||||
},
|
||||
},
|
||||
}).then(repo => {
|
||||
resolve(repo);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
await cloneProject(
|
||||
'https://github.com/Microsoft/TypeScript-Node-Starter.git',
|
||||
path.join(serverOptions.repoPath, 'github.com/Microsoft/TypeScript-Node-Starter')
|
||||
);
|
||||
|
||||
const g = new GitOperations(serverOptions.repoPath);
|
||||
const d = await g.getDiff(
|
||||
'github.com/Microsoft/TypeScript-Node-Starter',
|
||||
'6206f643',
|
||||
'4779cb7e'
|
||||
);
|
||||
const d = await g.getDiff('github.com/elastic/TypeScript-Node-Starter', '6206f643', '4779cb7e');
|
||||
assert.equal(d.additions, 2);
|
||||
assert.equal(d.deletions, 4);
|
||||
assert.equal(d.files.length, 3);
|
||||
|
|
|
@ -338,7 +338,7 @@ describe('lsp_indexer unit tests', function(this: any) {
|
|||
for (let i = 0; i < bulkSpy.callCount; i++) {
|
||||
total += bulkSpy.getCall(i).args[0].body.length;
|
||||
}
|
||||
assert.strictEqual(total, 48 * 2);
|
||||
assert.strictEqual(total, 49 * 2);
|
||||
// @ts-ignore
|
||||
}).timeout(20000);
|
||||
});
|
||||
|
|
|
@ -11,9 +11,7 @@ import {
|
|||
Commit,
|
||||
Diff as NodeGitDiff,
|
||||
Error as NodeGitError,
|
||||
Object,
|
||||
Oid,
|
||||
Reference,
|
||||
Repository,
|
||||
Tree,
|
||||
TreeEntry,
|
||||
|
@ -22,6 +20,9 @@ import Boom from 'boom';
|
|||
import LruCache from 'lru-cache';
|
||||
import * as Path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import * as isogit from 'isomorphic-git';
|
||||
import { CommitDescription, TreeDescription } from 'isomorphic-git';
|
||||
import { isBinaryFileSync } from 'isbinaryfile';
|
||||
|
||||
import { GitBlame } from '../common/git_blame';
|
||||
import { CommitDiff, Diff, DiffKind } from '../common/git_diff';
|
||||
|
@ -29,6 +30,8 @@ import { FileTree, FileTreeItemType, RepositoryUri, sortFileTree } from '../mode
|
|||
import { CommitInfo, ReferenceInfo, ReferenceType } from '../model/commit';
|
||||
import { detectLanguage } from './utils/detect_language';
|
||||
|
||||
isogit.plugins.set('fs', fs);
|
||||
|
||||
export const HEAD = 'HEAD';
|
||||
const REFS_HEADS = 'refs/heads/';
|
||||
export const DEFAULT_TREE_CHILDREN_LIMIT = 50;
|
||||
|
@ -115,49 +118,51 @@ export class GitOperations {
|
|||
}
|
||||
|
||||
public async fileContent(uri: RepositoryUri, path: string, revision: string = 'master') {
|
||||
const commit = await this.getCommit(uri, revision);
|
||||
const entry: TreeEntry = await checkExists(
|
||||
() => commit.getEntry(path),
|
||||
`file ${uri}/${path} not found `
|
||||
);
|
||||
if (entry.isFile() || entry.filemode() === TreeEntry.FILEMODE.LINK) {
|
||||
return await entry.getBlob();
|
||||
} else {
|
||||
throw Boom.unsupportedMediaType(`${uri}/${path} is not a file.`);
|
||||
const gitdir = this.repoDir(uri);
|
||||
const commit: CommitInfo = await this.getCommitOr404(uri, revision);
|
||||
const file = await isogit.readObject({
|
||||
gitdir,
|
||||
oid: commit.id,
|
||||
filepath: path,
|
||||
format: 'content',
|
||||
});
|
||||
if (file && file.type === 'blob') {
|
||||
return {
|
||||
isBinary() {
|
||||
return isBinaryFileSync(file.object as Buffer);
|
||||
},
|
||||
content() {
|
||||
return file.object as Buffer;
|
||||
},
|
||||
rawsize() {
|
||||
return (file.object as Buffer).length;
|
||||
},
|
||||
};
|
||||
}
|
||||
throw Boom.unsupportedMediaType(`${uri}/${path} is not a file.`);
|
||||
}
|
||||
|
||||
public async getCommit(uri: RepositoryUri, revision: string): Promise<Commit> {
|
||||
const info = await this.getCommitOr404(uri, revision);
|
||||
const repo = await this.openRepo(uri);
|
||||
if (revision.toUpperCase() === HEAD) {
|
||||
return await repo.getHeadCommit();
|
||||
}
|
||||
// branches and tags
|
||||
const refs = [`refs/remotes/origin/${revision}`, `refs/tags/${revision}`];
|
||||
const commit = await this.findCommitByRefs(repo, refs);
|
||||
if (commit === null) {
|
||||
return (await checkExists(
|
||||
() => this.findCommit(repo, revision),
|
||||
`revision or branch ${revision} not found in ${repo.path()}`
|
||||
)) as Commit;
|
||||
}
|
||||
return commit;
|
||||
return (await checkExists(
|
||||
() => this.findCommit(repo, info.id),
|
||||
`revision or branch ${revision} not found in ${uri}`
|
||||
)) as Commit;
|
||||
}
|
||||
|
||||
public async getDefaultBranch(uri: RepositoryUri): Promise<string> {
|
||||
const repo = await this.openRepo(uri);
|
||||
const ref = await repo.getReference(HEAD);
|
||||
const name = ref.name();
|
||||
if (name.startsWith(REFS_HEADS)) {
|
||||
return name.substr(REFS_HEADS.length);
|
||||
const gitdir = this.repoDir(uri);
|
||||
const ref = await isogit.resolveRef({ gitdir, ref: HEAD, depth: 2 });
|
||||
if (ref.startsWith(REFS_HEADS)) {
|
||||
return ref.substr(REFS_HEADS.length);
|
||||
}
|
||||
return name;
|
||||
return ref;
|
||||
}
|
||||
|
||||
public async getHeadRevision(uri: RepositoryUri): Promise<string> {
|
||||
const repo = await this.openRepo(uri);
|
||||
const commit = await repo.getHeadCommit();
|
||||
return commit.sha();
|
||||
const gitdir = this.repoDir(uri);
|
||||
return await isogit.resolveRef({ gitdir, ref: HEAD, depth: 10 });
|
||||
}
|
||||
|
||||
public async blame(uri: RepositoryUri, revision: string, path: string): Promise<GitBlame[]> {
|
||||
|
@ -196,8 +201,7 @@ export class GitOperations {
|
|||
return Promise.resolve(repo);
|
||||
}
|
||||
|
||||
const repoDir = Path.join(this.repoRoot, uri);
|
||||
this.checkPath(repoDir);
|
||||
const repoDir = this.repoDir(uri);
|
||||
const repo = await checkExists<Repository>(
|
||||
() => Repository.open(repoDir),
|
||||
`repo ${uri} not found`
|
||||
|
@ -206,30 +210,43 @@ export class GitOperations {
|
|||
return Promise.resolve(repo);
|
||||
}
|
||||
|
||||
private repoDir(uri: RepositoryUri) {
|
||||
const repoDir = Path.join(this.repoRoot, uri);
|
||||
this.checkPath(repoDir);
|
||||
return repoDir;
|
||||
}
|
||||
|
||||
private checkPath(path: string) {
|
||||
if (!fs.realpathSync(path).startsWith(fs.realpathSync(this.repoRoot))) {
|
||||
throw new Error('invalid path');
|
||||
}
|
||||
}
|
||||
public async countRepoFiles(uri: RepositoryUri, revision: string): Promise<number> {
|
||||
const commit = await this.getCommit(uri, revision);
|
||||
const tree = await commit.getTree();
|
||||
let count = 0;
|
||||
const commit = await this.getCommitOr404(uri, revision);
|
||||
const gitdir = this.repoDir(uri);
|
||||
const commitObject = await isogit.readObject({ gitdir, oid: commit.id });
|
||||
const treeId = (commitObject.object as CommitDescription).tree;
|
||||
|
||||
async function walk(t: Tree) {
|
||||
for (const e of t.entries()) {
|
||||
if (e.isFile() && e.filemode() !== TreeEntry.FILEMODE.LINK) {
|
||||
count++;
|
||||
} else if (e.isDirectory()) {
|
||||
const subFolder = await e.getTree();
|
||||
await walk(subFolder);
|
||||
} else {
|
||||
// ignore other files
|
||||
async function walk(oid: string) {
|
||||
const { object } = await isogit.readObject({ gitdir, oid });
|
||||
const tree = object as TreeDescription;
|
||||
for (const entry of tree.entries) {
|
||||
if (entry.type === 'tree') {
|
||||
await walk(entry.oid);
|
||||
} else if (entry.type === 'blob') {
|
||||
const type = GitOperations.mode2type(entry.mode);
|
||||
if (type === FileTreeItemType.File) {
|
||||
const blob = await isogit.readObject({ gitdir, oid: entry.oid, format: 'content' });
|
||||
if (!isBinaryFileSync(blob.object as Buffer)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await walk(tree);
|
||||
await walk(treeId);
|
||||
return count;
|
||||
}
|
||||
|
||||
|
@ -237,27 +254,53 @@ export class GitOperations {
|
|||
uri: RepositoryUri,
|
||||
revision: string
|
||||
): Promise<AsyncIterableIterator<FileTree>> {
|
||||
const commit = await this.getCommit(uri, revision);
|
||||
const tree = await commit.getTree();
|
||||
|
||||
async function* walk(t: Tree): AsyncIterableIterator<FileTree> {
|
||||
for (const e of t.entries()) {
|
||||
if (e.isFile() && e.filemode() !== TreeEntry.FILEMODE.LINK) {
|
||||
const blob = await e.getBlob();
|
||||
// Ignore binary files
|
||||
if (!blob.isBinary()) {
|
||||
yield entry2Tree(e);
|
||||
async function* walk(oid: string, prefix: string = ''): AsyncIterableIterator<FileTree> {
|
||||
const { object } = await isogit.readObject({ gitdir, oid });
|
||||
const tree = object as TreeDescription;
|
||||
for (const entry of tree.entries) {
|
||||
const path = prefix ? `${prefix}/${entry.path}` : entry.path;
|
||||
if (entry.type === 'tree') {
|
||||
yield* walk(entry.oid, path);
|
||||
} else if (entry.type === 'blob') {
|
||||
const type = GitOperations.mode2type(entry.mode);
|
||||
if (type === FileTreeItemType.File) {
|
||||
const blob = await isogit.readObject({ gitdir, oid: entry.oid, format: 'content' });
|
||||
if (!isBinaryFileSync(blob.object as Buffer)) {
|
||||
yield {
|
||||
name: entry.path,
|
||||
type,
|
||||
path,
|
||||
repoUri: uri,
|
||||
sha1: entry.oid,
|
||||
} as FileTree;
|
||||
}
|
||||
}
|
||||
} else if (e.isDirectory()) {
|
||||
const subFolder = await e.getTree();
|
||||
await (yield* walk(subFolder));
|
||||
} else {
|
||||
// ignore other files
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return await walk(tree);
|
||||
const commit = await this.getCommitOr404(uri, revision);
|
||||
const gitdir = this.repoDir(uri);
|
||||
const commitObject = await isogit.readObject({ gitdir, oid: commit.id });
|
||||
const treeId = (commitObject.object as CommitDescription).tree;
|
||||
return await walk(treeId);
|
||||
}
|
||||
|
||||
static mode2type(mode: string): FileTreeItemType {
|
||||
switch (mode) {
|
||||
case '100755':
|
||||
case '100644':
|
||||
return FileTreeItemType.File;
|
||||
case '120000':
|
||||
return FileTreeItemType.Link;
|
||||
case '40000':
|
||||
case '040000':
|
||||
return FileTreeItemType.Directory;
|
||||
case '160000':
|
||||
return FileTreeItemType.Submodule;
|
||||
default:
|
||||
throw new Error('unknown mode: ' + mode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -269,6 +312,7 @@ export class GitOperations {
|
|||
* @param limit pagination parameter, limit the number of node's children.
|
||||
* @param resolveParents whether the return value should always start from root
|
||||
* @param childrenDepth how depth should the children walk.
|
||||
* @param flatten
|
||||
*/
|
||||
public async fileTree(
|
||||
uri: RepositoryUri,
|
||||
|
@ -539,37 +583,107 @@ export class GitOperations {
|
|||
return fileTree;
|
||||
}
|
||||
|
||||
private async findCommit(repo: Repository, revision: string): Promise<Commit | null> {
|
||||
private async findCommit(repo: Repository, oid: string): Promise<Commit | null> {
|
||||
try {
|
||||
const obj = await Object.lookupPrefix(
|
||||
repo,
|
||||
Oid.fromString(revision),
|
||||
revision.length,
|
||||
Object.TYPE.COMMIT
|
||||
);
|
||||
if (obj) {
|
||||
return repo.getCommit(obj.id());
|
||||
}
|
||||
return null;
|
||||
return repo.getCommit(Oid.fromString(oid));
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private async findCommitByRefs(repo: Repository, refs: string[]): Promise<Commit | null> {
|
||||
if (refs.length === 0) {
|
||||
return null;
|
||||
}
|
||||
const [ref, ...rest] = refs;
|
||||
try {
|
||||
return await repo.getReferenceCommit(ref);
|
||||
} catch (e) {
|
||||
if (e.errno === NodeGitError.CODE.ENOTFOUND) {
|
||||
return await this.findCommitByRefs(repo, rest);
|
||||
} else {
|
||||
throw e;
|
||||
public async getBranchAndTags(repoUri: string): Promise<ReferenceInfo[]> {
|
||||
const gitdir = this.repoDir(repoUri);
|
||||
const remoteBranches = await isogit.listBranches({ gitdir, remote: 'origin' });
|
||||
const results: ReferenceInfo[] = [];
|
||||
for (const name of remoteBranches) {
|
||||
const reference = `refs/remotes/origin/${name}`;
|
||||
const commit = await this.getCommitInfo(repoUri, reference);
|
||||
if (commit) {
|
||||
results.push({
|
||||
name,
|
||||
reference,
|
||||
type: ReferenceType.REMOTE_BRANCH,
|
||||
commit,
|
||||
});
|
||||
}
|
||||
}
|
||||
const tags = await isogit.listTags({ gitdir });
|
||||
for (const name of tags) {
|
||||
const reference = `refs/tags/${name}`;
|
||||
const commit = await this.getCommitInfo(repoUri, reference);
|
||||
if (commit) {
|
||||
results.push({
|
||||
name,
|
||||
reference,
|
||||
type: ReferenceType.TAG,
|
||||
commit,
|
||||
});
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
public async getCommitOr404(repoUri: string, ref: string): Promise<CommitInfo> {
|
||||
const commit = await this.getCommitInfo(repoUri, ref);
|
||||
if (!commit) {
|
||||
throw Boom.notFound(`repo ${repoUri} or ${ref} not found`);
|
||||
}
|
||||
return commit;
|
||||
}
|
||||
|
||||
public async getCommitInfo(repoUri: string, ref: string): Promise<CommitInfo | null> {
|
||||
const gitdir = this.repoDir(repoUri);
|
||||
// depth: avoid infinite loop
|
||||
let obj: isogit.GitObjectDescription | null = null;
|
||||
let oid: string = '';
|
||||
if (/^[0-9a-f]{5,40}$/.test(ref)) {
|
||||
// it's possible ref is sha-1 object id
|
||||
try {
|
||||
oid = ref;
|
||||
if (oid.length < 40) {
|
||||
oid = await isogit.expandOid({ gitdir, oid });
|
||||
}
|
||||
obj = await isogit.readObject({ gitdir, oid, format: 'parsed' });
|
||||
} catch (e) {
|
||||
// expandOid or readObject failed
|
||||
}
|
||||
}
|
||||
// test if it is a reference
|
||||
if (!obj) {
|
||||
try {
|
||||
// try local branches or tags
|
||||
oid = await isogit.resolveRef({ gitdir, ref, depth: 10 });
|
||||
} catch (e) {
|
||||
// try remote branches
|
||||
try {
|
||||
oid = await isogit.resolveRef({ gitdir, ref: `origin/${ref}`, depth: 10 });
|
||||
} catch (e1) {
|
||||
// no match
|
||||
}
|
||||
}
|
||||
if (oid) {
|
||||
obj = await isogit.readObject({ gitdir, oid, format: 'parsed' });
|
||||
}
|
||||
}
|
||||
if (obj) {
|
||||
if (obj.type === 'commit') {
|
||||
const commit = obj.object as isogit.CommitDescription;
|
||||
return {
|
||||
id: obj.oid,
|
||||
author: commit.author.name,
|
||||
committer: commit.committer.name,
|
||||
message: commit.message,
|
||||
updated: new Date(commit.committer.timestamp * 1000),
|
||||
parents: commit.parent,
|
||||
} as CommitInfo;
|
||||
} else if (obj.type === 'tag') {
|
||||
const tag = obj.object as isogit.TagDescription;
|
||||
if (tag.type === 'commit') {
|
||||
return await this.getCommitInfo(repoUri, tag.object);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -577,40 +691,9 @@ export function commitInfo(commit: Commit): CommitInfo {
|
|||
return {
|
||||
updated: commit.date(),
|
||||
message: commit.message(),
|
||||
author: commit.author().name(),
|
||||
committer: commit.committer().name(),
|
||||
id: commit.sha().substr(0, 7),
|
||||
parents: commit.parents().map(oid => oid.toString().substring(0, 7)),
|
||||
};
|
||||
}
|
||||
const REMOTE_PREFIX = 'origin/';
|
||||
|
||||
export async function referenceInfo(ref: Reference): Promise<ReferenceInfo | null> {
|
||||
const repository = ref.owner();
|
||||
let commit: CommitInfo | undefined;
|
||||
try {
|
||||
const object = await ref.peel(Object.TYPE.COMMIT);
|
||||
commit = commitInfo(await repository.getCommit(object.id()));
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
let type: ReferenceType;
|
||||
let name = ref.shorthand();
|
||||
if (ref.isTag()) {
|
||||
type = ReferenceType.TAG;
|
||||
} else if (ref.isRemote()) {
|
||||
if (name.startsWith(REMOTE_PREFIX)) {
|
||||
name = name.substr(REMOTE_PREFIX.length);
|
||||
}
|
||||
type = ReferenceType.REMOTE_BRANCH;
|
||||
} else if (ref.isBranch()) {
|
||||
type = ReferenceType.BRANCH;
|
||||
} else {
|
||||
type = ReferenceType.OTHER;
|
||||
}
|
||||
return {
|
||||
name,
|
||||
reference: ref.name(),
|
||||
commit,
|
||||
type,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4,23 +4,17 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { Commit, Reference, Revwalk } from '@elastic/nodegit';
|
||||
import { Commit, Oid, Revwalk } from '@elastic/nodegit';
|
||||
import Boom from 'boom';
|
||||
import fileType from 'file-type';
|
||||
import hapi, { RequestQuery } from 'hapi';
|
||||
import {
|
||||
commitInfo,
|
||||
DEFAULT_TREE_CHILDREN_LIMIT,
|
||||
GitOperations,
|
||||
referenceInfo,
|
||||
} from '../git_operations';
|
||||
import { commitInfo, DEFAULT_TREE_CHILDREN_LIMIT, GitOperations } from '../git_operations';
|
||||
import { extractLines } from '../utils/buffer';
|
||||
import { detectLanguage } from '../utils/detect_language';
|
||||
import { CodeServerRouter } from '../security';
|
||||
import { RepositoryObjectClient } from '../search';
|
||||
import { EsClientWithRequest } from '../utils/esclient_with_request';
|
||||
import { TEXT_FILE_LIMIT } from '../../common/file';
|
||||
import { ReferenceType } from '../../model/commit';
|
||||
import { decodeRevisionString } from '../../common/uri_util';
|
||||
|
||||
export function fileRoute(server: CodeServerRouter, gitOps: GitOperations) {
|
||||
|
@ -178,21 +172,24 @@ export function fileRoute(server: CodeServerRouter, gitOps: GitOperations) {
|
|||
return Boom.notFound(`repo ${uri} not found`);
|
||||
}
|
||||
const repository = await gitOps.openRepo(uri);
|
||||
const commit = await gitOps.getCommit(uri, revision);
|
||||
const commit = await gitOps.getCommitInfo(uri, revision);
|
||||
if (commit === null) {
|
||||
throw Boom.notFound(`commit ${revision} not found in repo ${uri}`);
|
||||
}
|
||||
const walk = repository.createRevWalk();
|
||||
walk.sorting(Revwalk.SORT.TIME);
|
||||
walk.push(commit.id());
|
||||
const commitId = Oid.fromString(commit!.id);
|
||||
walk.push(commitId);
|
||||
let commits: Commit[];
|
||||
if (path) {
|
||||
// magic number 10000: how many commits at the most to iterate in order to find the commits contains the path
|
||||
const results = await walk.fileHistoryWalk(path, count, 10000);
|
||||
commits = results.map(result => result.commit);
|
||||
} else {
|
||||
walk.push(commit.id());
|
||||
commits = await walk.getCommits(count);
|
||||
}
|
||||
if (after && commits.length > 0) {
|
||||
if (commits[0].id().equal(commit.id())) {
|
||||
if (commits[0].id().equal(commitId)) {
|
||||
commits = commits.slice(1);
|
||||
}
|
||||
}
|
||||
|
@ -215,14 +212,7 @@ export function fileRoute(server: CodeServerRouter, gitOps: GitOperations) {
|
|||
return Boom.notFound(`repo ${uri} not found`);
|
||||
}
|
||||
try {
|
||||
const repository = await gitOps.openRepo(uri);
|
||||
const references = await repository.getReferences(Reference.TYPE.DIRECT);
|
||||
const referenceInfos = await Promise.all(references.map(referenceInfo));
|
||||
return referenceInfos.filter(
|
||||
info =>
|
||||
info !== null &&
|
||||
(info.type === ReferenceType.REMOTE_BRANCH || info.type === ReferenceType.TAG)
|
||||
);
|
||||
return await gitOps.getBranchAndTags(uri);
|
||||
} catch (e) {
|
||||
if (e.isBoom) {
|
||||
return e;
|
||||
|
|
|
@ -102,6 +102,7 @@
|
|||
"ansi-colors": "^3.0.5",
|
||||
"ansicolors": "0.3.2",
|
||||
"axios": "^0.19.0",
|
||||
"base64-js": "^1.2.1",
|
||||
"babel-jest": "^24.1.0",
|
||||
"babel-plugin-inline-react-svg": "1.1.0",
|
||||
"babel-plugin-mock-imports": "1.0.1",
|
||||
|
@ -203,7 +204,6 @@
|
|||
"apollo-server-errors": "^2.0.2",
|
||||
"apollo-server-hapi": "^1.3.6",
|
||||
"axios": "^0.19.0",
|
||||
"base64-js": "^1.2.1",
|
||||
"bluebird": "3.5.5",
|
||||
"boom": "^7.2.0",
|
||||
"brace": "0.11.1",
|
||||
|
@ -248,6 +248,8 @@
|
|||
"immer": "^1.5.0",
|
||||
"inline-style": "^2.0.0",
|
||||
"intl": "^1.2.5",
|
||||
"isomorphic-git": "0.55.5",
|
||||
"isbinaryfile": "4.0.2",
|
||||
"io-ts": "^1.4.2",
|
||||
"joi": "^13.5.2",
|
||||
"jquery": "^3.4.1",
|
||||
|
|
145
yarn.lock
145
yarn.lock
|
@ -5962,6 +5962,11 @@ async-limiter@~1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8"
|
||||
integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==
|
||||
|
||||
async-lock@^1.1.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/async-lock/-/async-lock-1.2.0.tgz#cd6a53cb1ec3f86af25eafdeb6bc7c6e317258b8"
|
||||
integrity sha512-81HzTQm4+qMj6PwNlnR+y9g7pDdGGzd/YBUrQnHk+BhR28ja2qv497NkQQc1KcKEqh/RShm07di2b0cIWVFrNQ==
|
||||
|
||||
async-retry@^1.2.3:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/async-retry/-/async-retry-1.2.3.tgz#a6521f338358d322b1a0012b79030c6f411d1ce0"
|
||||
|
@ -6757,6 +6762,11 @@ base64-arraybuffer@0.1.5:
|
|||
resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8"
|
||||
integrity sha1-c5JncZI7Whl0etZmqlzUv5xunOg=
|
||||
|
||||
base64-js@0.0.2, base64-js@^1.2.1, base64-js@^1.2.3:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3"
|
||||
integrity sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==
|
||||
|
||||
base64-js@0.0.8:
|
||||
version "0.0.8"
|
||||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-0.0.8.tgz#1101e9544f4a76b1bc3b26d452ca96d7a35e7978"
|
||||
|
@ -6767,11 +6777,6 @@ base64-js@^1.0.2, base64-js@^1.1.2:
|
|||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.1.tgz#a91947da1f4a516ea38e5b4ec0ec3773675e0886"
|
||||
integrity sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw==
|
||||
|
||||
base64-js@^1.2.1, base64-js@^1.2.3:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3"
|
||||
integrity sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==
|
||||
|
||||
base64id@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/base64id/-/base64id-1.0.0.tgz#47688cb99bb6804f0e06d3e763b1c32e57d8e6b6"
|
||||
|
@ -7060,6 +7065,14 @@ boom@7.x.x, boom@^7.1.0, boom@^7.2.0:
|
|||
dependencies:
|
||||
hoek "6.x.x"
|
||||
|
||||
bops@~0.0.6:
|
||||
version "0.0.7"
|
||||
resolved "https://registry.yarnpkg.com/bops/-/bops-0.0.7.tgz#b4a0a5a839a406454af0fe05a8b91a7a766a54e2"
|
||||
integrity sha1-tKClqDmkBkVK8P4FqLkaenZqVOI=
|
||||
dependencies:
|
||||
base64-js "0.0.2"
|
||||
to-utf8 "0.0.1"
|
||||
|
||||
bottleneck@^2.15.3:
|
||||
version "2.18.0"
|
||||
resolved "https://registry.yarnpkg.com/bottleneck/-/bottleneck-2.18.0.tgz#41fa63ae185b65435d789d1700334bc48222dacf"
|
||||
|
@ -8138,6 +8151,11 @@ clean-css@4.2.x, clean-css@^4.1.11:
|
|||
dependencies:
|
||||
source-map "~0.6.0"
|
||||
|
||||
clean-git-ref@1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/clean-git-ref/-/clean-git-ref-1.0.3.tgz#5325dc839eab01c974ae0e97f5734782750f88ec"
|
||||
integrity sha1-UyXcg56rAcl0rg6X9XNHgnUPiOw=
|
||||
|
||||
clean-stack@^1.0.0, clean-stack@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-1.3.0.tgz#9e821501ae979986c46b1d66d2d432db2fd4ae31"
|
||||
|
@ -9076,6 +9094,14 @@ cpy@^7.0.1:
|
|||
globby "^8.0.1"
|
||||
nested-error-stacks "^2.0.0"
|
||||
|
||||
crc-32@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.0.tgz#cb2db6e29b88508e32d9dd0ec1693e7b41a18208"
|
||||
integrity sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==
|
||||
dependencies:
|
||||
exit-on-epipe "~1.0.1"
|
||||
printj "~1.1.0"
|
||||
|
||||
crc32-stream@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-2.0.0.tgz#e3cdd3b4df3168dd74e3de3fbbcb7b297fe908f4"
|
||||
|
@ -10394,6 +10420,13 @@ diagnostics@^1.1.1:
|
|||
enabled "1.0.x"
|
||||
kuler "1.0.x"
|
||||
|
||||
diff-lines@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/diff-lines/-/diff-lines-1.1.1.tgz#4f10a709b6ce2af1d6b412ada5a90cf01d782571"
|
||||
integrity sha512-Oo5JzEEriF/+T0usOeRP5yOzr6SWvni2rrxvIgijMZSxPcEvf8JOvCO5GpnWwkte7fcOgnue/f5ECg1H9lMPCw==
|
||||
dependencies:
|
||||
diff "^3.5.0"
|
||||
|
||||
diff-sequences@^24.0.0:
|
||||
version "24.0.0"
|
||||
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.0.0.tgz#cdf8e27ed20d8b8d3caccb4e0c0d8fe31a173013"
|
||||
|
@ -11922,6 +11955,11 @@ exit-hook@^2.1.0:
|
|||
resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-2.1.0.tgz#2be08d8d01220050878577bfa017e104a6c3bcf3"
|
||||
integrity sha512-JCSm9Znc/KW6hoKYHOIqLxM2Z88+AQcabo07rJHZSyXcQIq6HsXkSWRVZRp13RFkGVIDcz1DRIbKR5cnU1uzCA==
|
||||
|
||||
exit-on-epipe@~1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz#0bdd92e87d5285d267daa8171d0eb06159689692"
|
||||
integrity sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==
|
||||
|
||||
exit@^0.1.2, exit@~0.1.1:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c"
|
||||
|
@ -13388,6 +13426,14 @@ gh-got@^5.0.0:
|
|||
got "^6.2.0"
|
||||
is-plain-obj "^1.1.0"
|
||||
|
||||
git-apply-delta@0.0.7:
|
||||
version "0.0.7"
|
||||
resolved "https://registry.yarnpkg.com/git-apply-delta/-/git-apply-delta-0.0.7.tgz#fb76ae144540d79440b52b31de03e63c993c7219"
|
||||
integrity sha1-+3auFEVA15RAtSsx3gPmPJk8chk=
|
||||
dependencies:
|
||||
bops "~0.0.6"
|
||||
varint "0.0.3"
|
||||
|
||||
git-clone@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/git-clone/-/git-clone-0.1.0.tgz#0d76163778093aef7f1c30238f2a9ef3f07a2eb9"
|
||||
|
@ -13692,6 +13738,11 @@ globals@^9.18.0, globals@^9.2.0:
|
|||
resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
|
||||
integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==
|
||||
|
||||
globalyzer@^0.1.0:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/globalyzer/-/globalyzer-0.1.4.tgz#bc8e273afe1ac7c24eea8def5b802340c5cc534f"
|
||||
integrity sha512-LeguVWaxgHN0MNbWC6YljNMzHkrCny9fzjmEUdnF1kQ7wATFD1RHFRqA1qxaX2tgxGENlcxjOflopBwj3YZiXA==
|
||||
|
||||
globby@8.0.2:
|
||||
version "8.0.2"
|
||||
resolved "https://registry.yarnpkg.com/globby/-/globby-8.0.2.tgz#5697619ccd95c5275dbb2d6faa42087c1a941d8d"
|
||||
|
@ -13779,6 +13830,11 @@ globby@^9.2.0:
|
|||
pify "^4.0.1"
|
||||
slash "^2.0.0"
|
||||
|
||||
globrex@^0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/globrex/-/globrex-0.1.2.tgz#dd5d9ec826232730cd6793a5e33a9302985e6098"
|
||||
integrity sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==
|
||||
|
||||
globule@^1.0.0:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/globule/-/globule-1.2.1.tgz#5dffb1b191f22d20797a9369b49eab4e9839696d"
|
||||
|
@ -15182,7 +15238,7 @@ ignore@^4.0.3, ignore@^4.0.6:
|
|||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
|
||||
integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==
|
||||
|
||||
ignore@^5.1.1:
|
||||
ignore@^5.0.4, ignore@^5.1.1:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.2.tgz#e28e584d43ad7e92f96995019cc43b9e1ac49558"
|
||||
integrity sha512-vdqWBp7MyzdmHkkRWV5nY+PfGRbYbahfuvsBCh277tq+w9zyNi7h5CYJCK0kmzti9kU+O/cB7sE8HvKv6aXAKQ==
|
||||
|
@ -16341,6 +16397,11 @@ isarray@2.0.1:
|
|||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.1.tgz#a37d94ed9cda2d59865c9f76fe596ee1f338741e"
|
||||
integrity sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=
|
||||
|
||||
isbinaryfile@4.0.2:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.2.tgz#bfc45642da645681c610cca831022e30af426488"
|
||||
integrity sha512-C3FSxJdNrEr2F4z6uFtNzECDM5hXk+46fxaa+cwBe5/XrWSmzdG8DDgyjfX6/NRdBB21q2JXuRAzPCUs+fclnQ==
|
||||
|
||||
isbinaryfile@^3.0.0:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-3.0.2.tgz#4a3e974ec0cba9004d3fc6cde7209ea69368a621"
|
||||
|
@ -16383,6 +16444,27 @@ isomorphic-fetch@^2.1.1:
|
|||
node-fetch "^1.0.1"
|
||||
whatwg-fetch ">=0.10.0"
|
||||
|
||||
isomorphic-git@0.55.5:
|
||||
version "0.55.5"
|
||||
resolved "https://registry.yarnpkg.com/isomorphic-git/-/isomorphic-git-0.55.5.tgz#d232dddefa9d271470b9b496c14aa65aa98f2519"
|
||||
integrity sha512-qqFID4DYGjnMkxDowXbp5GUdId6SJCbOEZFRdodMgrk26hjeOiNiOpGlYOX4rBe2mJAsE7Bdj30EQAQJtE72DA==
|
||||
dependencies:
|
||||
async-lock "^1.1.0"
|
||||
clean-git-ref "1.0.3"
|
||||
crc-32 "^1.2.0"
|
||||
diff-lines "^1.1.1"
|
||||
git-apply-delta "0.0.7"
|
||||
globalyzer "^0.1.0"
|
||||
globrex "^0.1.2"
|
||||
ignore "^5.0.4"
|
||||
marky "^1.2.1"
|
||||
minimisted "^2.0.0"
|
||||
pako "^1.0.10"
|
||||
pify "^4.0.1"
|
||||
readable-stream "^3.1.1"
|
||||
sha.js "^2.4.9"
|
||||
simple-get "^3.0.2"
|
||||
|
||||
isstream@0.1.x, isstream@~0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
|
||||
|
@ -18940,6 +19022,11 @@ marksy@^6.1.0:
|
|||
he "^1.1.1"
|
||||
marked "^0.3.12"
|
||||
|
||||
marky@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/marky/-/marky-1.2.1.tgz#a3fcf82ffd357756b8b8affec9fdbf3a30dc1b02"
|
||||
integrity sha512-md9k+Gxa3qLH6sUKpeC2CNkJK/Ld+bEz5X96nYwloqphQE0CKCVEKco/6jxEZixinqNdz5RFi/KaCyfbMDMAXQ==
|
||||
|
||||
material-colors@^1.2.1:
|
||||
version "1.2.5"
|
||||
resolved "https://registry.yarnpkg.com/material-colors/-/material-colors-1.2.5.tgz#5292593e6754cb1bcc2b98030e4e0d6a3afc9ea1"
|
||||
|
@ -19370,6 +19457,13 @@ minimist@~0.0.1:
|
|||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
|
||||
integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=
|
||||
|
||||
minimisted@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/minimisted/-/minimisted-2.0.0.tgz#5e3295e74ed701b1cbeaa863a888181d6efbe8ce"
|
||||
integrity sha512-oP88Dw3LK/pdrKyMdlbmg3W50969UNr4ctISzJfPl+YPYHTAOrS+dihXnsgRNKSRIzDsrnV3eE2CCVlZbpOKdQ==
|
||||
dependencies:
|
||||
minimist "^1.2.0"
|
||||
|
||||
minimost@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/minimost/-/minimost-1.0.0.tgz#1d07954aa0268873408b95552fbffc5977dfc78b"
|
||||
|
@ -20993,7 +21087,7 @@ pako@^0.2.5:
|
|||
resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75"
|
||||
integrity sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=
|
||||
|
||||
pako@^1.0.5, pako@~1.0.2:
|
||||
pako@^1.0.10, pako@^1.0.5, pako@~1.0.2:
|
||||
version "1.0.10"
|
||||
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732"
|
||||
integrity sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==
|
||||
|
@ -21914,6 +22008,11 @@ pretty-ms@^4.0.0:
|
|||
dependencies:
|
||||
parse-ms "^2.0.0"
|
||||
|
||||
printj@~1.1.0:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222"
|
||||
integrity sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==
|
||||
|
||||
prismjs@^1.8.4, prismjs@~1.16.0:
|
||||
version "1.16.0"
|
||||
resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.16.0.tgz#406eb2c8aacb0f5f0f1167930cb83835d10a4308"
|
||||
|
@ -25178,6 +25277,14 @@ sha.js@^2.4.0, sha.js@^2.4.8:
|
|||
inherits "^2.0.1"
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
sha.js@^2.4.9:
|
||||
version "2.4.11"
|
||||
resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7"
|
||||
integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==
|
||||
dependencies:
|
||||
inherits "^2.0.1"
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
shallow-clone@^0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-0.1.2.tgz#5909e874ba77106d73ac414cfec1ffca87d97060"
|
||||
|
@ -25287,6 +25394,20 @@ signal-exit@^3.0.0, signal-exit@^3.0.2:
|
|||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
|
||||
integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=
|
||||
|
||||
simple-concat@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6"
|
||||
integrity sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=
|
||||
|
||||
simple-get@^3.0.2:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.0.3.tgz#924528ac3f9d7718ce5e9ec1b1a69c0be4d62efa"
|
||||
integrity sha512-Wvre/Jq5vgoz31Z9stYWPLn0PqRqmBDpFSdypAnHu5AvRVCYPRYGnvryNLiXu8GOBNDH82J2FRHUGMjjHUpXFw==
|
||||
dependencies:
|
||||
decompress-response "^3.3.0"
|
||||
once "^1.3.1"
|
||||
simple-concat "^1.0.0"
|
||||
|
||||
simple-git@1.116.0:
|
||||
version "1.116.0"
|
||||
resolved "https://registry.yarnpkg.com/simple-git/-/simple-git-1.116.0.tgz#ea6e533466f1e0152186e306e004d4eefa6e3e00"
|
||||
|
@ -27091,6 +27212,11 @@ to-through@^2.0.0:
|
|||
dependencies:
|
||||
through2 "^2.0.3"
|
||||
|
||||
to-utf8@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/to-utf8/-/to-utf8-0.0.1.tgz#d17aea72ff2fba39b9e43601be7b3ff72e089852"
|
||||
integrity sha1-0Xrqcv8vujm55DYBvns/9y4ImFI=
|
||||
|
||||
toggle-selection@^1.0.3:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32"
|
||||
|
@ -28453,6 +28579,11 @@ value-or-function@^3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/value-or-function/-/value-or-function-3.0.0.tgz#1c243a50b595c1be54a754bfece8563b9ff8d813"
|
||||
integrity sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=
|
||||
|
||||
varint@0.0.3:
|
||||
version "0.0.3"
|
||||
resolved "https://registry.yarnpkg.com/varint/-/varint-0.0.3.tgz#b821de9b04b38b3cd22f72c18d94a9fb72ab3518"
|
||||
integrity sha1-uCHemwSzizzSL3LBjZSp+3KrNRg=
|
||||
|
||||
vary@^1, vary@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue