@netlify/git-utils 4.1.2 → 4.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/commits.js CHANGED
@@ -1,26 +1,22 @@
1
- import { git } from './exec.js'
2
-
1
+ import { git } from './exec.js';
3
2
  // Return information on each commit since the `base` commit, such as SHA,
4
3
  // parent commits, author, committer and commit message
5
4
  export const getCommits = function (base, head, cwd) {
6
- const stdout = git(['log', `--pretty=${GIT_PRETTY_FORMAT}`, `${base}...${head}`], cwd)
7
- const commits = stdout.split('\n').map(getCommit)
8
- return commits
9
- }
10
-
5
+ const stdout = git(['log', `--pretty=${GIT_PRETTY_FORMAT}`, `${base}...${head}`], cwd);
6
+ const commits = stdout.split('\n').map(getCommit);
7
+ return commits;
8
+ };
11
9
  // Parse the commit output from a string to a JavaScript object
12
10
  const getCommit = function (line) {
13
- const [sha, parents, authorName, authorEmail, authorDate, committerName, committerEmail, committerDate, message] =
14
- line.split(GIT_PRETTY_SEPARATOR)
15
- return {
16
- sha,
17
- parents,
18
- author: { name: authorName, email: authorEmail, date: authorDate },
19
- committer: { name: committerName, email: committerEmail, date: committerDate },
20
- message,
21
- }
22
- }
23
-
11
+ const [sha, parents, authorName, authorEmail, authorDate, committerName, committerEmail, committerDate, message] = line.split(GIT_PRETTY_SEPARATOR);
12
+ return {
13
+ sha,
14
+ parents,
15
+ author: { name: authorName, email: authorEmail, date: authorDate },
16
+ committer: { name: committerName, email: committerEmail, date: committerDate },
17
+ message,
18
+ };
19
+ };
24
20
  // `git log --pretty` does not have any way of separating tokens, except for
25
21
  // commits being separated by newlines. Since some tokens (like the commit
26
22
  // message or the committer name) might contain a wide range of characters, we
@@ -28,6 +24,6 @@ const getCommit = function (line) {
28
24
  // We choose RS (Record separator) which is a rarely used control character
29
25
  // intended for this very purpose: separating records. It is used by some
30
26
  // formats such as JSON text sequences (RFC 7464).
31
- const GIT_PRETTY_SEPARATOR = '\u001E'
27
+ const GIT_PRETTY_SEPARATOR = '\u001E';
32
28
  // List of commit fields we want to retrieve
33
- const GIT_PRETTY_FORMAT = ['%H', '%p', '%an', '%ae', '%ai', '%cn', '%ce', '%ci', '%f'].join(GIT_PRETTY_SEPARATOR)
29
+ const GIT_PRETTY_FORMAT = ['%H', '%p', '%an', '%ae', '%ai', '%cn', '%ce', '%ci', '%f'].join(GIT_PRETTY_SEPARATOR);
package/lib/diff.js CHANGED
@@ -1,36 +1,28 @@
1
- import { git } from './exec.js'
2
-
1
+ import { git } from './exec.js';
3
2
  // Return the list of modified|created|deleted files according to git, between
4
3
  // the `base` commit and the `HEAD`
5
4
  export const getDiffFiles = function (base, head, cwd) {
6
- const stdout = git(['diff', '--name-status', '--no-renames', `${base}...${head}`], cwd)
7
- const files = stdout.split('\n').map(getDiffFile).filter(Boolean)
8
-
9
- const modifiedFiles = getFilesByType(files, 'M')
10
- const createdFiles = getFilesByType(files, 'A')
11
- const deletedFiles = getFilesByType(files, 'D')
12
- return { modifiedFiles, createdFiles, deletedFiles }
13
- }
14
-
5
+ const stdout = git(['diff', '--name-status', '--no-renames', `${base}...${head}`], cwd);
6
+ const files = stdout.split('\n').map(getDiffFile).filter(Boolean);
7
+ const modifiedFiles = getFilesByType(files, 'M');
8
+ const createdFiles = getFilesByType(files, 'A');
9
+ const deletedFiles = getFilesByType(files, 'D');
10
+ return { modifiedFiles, createdFiles, deletedFiles };
11
+ };
15
12
  // Parse each `git diff` line
16
13
  const getDiffFile = function (line) {
17
- const result = DIFF_FILE_REGEXP.exec(line)
18
-
19
- // Happens for example when `base` is invalid
20
- if (result === null) {
21
- return
22
- }
23
-
24
- const [, type, filepath] = result
25
- return { type, filepath }
26
- }
27
-
28
- const DIFF_FILE_REGEXP = /([ADM])\s+(.*)/
29
-
14
+ const result = DIFF_FILE_REGEXP.exec(line);
15
+ // Happens for example when `base` is invalid
16
+ if (result === null) {
17
+ return;
18
+ }
19
+ const [, type, filepath] = result;
20
+ return { type, filepath };
21
+ };
22
+ const DIFF_FILE_REGEXP = /([ADM])\s+(.*)/;
30
23
  const getFilesByType = function (files, type) {
31
- return files.filter((file) => file.type === type).map(getFilepath)
32
- }
33
-
24
+ return files.filter((file) => file.type === type).map(getFilepath);
25
+ };
34
26
  const getFilepath = function ({ filepath }) {
35
- return filepath
36
- }
27
+ return filepath;
28
+ };
package/lib/exec.js CHANGED
@@ -1,44 +1,37 @@
1
- import process from 'process'
2
-
3
- import { execaSync } from 'execa'
4
- import moize from 'moize'
5
- import { pathExistsSync } from 'path-exists'
6
-
1
+ import process from 'process';
2
+ import { execaSync } from 'execa';
3
+ import moize from 'moize';
4
+ import { pathExistsSync } from 'path-exists';
7
5
  // Fires the `git` binary. Memoized.
8
6
  const mGit = function (args, cwd) {
9
- const cwdA = safeGetCwd(cwd)
10
- try {
11
- const { stdout } = execaSync('git', args, { cwd: cwdA })
12
- return stdout
13
- } catch (error) {
14
- // The child process `error.message` includes stderr and stdout output which most of the times contains duplicate
15
- // information. We rely on `error.shortMessage` instead.
16
- error.message = error.shortMessage
17
- throw error
18
- }
19
- }
20
-
21
- // eslint-disable-next-line no-magic-numbers
22
- export const git = moize(mGit, { isDeepEqual: true, maxSize: 1e3 })
23
-
7
+ const cwdA = safeGetCwd(cwd);
8
+ try {
9
+ const { stdout } = execaSync('git', args, { cwd: cwdA });
10
+ return stdout;
11
+ }
12
+ catch (error) {
13
+ // The child process `error.message` includes stderr and stdout output which most of the times contains duplicate
14
+ // information. We rely on `error.shortMessage` instead.
15
+ error.message = error.shortMessage;
16
+ throw error;
17
+ }
18
+ };
19
+ export const git = moize(mGit, { isDeepEqual: true, maxSize: 1e3 });
24
20
  const safeGetCwd = function (cwd) {
25
- const cwdA = getCwdValue(cwd)
26
-
27
- if (!pathExistsSync(cwdA)) {
28
- throw new Error(`Current directory does not exist: ${cwdA}`)
29
- }
30
-
31
- return cwdA
32
- }
33
-
21
+ const cwdA = getCwdValue(cwd);
22
+ if (!pathExistsSync(cwdA)) {
23
+ throw new Error(`Current directory does not exist: ${cwdA}`);
24
+ }
25
+ return cwdA;
26
+ };
34
27
  const getCwdValue = function (cwd) {
35
- if (cwd !== undefined) {
36
- return cwd
37
- }
38
-
39
- try {
40
- return process.cwd()
41
- } catch {
42
- throw new Error('Current directory does not exist')
43
- }
44
- }
28
+ if (cwd !== undefined) {
29
+ return cwd;
30
+ }
31
+ try {
32
+ return process.cwd();
33
+ }
34
+ catch {
35
+ throw new Error('Current directory does not exist');
36
+ }
37
+ };
package/lib/main.js CHANGED
@@ -1,16 +1,15 @@
1
- import { getCommits } from './commits.js'
2
- import { getDiffFiles } from './diff.js'
3
- import { fileMatch } from './match.js'
4
- import { getBase, getHead } from './refs.js'
5
- import { getLinesOfCode } from './stats.js'
6
-
1
+ import { getCommits } from './commits.js';
2
+ import { getDiffFiles } from './diff.js';
3
+ import { fileMatch } from './match.js';
4
+ import { getBase, getHead } from './refs.js';
5
+ import { getLinesOfCode } from './stats.js';
7
6
  // Main entry point to the git utilities
8
7
  export const getGitUtils = function ({ base, head, cwd } = {}) {
9
- const headA = getHead(cwd, head)
10
- const baseA = getBase(base, headA, cwd)
11
- const { modifiedFiles, createdFiles, deletedFiles } = getDiffFiles(baseA, headA, cwd)
12
- const commits = getCommits(baseA, headA, cwd)
13
- const linesOfCode = getLinesOfCode(baseA, headA, cwd)
14
- const fileMatchA = fileMatch.bind(null, { modifiedFiles, createdFiles, deletedFiles })
15
- return { modifiedFiles, createdFiles, deletedFiles, commits, linesOfCode, fileMatch: fileMatchA }
16
- }
8
+ const headA = getHead(cwd, head);
9
+ const baseA = getBase(base, headA, cwd);
10
+ const { modifiedFiles, createdFiles, deletedFiles } = getDiffFiles(baseA, headA, cwd);
11
+ const commits = getCommits(baseA, headA, cwd);
12
+ const linesOfCode = getLinesOfCode(baseA, headA, cwd);
13
+ const fileMatchA = fileMatch.bind(null, { modifiedFiles, createdFiles, deletedFiles });
14
+ return { modifiedFiles, createdFiles, deletedFiles, commits, linesOfCode, fileMatch: fileMatchA };
15
+ };
package/lib/match.js CHANGED
@@ -1,14 +1,13 @@
1
- import mapObj from 'map-obj'
2
- import micromatch from 'micromatch'
3
-
1
+ import mapObj from 'map-obj';
2
+ import micromatch from 'micromatch';
4
3
  // Return functions that return modified|created|deleted files filtered by a
5
4
  // globbing pattern
6
5
  export const fileMatch = function ({ modifiedFiles, createdFiles, deletedFiles }, ...patterns) {
7
- const matchFiles = {
8
- modified: modifiedFiles,
9
- created: createdFiles,
10
- deleted: deletedFiles,
11
- edited: [...modifiedFiles, ...createdFiles],
12
- }
13
- return mapObj(matchFiles, (key, paths) => [key, micromatch(paths, patterns)])
14
- }
6
+ const matchFiles = {
7
+ modified: modifiedFiles,
8
+ created: createdFiles,
9
+ deleted: deletedFiles,
10
+ edited: [...modifiedFiles, ...createdFiles],
11
+ };
12
+ return mapObj(matchFiles, (key, paths) => [key, micromatch(paths, patterns)]);
13
+ };
package/lib/refs.js CHANGED
@@ -1,63 +1,54 @@
1
- import { env } from 'process'
2
-
3
- import { git } from './exec.js'
4
-
1
+ import { env } from 'process';
2
+ import { git } from './exec.js';
5
3
  // Retrieve the `head` commit
6
4
  export const getHead = function (cwd, head = 'HEAD') {
7
- const result = checkRef(head, cwd)
8
- if (result.error !== undefined) {
9
- throwError('head', result)
10
- }
11
- return result.ref
12
- }
13
-
5
+ const result = checkRef(head, cwd);
6
+ if (result.error !== undefined) {
7
+ throwError('head', result);
8
+ }
9
+ return result.ref;
10
+ };
14
11
  // Retrieve the `base` commit
15
12
  export const getBase = function (base, head, cwd) {
16
- const refs = getBaseRefs(base, head)
17
- const { ref } = findRef(refs, cwd)
18
- return ref
19
- }
20
-
13
+ const refs = getBaseRefs(base, head);
14
+ const { ref } = findRef(refs, cwd);
15
+ return ref;
16
+ };
21
17
  const getBaseRefs = function (base, head) {
22
- if (base !== undefined) {
23
- return [base]
24
- }
25
-
26
- if (env.CACHED_COMMIT_REF) {
27
- return [env.CACHED_COMMIT_REF]
28
- }
29
-
30
- // Some git repositories are missing `master` or `main` branches, so we also try HEAD^.
31
- // We end with HEAD as a failsafe.
32
- return ['main', 'master', `${head}^`, head]
33
- }
34
-
18
+ if (base !== undefined) {
19
+ return [base];
20
+ }
21
+ if (env.CACHED_COMMIT_REF) {
22
+ return [env.CACHED_COMMIT_REF];
23
+ }
24
+ // Some git repositories are missing `master` or `main` branches, so we also try HEAD^.
25
+ // We end with HEAD as a failsafe.
26
+ return ['main', 'master', `${head}^`, head];
27
+ };
35
28
  // Use the first commit that exists
36
29
  const findRef = function (refs, cwd) {
37
- const results = refs.map((ref) => checkRef(ref, cwd))
38
- const result = results.find(refExists)
39
- if (result === undefined) {
40
- throwError('base', results[0])
41
- }
42
- return result
43
- }
44
-
30
+ const results = refs.map((ref) => checkRef(ref, cwd));
31
+ const result = results.find(refExists);
32
+ if (result === undefined) {
33
+ throwError('base', results[0]);
34
+ }
35
+ return result;
36
+ };
45
37
  // Check if a commit exists
46
38
  const checkRef = function (ref, cwd) {
47
- try {
48
- git(['rev-parse', ref], cwd)
49
- return { ref }
50
- } catch (error) {
51
- return { ref, error }
52
- }
53
- }
54
-
39
+ try {
40
+ git(['rev-parse', ref], cwd);
41
+ return { ref };
42
+ }
43
+ catch (error) {
44
+ return { ref, error };
45
+ }
46
+ };
55
47
  const refExists = function ({ error }) {
56
- return error === undefined
57
- }
58
-
48
+ return error === undefined;
49
+ };
59
50
  const throwError = function (name, { ref, error: { message, stderr } }) {
60
- const messages = [message, stderr].filter(Boolean).join('\n')
61
- const messageA = `Invalid ${name} commit ${ref}\n${messages}`
62
- throw new Error(messageA)
63
- }
51
+ const messages = [message, stderr].filter(Boolean).join('\n');
52
+ const messageA = `Invalid ${name} commit ${ref}\n${messages}`;
53
+ throw new Error(messageA);
54
+ };
package/lib/stats.js CHANGED
@@ -1,23 +1,18 @@
1
- import { git } from './exec.js'
2
-
1
+ import { git } from './exec.js';
3
2
  // Returns the number of lines of code added, removed or modified since the
4
3
  // `base` commit
5
4
  export const getLinesOfCode = function (base, head, cwd) {
6
- const stdout = git(['diff', '--shortstat', `${base}...${head}`], cwd)
7
- const insertions = parseStdout(stdout, INSERTION_REGEXP)
8
- const deletions = parseStdout(stdout, DELETION_REGEXP)
9
- return insertions + deletions
10
- }
11
-
5
+ const stdout = git(['diff', '--shortstat', `${base}...${head}`], cwd);
6
+ const insertions = parseStdout(stdout, INSERTION_REGEXP);
7
+ const deletions = parseStdout(stdout, DELETION_REGEXP);
8
+ return insertions + deletions;
9
+ };
12
10
  const parseStdout = function (stdout, regexp) {
13
- const result = regexp.exec(stdout)
14
-
15
- if (result === null) {
16
- return 0
17
- }
18
-
19
- return Number(result[1])
20
- }
21
-
22
- const INSERTION_REGEXP = /(\d+) insertion/
23
- const DELETION_REGEXP = /(\d+) deletion/
11
+ const result = regexp.exec(stdout);
12
+ if (result === null) {
13
+ return 0;
14
+ }
15
+ return Number(result[1]);
16
+ };
17
+ const INSERTION_REGEXP = /(\d+) insertion/;
18
+ const DELETION_REGEXP = /(\d+) deletion/;
package/package.json CHANGED
@@ -1,18 +1,21 @@
1
1
  {
2
2
  "name": "@netlify/git-utils",
3
- "version": "4.1.2",
3
+ "version": "4.1.3",
4
4
  "description": "Utility for dealing with modified, created, deleted files since a git commit",
5
5
  "type": "module",
6
6
  "exports": "./lib/main.js",
7
7
  "main": "./lib/main.js",
8
+ "types": "./lib/main.d.ts",
8
9
  "files": [
9
10
  "lib/**/*.js"
10
11
  ],
11
12
  "author": "Netlify Inc.",
12
13
  "scripts": {
13
- "prepublishOnly": "cd ../../ && npm run prepublishOnly",
14
14
  "prebuild": "rm -rf lib",
15
- "build": "cp -a src lib/"
15
+ "build": "tsc",
16
+ "test:dev": "ava",
17
+ "test:ci": "c8 -r lcovonly -r text -r json ava",
18
+ "test:measure": "node tools/tests_duration.mjs"
16
19
  },
17
20
  "keywords": [
18
21
  "nodejs",
@@ -54,9 +57,11 @@
54
57
  "path-exists": "^5.0.0"
55
58
  },
56
59
  "devDependencies": {
57
- "ava": "^4.0.0"
60
+ "ava": "^4.0.0",
61
+ "c8": "^7.12.0"
58
62
  },
59
63
  "engines": {
60
64
  "node": "^12.20.0 || ^14.14.0 || >=16.0.0"
61
- }
65
+ },
66
+ "gitHead": "2b070fd93c4ea7fbdd47d0e25f49b24f2115e4a7"
62
67
  }