Skip to content

Commit 69cd960

Browse files
authored
Merge pull request #1127 from denieler/patch-1
Use full unformatted subject message
2 parents bf04df7 + 040d5a3 commit 69cd960

File tree

7 files changed

+233
-71
lines changed

7 files changed

+233
-71
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@
131131
"tslint": "^5.11.0",
132132
"tslint-config-prettier": "^1.15.0",
133133
"typedoc": "0.9.0",
134-
"typescript": "^3.1.1",
134+
"typescript": "^3.9.7",
135135
"typescript-json-schema": "^0.32.0"
136136
},
137137
"dependencies": {
Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,63 @@
1-
import { formatJSON } from "../localGetCommits"
1+
import { localGetCommits } from "../localGetCommits"
2+
import { logGitCommits } from "../localLogGitCommits"
3+
4+
const hash = "hash"
5+
const abbrevParentHashes = "abbrevParentHashes"
6+
const treeHash = "treeHash"
7+
const authorName = "authorName"
8+
const authorEmail = "authorEmail"
9+
const authorDate = "authorDate"
10+
const committerName = "committerName"
11+
const committerEmail = "committerEmail"
12+
const committerDate = "committerDate"
13+
const subject = "subject"
14+
15+
const gitLogCommitMock = {
16+
hash,
17+
abbrevParentHashes,
18+
treeHash,
19+
authorName,
20+
authorEmail,
21+
authorDate,
22+
committerName,
23+
committerEmail,
24+
committerDate,
25+
subject,
26+
}
27+
28+
jest.mock("../localLogGitCommits", () => ({
29+
__esModule: true,
30+
logGitCommits: jest.fn(() => [gitLogCommitMock]),
31+
}))
232

333
it("generates a JSON-like commit message", () => {
4-
expect(formatJSON).toEqual(
5-
'{ "sha": "%H", "parents": "%p", "author": {"name": "%an", "email": "%ae", "date": "%ai" }, "committer": {"name": "%cn", "email": "%ce", "date": "%ci" }, "message": "%f"},'
6-
)
34+
const base = "base-branch"
35+
const head = "head-branch"
36+
37+
const result = localGetCommits(base, head)
38+
39+
expect(logGitCommits).toHaveBeenCalledWith({
40+
number: expect.any(Number),
41+
branch: `${base}...${head}`,
42+
fields: expect.any(Array),
43+
})
744

8-
const withoutComma = formatJSON.substring(0, formatJSON.length - 1)
9-
expect(() => JSON.parse(withoutComma)).not.toThrow()
45+
expect(result).toEqual([
46+
{
47+
sha: hash,
48+
author: {
49+
name: authorName,
50+
email: authorEmail,
51+
date: authorDate,
52+
},
53+
committer: {
54+
name: committerName,
55+
email: committerEmail,
56+
date: committerDate,
57+
},
58+
message: subject,
59+
tree: treeHash,
60+
url: expect.stringContaining(hash),
61+
},
62+
])
1063
})
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { execFileSync } from "child_process"
2+
3+
import { logGitCommits } from "../localLogGitCommits"
4+
5+
const COMMAND_OUTPUT = ""
6+
7+
jest.mock("child_process", () => ({
8+
__esModule: true,
9+
execFileSync: jest.fn(() => COMMAND_OUTPUT),
10+
}))
11+
12+
it("get git commits from the 'git log' command", () => {
13+
const options = {
14+
number: 10,
15+
branch: "test_branch",
16+
fields: ["hash" as "hash", "subject" as "subject"],
17+
}
18+
19+
const result = logGitCommits(options)
20+
21+
expect(execFileSync).toHaveBeenCalledWith("git", [
22+
"log",
23+
"-l0",
24+
`-n ${options.number}`,
25+
"--pretty=@begin@" + "\t%H\t%s" + "@end@",
26+
options.branch,
27+
])
28+
29+
expect(result).toEqual([])
30+
})
Lines changed: 38 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,40 @@
1-
import { debug } from "../../debug"
2-
import JSON5 from "json5"
3-
4-
import { spawn } from "child_process"
1+
import { logGitCommits } from "./localLogGitCommits"
52
import { GitCommit } from "../../dsl/Commit"
63

7-
const d = debug("localGetDiff")
8-
9-
const sha = "%H"
10-
const parents = "%p"
11-
const authorName = "%an"
12-
const authorEmail = "%ae"
13-
const authorDate = "%ai"
14-
const committerName = "%cn"
15-
const committerEmail = "%ce"
16-
const committerDate = "%ci"
17-
const message = "%f" // this is subject, not message, so it'll only be one line
18-
19-
const author = `"author": {"name": "${authorName}", "email": "${authorEmail}", "date": "${authorDate}" }`
20-
const committer = `"committer": {"name": "${committerName}", "email": "${committerEmail}", "date": "${committerDate}" }`
21-
export const formatJSON = `{ "sha": "${sha}", "parents": "${parents}", ${author}, ${committer}, "message": "${message}"},`
22-
23-
export const localGetCommits = (base: string, head: string) =>
24-
new Promise<GitCommit[]>((resolve, reject) => {
25-
const args = ["log", `${base}...${head}`, `--pretty=format:${formatJSON}`]
26-
const child = spawn("git", args, { env: process.env })
27-
d("> git", args.join(" "))
28-
const commits: GitCommit[] = []
29-
30-
child.stdout.on("data", async (chunk: Buffer) => {
31-
const data = chunk.toString()
32-
// remove trailing comma, and wrap into an array
33-
const asJSONString = `[${data.substring(0, data.length - 1)}]`
34-
const parsedCommits = JSON5.parse(asJSONString)
35-
const realCommits = parsedCommits.map((c: any) => ({
36-
...c,
37-
parents: c.parents.split(" "),
38-
url: "fake.danger.systems/" + c.sha,
39-
}))
40-
41-
commits.push(...realCommits)
42-
})
43-
44-
child.stderr.on("end", () => resolve(commits))
45-
46-
const errorParts: string[] = []
47-
48-
child.stderr.on("data", (chunk: Buffer) => errorParts.push(chunk.toString()))
49-
50-
child.on("close", code => {
51-
if (code !== 0) {
52-
console.error(`Could not get commits from git between ${base} and ${head}`)
53-
reject(new Error(errorParts.join("")))
54-
} else {
55-
resolve(commits)
56-
}
57-
})
58-
})
4+
export const localGetCommits = (base: string, head: string) => {
5+
const options = {
6+
number: 100,
7+
branch: `${base}...${head}`,
8+
fields: [
9+
"hash" as "hash",
10+
"abbrevParentHashes" as "abbrevParentHashes",
11+
"treeHash" as "treeHash",
12+
"authorName" as "authorName",
13+
"authorEmail" as "authorEmail",
14+
"authorDate" as "authorDate",
15+
"committerName" as "committerName",
16+
"committerEmail" as "committerEmail",
17+
"committerDate" as "committerDate",
18+
"subject" as "subject",
19+
],
20+
}
21+
22+
const commits: GitCommit[] = logGitCommits(options).map(commit => ({
23+
sha: commit.hash,
24+
author: {
25+
name: commit.authorName,
26+
email: commit.authorEmail,
27+
date: commit.authorDate,
28+
},
29+
committer: {
30+
name: commit.committerName,
31+
email: commit.committerEmail,
32+
date: commit.committerDate,
33+
},
34+
message: commit.subject,
35+
tree: commit.treeHash,
36+
url: "fake.danger.systems/" + commit.hash,
37+
}))
38+
39+
return commits
40+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import { execFileSync } from "child_process"
2+
3+
const delimiter = "\t"
4+
const fieldMap = {
5+
hash: "%H",
6+
treeHash: "%T",
7+
abbrevParentHashes: "%P",
8+
authorName: "%an",
9+
authorEmail: "%ae",
10+
authorDate: "%ai",
11+
committerName: "%cn",
12+
committerEmail: "%ce",
13+
committerDate: "%cd",
14+
subject: "%s",
15+
}
16+
17+
export type GitLogOptions = {
18+
number: number
19+
branch: string
20+
fields: Array<Partial<keyof typeof fieldMap>>
21+
}
22+
23+
export type GitLogCommit = {
24+
hash: string
25+
treeHash: string
26+
abbrevParentHashes: string
27+
authorName: string
28+
authorEmail: string
29+
authorDate: string
30+
committerName: string
31+
committerEmail: string
32+
committerDate: string
33+
subject: string
34+
}
35+
36+
const createCommandArguments = (options: GitLogOptions) => {
37+
// Start constructing command
38+
let command: string[] = ["log", "-l0"]
39+
40+
command.push(`-n ${options.number}`)
41+
42+
// Start of custom format
43+
let prettyArgument = "--pretty=@begin@"
44+
45+
// Iterating through the fields and adding them to the custom format
46+
if (options.fields) {
47+
options.fields.forEach(field => {
48+
prettyArgument += delimiter + fieldMap[field]
49+
})
50+
}
51+
52+
// Close custom format
53+
prettyArgument += "@end@"
54+
command.push(prettyArgument)
55+
56+
// Append branch (revision range) if specified
57+
if (options.branch) {
58+
command.push(options.branch)
59+
}
60+
61+
return command
62+
}
63+
64+
const parseCommits = (commits: string[], fields: string[]) =>
65+
commits.map(rawCommit => {
66+
const parts = rawCommit.split("@end@")
67+
const commit = parts[0].split(delimiter)
68+
69+
// Remove the first empty char from the array
70+
commit.shift()
71+
72+
const parsed = {}
73+
74+
commit.forEach((commitField, index) => {
75+
if (!fields[index]) {
76+
return
77+
}
78+
79+
parsed[fields[index]] = commitField
80+
})
81+
82+
return parsed as GitLogCommit
83+
})
84+
85+
export const logGitCommits = (options: GitLogOptions) => {
86+
const commandArguments = createCommandArguments(options)
87+
88+
const stdout = execFileSync("git", commandArguments).toString()
89+
90+
const commits = stdout.split("@begin@")
91+
92+
if (commits[0] === "") {
93+
commits.shift()
94+
}
95+
96+
return parseCommits(commits, options.fields)
97+
}

source/runner/Executor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ export interface ExecutorOptions {
7070
const isTests = typeof jest === "object"
7171

7272
interface ExitCodeContainer {
73-
exitCode: number
73+
exitCode?: number
7474
}
7575

7676
export class Executor {

yarn.lock

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,9 +1169,9 @@
11691169
integrity sha512-GnZbirvmqZUzMgkFn70c74OQpTTUcCzlhQliTzYjQMqg+hVKcDnxdL19Ne3UdYzdMA/+W3eb646FWn/ZaT1NfQ==
11701170

11711171
"@types/node@^10.11.3":
1172-
version "10.11.3"
1173-
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.11.3.tgz#c055536ac8a5e871701aa01914be5731539d01ee"
1174-
integrity sha512-3AvcEJAh9EMatxs+OxAlvAEs7OTy6AG94mcH1iqyVDwVVndekLxzwkWQ/Z4SDbY6GO2oyUXyWW8tQ4rENSSQVQ==
1172+
version "10.17.55"
1173+
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.55.tgz#a147f282edec679b894d4694edb5abeb595fecbd"
1174+
integrity sha512-koZJ89uLZufDvToeWO5BrC4CR4OUfHnUz2qoPs/daQH6qq3IN62QFxCTZ+bKaCE0xaoCAJYE4AXre8AbghCrhg==
11751175

11761176
"@types/p-limit@^2.0.0":
11771177
version "2.0.0"
@@ -8837,10 +8837,10 @@ typescript@^3.0.1:
88378837
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.1.3.tgz#01b70247a6d3c2467f70c45795ef5ea18ce191d5"
88388838
integrity sha512-+81MUSyX+BaSo+u2RbozuQk/UWx6hfG0a5gHu4ANEM4sU96XbuIyAB+rWBW1u70c6a5QuZfuYICn3s2UjuHUpA==
88398839

8840-
typescript@^3.1.1:
8841-
version "3.1.1"
8842-
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.1.1.tgz#3362ba9dd1e482ebb2355b02dfe8bcd19a2c7c96"
8843-
integrity sha512-Veu0w4dTc/9wlWNf2jeRInNodKlcdLgemvPsrNpfu5Pq39sgfFjvIIgTsvUHCoLBnMhPoUA+tFxsXjU6VexVRQ==
8840+
typescript@^3.9.7:
8841+
version "3.9.9"
8842+
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.9.tgz#e69905c54bc0681d0518bd4d587cc6f2d0b1a674"
8843+
integrity sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w==
88448844

88458845
uglify-js@^2.6:
88468846
version "2.8.29"

0 commit comments

Comments
 (0)