@netlify/git-utils 2.0.1 → 4.1.0
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/README.md +52 -56
- package/package.json +5 -3
- package/src/commits.js +25 -13
- package/src/diff.js +2 -6
- package/src/exec.js +6 -10
- package/src/main.js +6 -10
- package/src/match.js +3 -7
- package/src/refs.js +4 -8
- package/src/stats.js +2 -6
package/README.md
CHANGED
|
@@ -9,38 +9,36 @@ Utility for dealing with modified, created, deleted files since a git commit.
|
|
|
9
9
|
|
|
10
10
|
```js
|
|
11
11
|
/* Export the Netlify Plugin */
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
},
|
|
12
|
+
export const onPreBuild = function ({ utils }) {
|
|
13
|
+
const { git } = utils
|
|
14
|
+
|
|
15
|
+
/* Do stuff if files modified */
|
|
16
|
+
if (git.modifiedFiles.length !== 0) {
|
|
17
|
+
console.log('Modified files:', git.modifiedFiles)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/* Do stuff only if html code edited */
|
|
21
|
+
const htmlFiles = git.fileMatch('**/*.html')
|
|
22
|
+
console.log('html files git info:', htmlFiles)
|
|
23
|
+
|
|
24
|
+
if (htmlFiles.edited.length !== 0) {
|
|
25
|
+
console.log('>> Run thing because HTML has changed\n')
|
|
26
|
+
}
|
|
27
|
+
//
|
|
28
|
+
/* Do stuff only if markdown files edited */
|
|
29
|
+
const markdownFiles = git.fileMatch('**/*.md')
|
|
30
|
+
console.log('markdown files git info:', markdownFiles)
|
|
31
|
+
|
|
32
|
+
if (markdownFiles.modified.length !== 0) {
|
|
33
|
+
console.log('>> Run thing because Markdown files have been created/changed/deleted\n')
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/* Do stuff only if css files edited */
|
|
37
|
+
const cssFiles = git.fileMatch('**/*.css')
|
|
38
|
+
if (cssFiles.deleted.length !== 0) {
|
|
39
|
+
console.log('>> Run thing because css files have been deleted\n')
|
|
40
|
+
console.log(cssFiles)
|
|
41
|
+
}
|
|
44
42
|
}
|
|
45
43
|
```
|
|
46
44
|
|
|
@@ -49,36 +47,34 @@ module.exports = {
|
|
|
49
47
|
The `git` util includes the following signature.
|
|
50
48
|
|
|
51
49
|
```js
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
//
|
|
64
|
-
},
|
|
50
|
+
export const onPreBuild = function ({ utils }) {
|
|
51
|
+
console.log(utils.git)
|
|
52
|
+
// {
|
|
53
|
+
// fileMatch: [Function], <-- Lookup function. See below
|
|
54
|
+
// modifiedFiles: [ Array of all modified files ],
|
|
55
|
+
// createdFiles: [ Array of all created files ],
|
|
56
|
+
// deletedFiles: [ Array of all deleted files ],
|
|
57
|
+
// commits: [ Array of commits with details ],
|
|
58
|
+
// linesOfCode: [AsyncFunction: linesOfCode] <-- how many lines of code have changed
|
|
59
|
+
// }
|
|
60
|
+
//
|
|
65
61
|
}
|
|
66
62
|
```
|
|
67
63
|
|
|
68
64
|
`git.fileMatch()` is a glob matcher function to detect the git status of a pattern of files.
|
|
69
65
|
|
|
70
|
-
Example:
|
|
71
|
-
|
|
72
66
|
```js
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
//
|
|
77
|
-
//
|
|
78
|
-
//
|
|
79
|
-
//
|
|
80
|
-
//
|
|
81
|
-
//
|
|
67
|
+
export const onPreBuild = function ({ utils }) {
|
|
68
|
+
const cssFiles = utils.git.fileMatch('**/*.css')
|
|
69
|
+
console.log('cssFiles', cssFiles)
|
|
70
|
+
// {
|
|
71
|
+
// modified: [ 'just-changed.css', 'just-changed-two.css' ],
|
|
72
|
+
// created: [ 'just-added.css' ],
|
|
73
|
+
// deleted: [ 'just-deleted.css' ],
|
|
74
|
+
// edited: [ 'just-changed.css', 'just-changed-two.css', 'just-added.css', 'just-deleted.css' ]
|
|
75
|
+
// }
|
|
76
|
+
//
|
|
77
|
+
}
|
|
82
78
|
```
|
|
83
79
|
|
|
84
80
|
## Prior art
|
package/package.json
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@netlify/git-utils",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.1.0",
|
|
4
4
|
"description": "Utility for dealing with modified, created, deleted files since a git commit",
|
|
5
|
-
"
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": "./src/main.js",
|
|
7
|
+
"main": "./src/main.js",
|
|
6
8
|
"files": [
|
|
7
9
|
"src/**/*.js"
|
|
8
10
|
],
|
|
@@ -53,6 +55,6 @@
|
|
|
53
55
|
"ava": "^3.15.0"
|
|
54
56
|
},
|
|
55
57
|
"engines": {
|
|
56
|
-
"node": ">=
|
|
58
|
+
"node": "^12.20.0 || ^14.14.0 || >=16.0.0"
|
|
57
59
|
}
|
|
58
60
|
}
|
package/src/commits.js
CHANGED
|
@@ -1,21 +1,33 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const { git } = require('./exec')
|
|
1
|
+
import { git } from './exec.js'
|
|
4
2
|
|
|
5
3
|
// Return information on each commit since the `base` commit, such as SHA,
|
|
6
4
|
// parent commits, author, committer and commit message
|
|
7
|
-
const getCommits = function (base, head, cwd) {
|
|
8
|
-
const stdout = git(['log', `--pretty
|
|
9
|
-
const commits =
|
|
5
|
+
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)
|
|
10
8
|
return commits
|
|
11
9
|
}
|
|
12
10
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
parents
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
11
|
+
// Parse the commit output from a string to a JavaScript object
|
|
12
|
+
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
|
+
}
|
|
19
22
|
}
|
|
20
23
|
|
|
21
|
-
|
|
24
|
+
// `git log --pretty` does not have any way of separating tokens, except for
|
|
25
|
+
// commits being separated by newlines. Since some tokens (like the commit
|
|
26
|
+
// message or the committer name) might contain a wide range of characters, we
|
|
27
|
+
// need a specific separator.
|
|
28
|
+
// We choose RS (Record separator) which is a rarely used control character
|
|
29
|
+
// intended for this very purpose: separating records. It is used by some
|
|
30
|
+
// formats such as JSON text sequences (RFC 7464).
|
|
31
|
+
const GIT_PRETTY_SEPARATOR = '\u001E'
|
|
32
|
+
// 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)
|
package/src/diff.js
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const { git } = require('./exec')
|
|
1
|
+
import { git } from './exec.js'
|
|
4
2
|
|
|
5
3
|
// Return the list of modified|created|deleted files according to git, between
|
|
6
4
|
// the `base` commit and the `HEAD`
|
|
7
|
-
const getDiffFiles = function (base, head, cwd) {
|
|
5
|
+
export const getDiffFiles = function (base, head, cwd) {
|
|
8
6
|
const stdout = git(['diff', '--name-status', '--no-renames', `${base}...${head}`], cwd)
|
|
9
7
|
const files = stdout.split('\n').map(getDiffFile).filter(Boolean)
|
|
10
8
|
|
|
@@ -36,5 +34,3 @@ const getFilesByType = function (files, type) {
|
|
|
36
34
|
const getFilepath = function ({ filepath }) {
|
|
37
35
|
return filepath
|
|
38
36
|
}
|
|
39
|
-
|
|
40
|
-
module.exports = { getDiffFiles }
|
package/src/exec.js
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
import process from 'process'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const moize = require('moize')
|
|
7
|
-
const pathExists = require('path-exists')
|
|
3
|
+
import execa from 'execa'
|
|
4
|
+
import moize from 'moize'
|
|
5
|
+
import pathExists from 'path-exists'
|
|
8
6
|
|
|
9
7
|
// Fires the `git` binary. Memoized.
|
|
10
8
|
const mGit = function (args, cwd) {
|
|
@@ -21,7 +19,7 @@ const mGit = function (args, cwd) {
|
|
|
21
19
|
}
|
|
22
20
|
|
|
23
21
|
// eslint-disable-next-line no-magic-numbers
|
|
24
|
-
const git = moize(mGit, { isDeepEqual: true, maxSize: 1e3 })
|
|
22
|
+
export const git = moize(mGit, { isDeepEqual: true, maxSize: 1e3 })
|
|
25
23
|
|
|
26
24
|
const safeGetCwd = function (cwd) {
|
|
27
25
|
const cwdA = getCwdValue(cwd)
|
|
@@ -40,9 +38,7 @@ const getCwdValue = function (cwd) {
|
|
|
40
38
|
|
|
41
39
|
try {
|
|
42
40
|
return process.cwd()
|
|
43
|
-
} catch
|
|
41
|
+
} catch {
|
|
44
42
|
throw new Error('Current directory does not exist')
|
|
45
43
|
}
|
|
46
44
|
}
|
|
47
|
-
|
|
48
|
-
module.exports = { git }
|
package/src/main.js
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const { getBase, getHead } = require('./refs')
|
|
7
|
-
const { getLinesOfCode } = require('./stats')
|
|
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'
|
|
8
6
|
|
|
9
7
|
// Main entry point to the git utilities
|
|
10
|
-
const getGitUtils = function ({ base, head, cwd } = {}) {
|
|
8
|
+
export const getGitUtils = function ({ base, head, cwd } = {}) {
|
|
11
9
|
const headA = getHead(cwd, head)
|
|
12
10
|
const baseA = getBase(base, headA, cwd)
|
|
13
11
|
const { modifiedFiles, createdFiles, deletedFiles } = getDiffFiles(baseA, headA, cwd)
|
|
@@ -16,5 +14,3 @@ const getGitUtils = function ({ base, head, cwd } = {}) {
|
|
|
16
14
|
const fileMatchA = fileMatch.bind(null, { modifiedFiles, createdFiles, deletedFiles })
|
|
17
15
|
return { modifiedFiles, createdFiles, deletedFiles, commits, linesOfCode, fileMatch: fileMatchA }
|
|
18
16
|
}
|
|
19
|
-
|
|
20
|
-
module.exports = getGitUtils
|
package/src/match.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const mapObj = require('map-obj')
|
|
4
|
-
const micromatch = require('micromatch')
|
|
1
|
+
import mapObj from 'map-obj'
|
|
2
|
+
import micromatch from 'micromatch'
|
|
5
3
|
|
|
6
4
|
// Return functions that return modified|created|deleted files filtered by a
|
|
7
5
|
// globbing pattern
|
|
8
|
-
const fileMatch = function ({ modifiedFiles, createdFiles, deletedFiles }, ...patterns) {
|
|
6
|
+
export const fileMatch = function ({ modifiedFiles, createdFiles, deletedFiles }, ...patterns) {
|
|
9
7
|
const matchFiles = {
|
|
10
8
|
modified: modifiedFiles,
|
|
11
9
|
created: createdFiles,
|
|
@@ -14,5 +12,3 @@ const fileMatch = function ({ modifiedFiles, createdFiles, deletedFiles }, ...pa
|
|
|
14
12
|
}
|
|
15
13
|
return mapObj(matchFiles, (key, paths) => [key, micromatch(paths, patterns)])
|
|
16
14
|
}
|
|
17
|
-
|
|
18
|
-
module.exports = { fileMatch }
|
package/src/refs.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
import { env } from 'process'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const { git } = require('./exec')
|
|
3
|
+
import { git } from './exec.js'
|
|
6
4
|
|
|
7
5
|
// Retrieve the `head` commit
|
|
8
|
-
const getHead = function (cwd, head = 'HEAD') {
|
|
6
|
+
export const getHead = function (cwd, head = 'HEAD') {
|
|
9
7
|
const result = checkRef(head, cwd)
|
|
10
8
|
if (result.error !== undefined) {
|
|
11
9
|
throwError('head', result)
|
|
@@ -14,7 +12,7 @@ const getHead = function (cwd, head = 'HEAD') {
|
|
|
14
12
|
}
|
|
15
13
|
|
|
16
14
|
// Retrieve the `base` commit
|
|
17
|
-
const getBase = function (base, head, cwd) {
|
|
15
|
+
export const getBase = function (base, head, cwd) {
|
|
18
16
|
const refs = getBaseRefs(base, head)
|
|
19
17
|
const { ref } = findRef(refs, cwd)
|
|
20
18
|
return ref
|
|
@@ -63,5 +61,3 @@ const throwError = function (name, { ref, error: { message, stderr } }) {
|
|
|
63
61
|
const messageA = `Invalid ${name} commit ${ref}\n${messages}`
|
|
64
62
|
throw new Error(messageA)
|
|
65
63
|
}
|
|
66
|
-
|
|
67
|
-
module.exports = { getBase, getHead }
|
package/src/stats.js
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const { git } = require('./exec')
|
|
1
|
+
import { git } from './exec.js'
|
|
4
2
|
|
|
5
3
|
// Returns the number of lines of code added, removed or modified since the
|
|
6
4
|
// `base` commit
|
|
7
|
-
const getLinesOfCode = function (base, head, cwd) {
|
|
5
|
+
export const getLinesOfCode = function (base, head, cwd) {
|
|
8
6
|
const stdout = git(['diff', '--shortstat', `${base}...${head}`], cwd)
|
|
9
7
|
const insertions = parseStdout(stdout, INSERTION_REGEXP)
|
|
10
8
|
const deletions = parseStdout(stdout, DELETION_REGEXP)
|
|
@@ -23,5 +21,3 @@ const parseStdout = function (stdout, regexp) {
|
|
|
23
21
|
|
|
24
22
|
const INSERTION_REGEXP = /(\d+) insertion/
|
|
25
23
|
const DELETION_REGEXP = /(\d+) deletion/
|
|
26
|
-
|
|
27
|
-
module.exports = { getLinesOfCode }
|