Skip to content

Commit

Permalink
Add new fromClosestTag function (#68)
Browse files Browse the repository at this point in the history
  • Loading branch information
maxmilton committed Oct 5, 2021
1 parent ef7dd0a commit 8595ae2
Show file tree
Hide file tree
Showing 3 changed files with 157 additions and 5 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,18 @@ const state = isDirty();
console.log(state); // false
```

### Commits away from closest tag

Get the number of commits from the closest tagged commit to the current HEAD commit.

```js
import { fromClosestTag } from 'git-ref';

const count = fromClosestTag();

console.log(count); // 0
```

## Changelog

See [releases on GitHub](https://github.com/maxmilton/git-ref/releases).
Expand Down
32 changes: 28 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* eslint-disable no-console */

import { execSync } from 'child_process';

/**
Expand All @@ -16,7 +18,6 @@ export function gitRef(cwd?: string): string {
});
reference = result.toString().trim();
} catch (error) {
// eslint-disable-next-line no-console
console.error(error);
}

Expand All @@ -32,7 +33,7 @@ export default gitRef;
* the first 7 characters (default `false`).
* @param cwd - Modify the working directory git is executed in (default is the
* directory of the current node process).
* @returns The git commit hash.
* @returns A git commit hash.
*/
export function gitHash(long?: boolean, cwd?: string): string {
let hash = '';
Expand All @@ -43,7 +44,6 @@ export function gitHash(long?: boolean, cwd?: string): string {
});
hash = result.toString().trim();
} catch (error) {
// eslint-disable-next-line no-console
console.error(error);
}

Expand All @@ -64,9 +64,33 @@ export function isDirty(cwd?: string): boolean {
const result = execSync('git status --porcelain', { cwd });
dirty = !!result.toString().trim();
} catch (error) {
// eslint-disable-next-line no-console
console.error(error);
}

return dirty;
}

/**
* Get the number of commits from the closest tagged commit to the HEAD commit.
*
* Note: Unix only due to shell command substitution.
*
* @param cwd - Modify the working directory git is executed in (default is the
* directory of the current node process).
* @returns The number of commits from closest tag to HEAD or -1 when error.
*/
export function fromClosestTag(cwd?: string): number {
let count = -1;

try {
const result = execSync(
'git rev-list $(git describe --abbrev=0)..HEAD --count',
{ cwd },
);
count = +result.toString().trim();
} catch (error) {
console.error(error);
}

return count;
}
118 changes: 117 additions & 1 deletion test/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import * as assert from 'uvu/assert';
import * as allExports from '../src/index';
import { gitHash, gitRef, isDirty } from '../src/index';
import {
fromClosestTag, gitHash, gitRef, isDirty,
} from '../src/index';
import {
createTempDir,
deleteTempDir,
Expand All @@ -16,6 +18,7 @@ describe('exports', (test) => {
['gitRef', '"gitRef" named'],
['gitHash', '"gitHash" named'],
['isDirty', '"isDirty" named'],
['fromClosestTag', '"fromClosestTag" named'],
] as const
).forEach(([name, description]) => {
test(`has a ${description} export`, () => {
Expand Down Expand Up @@ -288,3 +291,116 @@ describe('isDirty', (test) => {
assert.is(result4, false);
});
});

describe('fromClosestTag', (test) => {
test.before(createTempDir);
test.after(deleteTempDir);

test('returns -1 in non-git dir', () => {
const dir = getTempDir('not-git');
const result = fromClosestTag(dir);
assert.is(result, -1);
});

test('returns -1 in repo without commits', () => {
const dir = getTempDir('no-commit');
execCmds(dir, ['git init --quiet']);
const result = fromClosestTag(dir);
assert.is(result, -1);
});

test('returns -1 in repo with uncommitted new file', () => {
const dir = getTempDir('uncommitted-file');
execCmds(dir, ['git init --quiet', 'touch file.txt']);
const result = fromClosestTag(dir);
assert.is(result, -1);
});

test('returns 0 in repo with no tags', () => {
const dir = getTempDir('with-commit');
execCmds(dir, [
'git init --quiet',
'git config user.email "test@test.com"',
'git config user.name "Test Test"',
'touch file1.txt',
'git add file1.txt',
'git commit --quiet --no-gpg-sign -m "commit1"',
]);
const result1 = fromClosestTag(dir);
assert.type(result1, 'number');
assert.is(result1, 0);
execCmds(dir, [
'touch file2.txt',
'git add file2.txt',
'git commit --quiet --no-gpg-sign -m "commit2"',
]);
const result2 = fromClosestTag(dir);
assert.type(result2, 'number');
assert.is(result2, 0);
execCmds(dir, [
'touch file3.txt',
'git add file3.txt',
'git commit --quiet --no-gpg-sign -m "commit3"',
]);
const result3 = fromClosestTag(dir);
assert.type(result3, 'number');
assert.is(result3, 0);
});

test('returns count in repo with commits after tag', () => {
const dir = getTempDir('tag-commits');
execCmds(dir, [
'git init --quiet',
'git config user.email "test@test.com"',
'git config user.name "Test Test"',
'touch file1.txt',
'git add file1.txt',
'git commit --quiet --no-gpg-sign -m "commit1"',
]);
const result1 = fromClosestTag(dir);
assert.type(result1, 'number');
assert.is(result1, 0);
execCmds(dir, [
'touch file2.txt',
'git add file2.txt',
'git commit --quiet --no-gpg-sign -m "commit2"',
'git tag --no-sign -m "v1" v1',
]);
const result2 = fromClosestTag(dir);
assert.type(result2, 'number');
assert.is(result2, 0);
execCmds(dir, [
'touch file3.txt',
'git add file3.txt',
'git commit --quiet --no-gpg-sign -m "commit3"',
]);
const result3 = fromClosestTag(dir);
assert.type(result3, 'number');
assert.is(result3, 1);
execCmds(dir, [
'touch file4.txt',
'git add file4.txt',
'git commit --quiet --no-gpg-sign -m "commit4"',
]);
const result4 = fromClosestTag(dir);
assert.type(result4, 'number');
assert.is(result4, 2);
execCmds(dir, [
'touch file5.txt',
'git add file5.txt',
'git commit --quiet --no-gpg-sign -m "commit5"',
'git tag --no-sign -m "v2" v2',
]);
const result5 = fromClosestTag(dir);
assert.type(result5, 'number');
assert.is(result5, 0);
execCmds(dir, [
'touch file6.txt',
'git add file6.txt',
'git commit --quiet --no-gpg-sign -m "commit6"',
]);
const result6 = fromClosestTag(dir);
assert.type(result6, 'number');
assert.is(result6, 1);
});
});

0 comments on commit 8595ae2

Please sign in to comment.