From 57e30a47b4955bd0fed4e06ee40c756b6c12d5dc Mon Sep 17 00:00:00 2001 From: Rongjian Zhang Date: Tue, 2 Jul 2019 00:12:52 +0800 Subject: [PATCH] feat(core): use git config to determine author before username (#920) --- .../api/core/src/api/init-scripts/init-npm.ts | 6 +-- .../api/core/src/util/determine-author.ts | 26 +++++++++ .../core/test/fast/determine-author_spec.ts | 54 +++++++++++++++++++ packages/maker/appx/src/util/author-name.ts | 9 ++-- packages/maker/wix/src/util/author-name.ts | 9 ++-- packages/utils/types/src/index.ts | 6 +++ 6 files changed, 95 insertions(+), 15 deletions(-) create mode 100644 packages/api/core/src/util/determine-author.ts create mode 100644 packages/api/core/test/fast/determine-author_spec.ts diff --git a/packages/api/core/src/api/init-scripts/init-npm.ts b/packages/api/core/src/api/init-scripts/init-npm.ts index 64d63a4d4b..a128fa38be 100644 --- a/packages/api/core/src/api/init-scripts/init-npm.ts +++ b/packages/api/core/src/api/init-scripts/init-npm.ts @@ -2,11 +2,11 @@ import { asyncOra } from '@electron-forge/async-ora'; import debug from 'debug'; import fs from 'fs-extra'; import path from 'path'; -import username from 'username'; -import { setInitialForgeConfig } from '../../util/forge-config'; +import determineAuthor from '../../util/determine-author'; import installDepList, { DepType, DepVersionRestriction } from '../../util/install-dependencies'; import { readRawPackageJson } from '../../util/read-package-json'; +import { setInitialForgeConfig } from '../../util/forge-config'; const d = debug('electron-forge:init:npm'); const corePackage = fs.readJsonSync(path.resolve(__dirname, '../../../package.json')); @@ -30,7 +30,7 @@ export default async (dir: string) => { const packageJSON = await readRawPackageJson(path.resolve(__dirname, '../../../tmpl')); // eslint-disable-next-line no-multi-assign packageJSON.productName = packageJSON.name = path.basename(dir).toLowerCase(); - packageJSON.author = await username(); + packageJSON.author = await determineAuthor(dir); setInitialForgeConfig(packageJSON); packageJSON.scripts.lint = 'echo "No linting configured"'; diff --git a/packages/api/core/src/util/determine-author.ts b/packages/api/core/src/util/determine-author.ts new file mode 100644 index 0000000000..d2e755043c --- /dev/null +++ b/packages/api/core/src/util/determine-author.ts @@ -0,0 +1,26 @@ +import childProcess from 'child_process'; +import debug from 'debug'; +import { PackagePerson } from '@electron-forge/shared-types'; +import { promisify } from 'util'; +import username from 'username'; + +const d = debug('electron-forge:determine-author'); +const exec = promisify(childProcess.exec); + +const execAndTrimResult = async (command: string, dir: string) => { + const { stdout } = await exec(command, { cwd: dir }); + return stdout.trim(); +}; + +const getAuthorFromGitConfig = async (dir: string): Promise => { + try { + const name = await execAndTrimResult('git config --get user.name', dir); + const email = await execAndTrimResult('git config --get user.email', dir); + return { name, email }; + } catch (err) { + d('Error when getting git config:', err); + return undefined; + } +}; + +export default async (dir: string) => (await getAuthorFromGitConfig(dir)) || username(); diff --git a/packages/api/core/test/fast/determine-author_spec.ts b/packages/api/core/test/fast/determine-author_spec.ts new file mode 100644 index 0000000000..f350dcda0e --- /dev/null +++ b/packages/api/core/test/fast/determine-author_spec.ts @@ -0,0 +1,54 @@ +import { expect } from 'chai'; +import proxyquire from 'proxyquire'; +import sinon from 'sinon'; + +import { PackagePerson } from '@electron-forge/shared-types'; + +describe('determineAuthor', () => { + let determineAuthor: (dir: string) => Promise; + let returnGitUsername = true; + let returnGitEmail = true; + // eslint-disable-next-line max-len + const fakeExec = (cmd: string, options: { cwd: string }, callback: (err: Error | null, result?: { stdout?: string, stderr?: string }) => void) => { + if (cmd.includes('user.name')) { + if (returnGitUsername) { + callback(null, { stdout: 'Foo Bar\n' }); + } else { + callback(new Error('Not returning username')); + } + } else if (cmd.includes('user.email')) { + if (returnGitEmail) { + callback(null, { stdout: 'foo@example.com\n' }); + } else { + callback(new Error('Not returning email')); + } + } else { + callback(new Error('Unknown cmd')); + } + }; + + beforeEach(() => { + determineAuthor = proxyquire.noCallThru().load('../../src/util/determine-author', { + child_process: { exec: sinon.stub().callsFake(fakeExec) }, + username: sinon.stub().resolves('fromUsername'), + }).default; + }); + + it('returns git config if both name and email are set', async () => { + returnGitUsername = true; + returnGitEmail = true; + expect(await determineAuthor('foo')).to.deep.equal({ name: 'Foo Bar', email: 'foo@example.com' }); + }); + + it('returns username if only name is set', async () => { + returnGitUsername = true; + returnGitEmail = false; + expect(await determineAuthor('foo')).to.equal('fromUsername'); + }); + + it('returns username if only name is set', async () => { + returnGitUsername = false; + returnGitEmail = true; + expect(await determineAuthor('foo')).to.equal('fromUsername'); + }); +}); diff --git a/packages/maker/appx/src/util/author-name.ts b/packages/maker/appx/src/util/author-name.ts index 67391f6231..0b6d95609b 100644 --- a/packages/maker/appx/src/util/author-name.ts +++ b/packages/maker/appx/src/util/author-name.ts @@ -1,11 +1,8 @@ import parseAuthor from 'parse-author'; +import { PackagePerson } from '@electron-forge/shared-types'; -type AuthorType = string | { - name: string; -} | undefined; - -export default function getNameFromAuthor(author: AuthorType) { - let publisher: AuthorType = author || ''; +export default function getNameFromAuthor(author: PackagePerson) { + let publisher: PackagePerson = author || ''; if (typeof publisher === 'string') { publisher = parseAuthor(publisher); diff --git a/packages/maker/wix/src/util/author-name.ts b/packages/maker/wix/src/util/author-name.ts index 67391f6231..0b6d95609b 100644 --- a/packages/maker/wix/src/util/author-name.ts +++ b/packages/maker/wix/src/util/author-name.ts @@ -1,11 +1,8 @@ import parseAuthor from 'parse-author'; +import { PackagePerson } from '@electron-forge/shared-types'; -type AuthorType = string | { - name: string; -} | undefined; - -export default function getNameFromAuthor(author: AuthorType) { - let publisher: AuthorType = author || ''; +export default function getNameFromAuthor(author: PackagePerson) { + let publisher: PackagePerson = author || ''; if (typeof publisher === 'string') { publisher = parseAuthor(publisher); diff --git a/packages/utils/types/src/index.ts b/packages/utils/types/src/index.ts index 43c29c4d18..75cfed6074 100644 --- a/packages/utils/types/src/index.ts +++ b/packages/utils/types/src/index.ts @@ -121,3 +121,9 @@ export interface ForgeTemplate { devDependencies?: string[]; initializeTemplate?: (dir: string) => void; } + +export type PackagePerson = undefined | string | { + name: string; + email?: string; + url?: string; +};