Skip to content

Commit

Permalink
Refactor branch/tag resolution for git dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
Volune committed Jul 17, 2017
1 parent 7a053e2 commit 835eb20
Show file tree
Hide file tree
Showing 7 changed files with 508 additions and 177 deletions.
108 changes: 52 additions & 56 deletions __tests__/util/git.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
/* @flow */

jest.mock('../../src/util/child.js', () => {
const realChild = (require: any).requireActual('../../src/util/child.js');

realChild.spawn = jest.fn(() => Promise.resolve(''));

return realChild;
});

jest.mock('../../src/util/git/git-spawn.js', () => ({
spawn: jest.fn(([command]) => {
switch (command) {
case 'ls-remote':
return `ref: refs/heads/master HEAD
7a053e2ca07d19b2e2eebeeb0c27edaacfd67904 HEAD`;
case 'rev-list':
return Promise.resolve('7a053e2ca07d19b2e2eebeeb0c27edaacfd67904 Fix ...');
}
return Promise.resolve('');
}),
}));

import Config from '../../src/config.js';
import Git from '../../src/util/git.js';
import {spawn} from '../../src/util/child.js';
import {spawn as spawnGit} from '../../src/util/git/git-spawn.js';
import {NoopReporter} from '../../src/reporters/index.js';

jasmine.DEFAULT_TIMEOUT_INTERVAL = 90000;
Expand Down Expand Up @@ -72,15 +78,6 @@ test('npmUrlToGitUrl', () => {
});
});

test('isCommitHash', () => {
expect(Git.isCommitHash('ca82a6dff817ec66f44312307202690a93763949')).toBeTruthy();
expect(Git.isCommitHash('abc12')).toBeTruthy();
expect(Git.isCommitHash('')).toBeFalsy();
expect(Git.isCommitHash('abc12_')).toBeFalsy();
expect(Git.isCommitHash('gccda')).toBeFalsy();
expect(Git.isCommitHash('abC12')).toBeFalsy();
});

test('secureGitUrl', async function(): Promise<void> {
const reporter = new NoopReporter();

Expand Down Expand Up @@ -109,44 +106,43 @@ test('secureGitUrl', async function(): Promise<void> {
expect(gitURL.repository).toEqual('https://github.com/yarnpkg/yarn.git');
});

test('parseRefs', () => {
expect(Git.parseRefs(`64b2c0cee9e829f73c5ad32b8cc8cb6f3bec65bb refs/tags/v4.2.2`)).toMatchObject({
'v4.2.2': '64b2c0cee9e829f73c5ad32b8cc8cb6f3bec65bb',
});

expect(
Git.parseRefs(`ebeb6eafceb61dd08441ffe086c77eb472842494 refs/tags/v0.21.0
70e76d174b0c7d001d2cd608a16c94498496e92d refs/tags/v0.21.0^{}
de43f4a993d1e08cd930ee22ecb2bac727f53449 refs/tags/v0.21.0-pre`),
).toMatchObject({
'v0.21.0': '70e76d174b0c7d001d2cd608a16c94498496e92d',
'v0.21.0-pre': 'de43f4a993d1e08cd930ee22ecb2bac727f53449',
});

expect(
Git.parseRefs(`**********
This is a custom response header
as described in: https://github.com/yarnpkg/yarn/issues/3325
**********
ebeb6eafceb61dd08441ffe086c77eb472842494 refs/tags/v0.21.0
70e76d174b0c7d001d2cd608a16c94498496e92d refs/tags/v0.21.0^{}
de43f4a993d1e08cd930ee22ecb2bac727f53449 refs/tags/v0.21.0-pre`),
).toMatchObject({
'v0.21.0': '70e76d174b0c7d001d2cd608a16c94498496e92d',
'v0.21.0-pre': 'de43f4a993d1e08cd930ee22ecb2bac727f53449',
});
test('resolveDefaultBranch', async () => {
const spawnGitMock = (spawnGit: any).mock;
const config = await Config.create();
const git = new Git(
config,
{
protocol: '',
hostname: undefined,
repository: '',
},
'',
);
expect(await git.resolveDefaultBranch()).toEqual({
sha: '7a053e2ca07d19b2e2eebeeb0c27edaacfd67904',
ref: 'refs/heads/master',
});
const lastCall = spawnGitMock.calls[spawnGitMock.calls.length - 1];
expect(lastCall[0]).toContain('ls-remote');
});

test('spawn', () => {
const spawnMock = (spawn: any).mock;

Git.spawn(['status']);

expect(spawnMock.calls[0][2].env).toMatchObject({
GIT_ASKPASS: '',
GIT_TERMINAL_PROMPT: 0,
GIT_SSH_COMMAND: 'ssh -oBatchMode=yes',
...process.env,
});
test('resolveCommit', async () => {
const spawnGitMock = (spawnGit: any).mock;
const config = await Config.create();
const git = new Git(
config,
{
protocol: '',
hostname: undefined,
repository: '',
},
'',
);
expect(await git.resolveCommit('7a053e2')).toEqual({
sha: '7a053e2ca07d19b2e2eebeeb0c27edaacfd67904',
ref: undefined,
});
const lastCall = spawnGitMock.calls[spawnGitMock.calls.length - 1];
expect(lastCall[0]).toContain('rev-list');
expect(lastCall[0]).toContain('7a053e2');
});
154 changes: 154 additions & 0 deletions __tests__/util/git/git-ref-resolver.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/* @flow */

import Config from '../../../src/config.js';
import type {ResolvedSha, GitRefResolvingInterface} from '../../../src/util/git/git-ref-resolver.js';
import {resolveVersion, isCommitSha, parseRefs} from '../../../src/util/git/git-ref-resolver.js';

class GitMock implements GitRefResolvingInterface {
resolveDefaultBranch(): Promise<ResolvedSha> {
return Promise.resolve({sha: '8a41a314e23dc566a6b7e73c757a10d13e3320cf', ref: 'refs/heads/main'});
}
resolveCommit(sha: string): Promise<?ResolvedSha> {
if (sha.startsWith('003ae60')) {
return Promise.resolve({sha: '003ae6063f23a4184736610361f14438a3257c83', ref: undefined});
}
return Promise.resolve(null);
}
}

test('resolveVersion', async () => {
const config = await Config.create();

const refs = {
'refs/heads/1.1': 'eaa56cb34863810060abbec2d755ba51508afedc',
'refs/heads/3.3': '4cff93aa6e8270c3bec988af464d28a164bc3cb2',
'refs/heads/main': '8a41a314e23dc566a6b7e73c757a10d13e3320cf',
'refs/heads/both': '106c28537be070b98ca1effaef6a2bf6414e1e49',
'refs/tags/v1.1.0': '37d5ed001dc4402d5446911c4e1cb589449e7d8d',
'refs/tags/v2.2.0': 'e88209b9513544a22fc3f8660e3d829281dc2c9f',
'refs/tags/both': 'f0dbab0a4345a64f544af37e24fc8187176936a4',
};
const emptyRefs = {};
const git = new GitMock();

const resolve = version => resolveVersion({config, version, refs, git});

expect(await resolve('')).toEqual({
sha: '8a41a314e23dc566a6b7e73c757a10d13e3320cf',
ref: 'refs/heads/main',
});
expect(await resolve('003ae6063f23a4184736610361f14438a3257c83')).toEqual({
sha: '003ae6063f23a4184736610361f14438a3257c83',
ref: undefined,
});
expect(await resolve('003ae60')).toEqual({
sha: '003ae6063f23a4184736610361f14438a3257c83',
ref: undefined,
});
// Test uppercase
expect(await resolve('003AE60')).toEqual({
sha: '003ae6063f23a4184736610361f14438a3257c83',
ref: undefined,
});
expect(await resolve('4cff93aa6e8270c3bec988af464d28a164bc3cb2')).toEqual({
sha: '4cff93aa6e8270c3bec988af464d28a164bc3cb2',
ref: 'refs/heads/3.3',
});
expect(await resolve('4cff93a')).toEqual({
sha: '4cff93aa6e8270c3bec988af464d28a164bc3cb2',
ref: 'refs/heads/3.3',
});
expect(await resolve('main')).toEqual({
sha: '8a41a314e23dc566a6b7e73c757a10d13e3320cf',
ref: 'refs/heads/main',
});
expect(await resolve('1.1')).toEqual({
sha: 'eaa56cb34863810060abbec2d755ba51508afedc',
ref: 'refs/heads/1.1',
});
expect(await resolve('v1.1.0')).toEqual({
sha: '37d5ed001dc4402d5446911c4e1cb589449e7d8d',
ref: 'refs/tags/v1.1.0',
});
// not-existing sha
expect(await resolve('0123456')).toEqual(null);

// Test tags precedence over branches
expect(await resolve('both')).toEqual({
sha: 'f0dbab0a4345a64f544af37e24fc8187176936a4',
ref: 'refs/tags/both',
});
expect(await resolve('refs/heads/both')).toEqual({
sha: '106c28537be070b98ca1effaef6a2bf6414e1e49',
ref: 'refs/heads/both',
});
// Test no match
expect(await resolve('unknown')).toEqual(null);

// Test SemVer

// prefix space to force semver
expect(await resolve(' 1.1')).toEqual({
sha: '37d5ed001dc4402d5446911c4e1cb589449e7d8d',
ref: 'refs/tags/v1.1.0',
});
expect(await resolve('~1.1')).toEqual({
sha: '37d5ed001dc4402d5446911c4e1cb589449e7d8d',
ref: 'refs/tags/v1.1.0',
});
// test on tags first, should not match 3.3
expect(await resolve('*')).toEqual({
sha: 'e88209b9513544a22fc3f8660e3d829281dc2c9f',
ref: 'refs/tags/v2.2.0',
});
// Test * without tags, use default branch
expect(await resolveVersion({config, version: '*', refs: emptyRefs, git})).toEqual({
sha: '8a41a314e23dc566a6b7e73c757a10d13e3320cf',
ref: 'refs/heads/main',
});
});

test('isCommitSha', () => {
expect(isCommitSha('ca82a6dff817ec66f44312307202690a93763949')).toBeTruthy();
expect(isCommitSha('abc12')).toBeTruthy();
expect(isCommitSha('')).toBeFalsy();
expect(isCommitSha('abc12_')).toBeFalsy();
expect(isCommitSha('gccda')).toBeFalsy();
expect(isCommitSha('abC12')).toBeFalsy();
});

test('parseRefs', () => {
expect(parseRefs(`64b2c0cee9e829f73c5ad32b8cc8cb6f3bec65bb refs/tags/v4.2.2`)).toMatchObject({
'refs/tags/v4.2.2': '64b2c0cee9e829f73c5ad32b8cc8cb6f3bec65bb',
});

expect(
parseRefs(`ebeb6eafceb61dd08441ffe086c77eb472842494 refs/tags/v0.21.0
70e76d174b0c7d001d2cd608a16c94498496e92d refs/tags/v0.21.0^{}
de43f4a993d1e08cd930ee22ecb2bac727f53449 refs/tags/v0.21.0-pre`),
).toMatchObject({
'refs/tags/v0.21.0': '70e76d174b0c7d001d2cd608a16c94498496e92d',
'refs/tags/v0.21.0-pre': 'de43f4a993d1e08cd930ee22ecb2bac727f53449',
});

expect(
parseRefs(`ebeb6eafceb61dd08441ffe086c77eb472842494 refs/tags/tag
70e76d174b0c7d001d2cd608a16c94498496e92d refs/merge-requests/38/head`),
).toMatchObject({
'refs/tags/tag': 'ebeb6eafceb61dd08441ffe086c77eb472842494',
});

expect(
parseRefs(`**********
This is a custom response header
as described in: https://github.com/yarnpkg/yarn/issues/3325
**********
ebeb6eafceb61dd08441ffe086c77eb472842494 refs/tags/v0.21.0
70e76d174b0c7d001d2cd608a16c94498496e92d refs/tags/v0.21.0^{}
de43f4a993d1e08cd930ee22ecb2bac727f53449 refs/tags/v0.21.0-pre`),
).toMatchObject({
'refs/tags/v0.21.0': '70e76d174b0c7d001d2cd608a16c94498496e92d',
'refs/tags/v0.21.0-pre': 'de43f4a993d1e08cd930ee22ecb2bac727f53449',
});
});
25 changes: 25 additions & 0 deletions __tests__/util/git/git-spawn.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/* @flow */

jest.mock('../../../src/util/child.js', () => {
const realChild = (require: any).requireActual('../../../src/util/child.js');

realChild.spawn = jest.fn(() => Promise.resolve(''));

return realChild;
});

import {spawn as spawnGit} from '../../../src/util/git/git-spawn.js';
import {spawn} from '../../../src/util/child.js';

test('spawn', () => {
const spawnMock = (spawn: any).mock;

spawnGit(['status']);

expect(spawnMock.calls[0][2].env).toMatchObject({
GIT_ASKPASS: '',
GIT_TERMINAL_PROMPT: 0,
GIT_SSH_COMMAND: 'ssh -oBatchMode=yes',
...process.env,
});
});
3 changes: 1 addition & 2 deletions src/resolvers/exotics/hosted-git-resolver.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,7 @@ export default class HostedGitResolver extends ExoticResolver {
throw new Error(this.reporter.lang('hostedGitResolveError'));
}

const refs = Git.parseRefs(out);
return client.setRef(refs);
return client.setRefHosted(out);
}

async resolveOverHTTP(url: string): Promise<Manifest> {
Expand Down
Loading

0 comments on commit 835eb20

Please sign in to comment.