Skip to content

Commit

Permalink
fix: retrieve branch from repo with a detached head
Browse files Browse the repository at this point in the history
  • Loading branch information
pvdlg committed Apr 27, 2018
1 parent b0a335c commit 716b7e6
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 17 deletions.
8 changes: 7 additions & 1 deletion lib/git.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,13 @@ function head() {

function branch() {
try {
return execa.sync('git', ['rev-parse', '--abbrev-ref', 'HEAD']).stdout;
const branch = execa
.sync('git', ['show', '-s', '--pretty=%d', 'HEAD'])
.stdout.match(/\(?(.*)\)?/)[1]
.split(', ')
.find(branch => branch.startsWith('origin/'));

return branch ? branch.match(/^origin\/(.+)/)[1] : execa.sync('git', ['rev-parse', '--abbrev-ref', 'HEAD']).stdout;
} catch (err) {
return undefined;
}
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"devDependencies": {
"ava": "^0.25.0",
"codecov": "^3.0.0",
"file-url": "^2.0.2",
"nyc": "^11.1.0",
"semantic-release": "^15.0.0",
"tempy": "^0.2.1",
Expand Down
7 changes: 3 additions & 4 deletions test/codebuild.test.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import test from 'ava';
import codebuild from '../lib/codebuild';
import {gitRepo, gitCommit} from './helpers/git-utils';
import {gitRepo, gitHead} from './helpers/git-utils';

// Save the current working diretory
const cwd = process.cwd();

test.beforeEach(async () => {
await gitRepo();
await gitRepo(true);
});

test.afterEach.always(() => {
Expand All @@ -15,15 +15,14 @@ test.afterEach.always(() => {
});

test('Push', async t => {
const commit = await gitCommit();
process.env.CODEBUILD_BUILD_ID = 'env-ci:40cc72d2-acd5-46f4-a86b-6a3dcd2a39a0';
process.env.AWS_REGION = 'us-east-1';
process.env.PWD = '/codebuild/output/src807365521/src/github.com/owner/repo';

t.deepEqual(codebuild.configuration(), {
name: 'AWS CodeBuild',
service: 'codebuild',
commit,
commit: await gitHead(),
build: 'env-ci:40cc72d2-acd5-46f4-a86b-6a3dcd2a39a0',
branch: 'master',
buildUrl:
Expand Down
13 changes: 8 additions & 5 deletions test/git.test.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
import test from 'ava';
import git from '../lib/git';
import {gitRepo, gitCommit} from './helpers/git-utils';
import {gitRepo, gitCommit, gitHead} from './helpers/git-utils';

// Save the current working diretory
const cwd = process.cwd();

test.beforeEach(async () => {
await gitRepo('master');
});

test.afterEach.always(() => {
// Restore the current working directory
process.chdir(cwd);
});

test.serial('Git repository', async t => {
await gitRepo();
const commit = await gitCommit();

t.deepEqual(git.configuration(), {commit, branch: 'master'});
});

test.serial('Git repository with detached head', async t => {
await gitRepo(true);

t.deepEqual(git.configuration(), {commit: await gitHead(), branch: 'master'});
});
76 changes: 69 additions & 7 deletions test/helpers/git-utils.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,77 @@
import tempy from 'tempy';
import execa from 'execa';
import fileUrl from 'file-url';

/**
* Create a git repository and change the current working directory to the repository root.
* Create a temporary git repository.
* If `withRemote` is `true`, creates a bare repository, initialize it and create a shallow clone. Change the current working directory to the clone root.
* If `withRemote` is `false`, creates a regular repository and initialize it. Change the current working directory to the repository root.
*
* @method gitRepo
* @param {String} [branch='master'] The branch to initialize.
* @return {String} The path of the repository otherwise.
* @param {Boolean} withRemote `true` to create a shallow clone of a bare repository.
* @param {String} [branc='master'] The branch to initialize.
* @return {String} The path of the clone if `withRemote` is `true`, the path of the repository otherwise.
*/
export async function gitRepo(branch = 'master') {
export async function gitRepo(withRemote, branch = 'master') {
const dir = tempy.directory();

process.chdir(dir);
await execa('git', ['init']);
await execa('git', ['checkout', '-b', branch]);
await execa('git', ['init'].concat(withRemote ? ['--bare'] : []));

if (withRemote) {
await initBareRepo(fileUrl(dir), branch);
await gitShallowClone(fileUrl(dir));
} else {
await gitCheckout(branch);
}
return fileUrl(dir);
}

/**
* Initialize an existing bare repository:
* - Clone the repository
* - Change the current working directory to the clone root
* - Create a default branch
* - Create an initial commits
* - Push to origin
*
* @param {String} origin The URL of the bare repository.
* @param {String} [branch='master'] the branch to initialize.
*/
export async function initBareRepo(origin, branch = 'master') {
const clone = tempy.directory();
await execa('git', ['clone', '--no-hardlinks', origin, clone]);
process.chdir(clone);
await gitCheckout(branch);
await gitCommit('Initial commit');
await execa('git', ['push', origin, branch]);
}

/**
* Create a shallow clone of a git repository and change the current working directory to the cloned repository root.
* The shallow will contain a limited number of commit and no tags.
*
* @param {String} origin The path of the repository to clone.
* @param {Number} [depth=1] The number of commit to clone.
* @return {String} The path of the cloned repository.
*/
export async function gitShallowClone(origin, branch = 'master', depth = 1) {
const dir = tempy.directory();

process.chdir(dir);
await execa('git', ['clone', '--no-hardlinks', '--no-tags', '-b', branch, '--depth', depth, origin, dir]);
return dir;
}

/**
* Checkout a branch on the current git repository.
*
* @param {String} branch Branch name.
* @param {boolean} create `true` to create the branche ans switch, `false` to only switch.
*/
export async function gitCheckout(branch, create = true) {
await execa('git', create ? ['checkout', '-b', branch] : ['checkout', branch]);
}

/**
* Create commit on the current git repository.
*
Expand All @@ -28,3 +83,10 @@ export async function gitCommit(message = 'Test commit message') {
await execa('git', ['commit', '-m', message, '--allow-empty', '--no-gpg-sign']);
return execa.stdout('git', ['rev-parse', 'HEAD']);
}

/**
* @return {String} The sha of the head commit in the current git repository.
*/
export async function gitHead() {
return execa.stdout('git', ['rev-parse', 'HEAD']);
}

0 comments on commit 716b7e6

Please sign in to comment.