build: drop dugite as a dependency (#49194)

This commit is contained in:
John Kleinschmidt
2025-12-12 13:43:12 -05:00
committed by GitHub
parent a486185e10
commit e181fd040f
10 changed files with 94 additions and 66 deletions

View File

@@ -25,7 +25,6 @@
"buffer": "^6.0.3",
"chalk": "^4.1.0",
"check-for-leaks": "^1.2.1",
"dugite": "^2.7.1",
"eslint": "^8.57.1",
"eslint-config-standard": "^17.1.0",
"eslint-plugin-import": "^2.32.0",
@@ -149,9 +148,6 @@
"dependenciesMeta": {
"abstract-socket": {
"built": true
},
"dugite": {
"built": true
}
}
}

View File

@@ -1,6 +1,6 @@
const chalk = require('chalk');
const { GitProcess } = require('dugite');
const childProcess = require('node:child_process');
const fs = require('node:fs');
const os = require('node:os');
const path = require('node:path');
@@ -61,13 +61,16 @@ function getAbsoluteElectronExec () {
return path.resolve(SRC_DIR, getElectronExec());
}
async function handleGitCall (args, gitDir) {
const details = await GitProcess.exec(args, gitDir);
if (details.exitCode === 0) {
return details.stdout.replace(/^\*|\s+|\s+$/, '');
function handleGitCall (args, gitDir) {
const result = childProcess.spawnSync('git', args, {
cwd: gitDir,
encoding: 'utf8',
stdio: ['inherit', 'pipe', 'pipe']
});
if (result.status === 0) {
return result.stdout.replace(/^\*|\s+|\s+$/, '');
} else {
const error = GitProcess.parseError(details.stderr);
console.log(`${fail} couldn't parse git process call: `, error);
console.log(`${fail} couldn't parse git process call: `, result.stderr);
process.exit(1);
}
}

View File

@@ -1,6 +1,5 @@
#!/usr/bin/env node
const { GitProcess } = require('dugite');
const { ESLint } = require('eslint');
const minimist = require('minimist');
@@ -431,9 +430,13 @@ function populateLinterWithArgs (linter, opts) {
}
async function findChangedFiles (top) {
const result = await GitProcess.exec(['diff', '--name-only', '--cached'], top);
if (result.exitCode !== 0) {
console.log('Failed to find changed files', GitProcess.parseError(result.stderr));
const result = childProcess.spawnSync('git', ['diff', '--name-only', '--cached'], {
cwd: top,
encoding: 'utf8',
stdio: ['inherit', 'pipe', 'pipe']
});
if (result.status !== 0) {
console.log('Failed to find changed files', result.stderr);
process.exit(1);
}
const relativePaths = result.stdout.split(/\r\n|\r|\n/g);

View File

@@ -1,9 +1,9 @@
#!/usr/bin/env node
import { Octokit } from '@octokit/rest';
import { GitProcess } from 'dugite';
import { valid, compare, gte, lte } from 'semver';
import { spawnSync } from 'node:child_process';
import { basename } from 'node:path';
import { parseArgs } from 'node:util';
@@ -20,8 +20,12 @@ const semverify = (version: string) => version.replace(/^origin\//, '').replace(
const runGit = async (args: string[]) => {
console.info(`Running: git ${args.join(' ')}`);
const response = await GitProcess.exec(args, ELECTRON_DIR);
if (response.exitCode !== 0) {
const response = spawnSync('git', args, {
cwd: ELECTRON_DIR,
encoding: 'utf8',
stdio: ['inherit', 'pipe', 'pipe']
});
if (response.status !== 0) {
throw new Error(response.stderr.trim());
}
return response.stdout.trim();

View File

@@ -1,8 +1,8 @@
#!/usr/bin/env node
import { Octokit } from '@octokit/rest';
import { GitProcess } from 'dugite';
import { spawnSync } from 'node:child_process';
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
import { resolve as _resolve } from 'node:path';
@@ -105,8 +105,12 @@ class Pool {
**/
const runGit = async (dir: string, args: string[]) => {
const response = await GitProcess.exec(args, dir);
if (response.exitCode !== 0) {
const response = spawnSync('git', args, {
cwd: dir,
encoding: 'utf8',
stdio: ['inherit', 'pipe', 'pipe']
});
if (response.status !== 0) {
throw new Error(response.stderr.trim());
}
return response.stdout.trim();

View File

@@ -1,8 +1,7 @@
import { Octokit } from '@octokit/rest';
import * as chalk from 'chalk';
import { GitProcess } from 'dugite';
import { execSync } from 'node:child_process';
import { execSync, spawnSync } from 'node:child_process';
import { join } from 'node:path';
import { createGitHubTokenStrategy } from './github-token';
@@ -166,11 +165,12 @@ async function createRelease (
}
async function pushRelease (branch: string) {
const pushDetails = await GitProcess.exec(
['push', 'origin', `HEAD:${branch}`, '--follow-tags'],
ELECTRON_DIR
);
if (pushDetails.exitCode === 0) {
const pushDetails = spawnSync('git', ['push', 'origin', `HEAD:${branch}`, '--follow-tags'], {
cwd: ELECTRON_DIR,
encoding: 'utf8',
stdio: ['inherit', 'pipe', 'pipe']
});
if (pushDetails.status === 0) {
console.log(
`${pass} Successfully pushed the release. Wait for ` +
'release builds to finish before running "npm run release".'
@@ -191,11 +191,12 @@ async function runReleaseBuilds (branch: string, newVersion: string) {
async function tagRelease (version: string) {
console.log(`Tagging release ${version}.`);
const checkoutDetails = await GitProcess.exec(
['tag', '-a', '-m', version, version],
ELECTRON_DIR
);
if (checkoutDetails.exitCode === 0) {
const checkoutDetails = spawnSync('git', ['tag', '-a', '-m', version, version], {
cwd: ELECTRON_DIR,
encoding: 'utf8',
stdio: ['inherit', 'pipe', 'pipe']
});
if (checkoutDetails.status === 0) {
console.log(`${pass} Successfully tagged ${version}.`);
} else {
console.log(

View File

@@ -1,6 +1,7 @@
import { GitProcess } from 'dugite';
import * as semver from 'semver';
import { spawnSync } from 'node:child_process';
import { ELECTRON_DIR } from '../lib/utils';
export enum PreType {
@@ -27,7 +28,11 @@ export const isStable = (v: string) => {
export async function nextAlpha (v: string) {
const next = semver.coerce(semver.clean(v));
const tagBlob = await GitProcess.exec(['tag', '--list', '-l', `v${next}-alpha.*`], ELECTRON_DIR);
const tagBlob = spawnSync('git', ['tag', '--list', '-l', `v${next}-alpha.*`], {
cwd: ELECTRON_DIR,
encoding: 'utf8',
stdio: ['inherit', 'pipe', 'pipe']
});
const tags = tagBlob.stdout.split('\n').filter(e => e !== '');
tags.sort((t1, t2) => {
const a = parseInt(t1.split('.').pop()!, 10);
@@ -41,7 +46,11 @@ export async function nextAlpha (v: string) {
export async function nextBeta (v: string) {
const next = semver.coerce(semver.clean(v));
const tagBlob = await GitProcess.exec(['tag', '--list', '-l', `v${next}-beta.*`], ELECTRON_DIR);
const tagBlob = spawnSync('git', ['tag', '--list', '-l', `v${next}-beta.*`], {
cwd: ELECTRON_DIR,
encoding: 'utf8',
stdio: ['inherit', 'pipe', 'pipe']
});
const tags = tagBlob.stdout.split('\n').filter(e => e !== '');
tags.sort((t1, t2) => {
const a = parseInt(t1.split('.').pop()!, 10);
@@ -57,7 +66,11 @@ export async function nextNightly (v: string) {
let next = semver.valid(semver.coerce(v));
const pre = `nightly.${getCurrentDate()}`;
const branch = (await GitProcess.exec(['rev-parse', '--abbrev-ref', 'HEAD'], ELECTRON_DIR)).stdout.trim();
const branch = spawnSync('git', ['rev-parse', '--abbrev-ref', 'HEAD'], {
cwd: ELECTRON_DIR,
encoding: 'utf8',
stdio: ['inherit', 'pipe', 'pipe']
}).stdout.trim();
if (branch === 'main') {
next = semver.inc(await getLastMajorForMain(), 'major');
} else if (isStable(v)) {
@@ -69,8 +82,12 @@ export async function nextNightly (v: string) {
async function getLastMajorForMain () {
let branchNames;
const result = await GitProcess.exec(['branch', '-a', '--remote', '--list', 'origin/[0-9]*-x-y'], ELECTRON_DIR);
if (result.exitCode === 0) {
const result = spawnSync('git', ['branch', '-a', '--remote', '--list', 'origin/[0-9]*-x-y'], {
cwd: ELECTRON_DIR,
encoding: 'utf8',
stdio: ['inherit', 'pipe', 'pipe']
});
if (result.status === 0) {
branchNames = result.stdout.trim().split('\n');
const filtered = branchNames.map(b => b.replace('origin/', ''));
return getNextReleaseBranch(filtered);

View File

@@ -1,12 +1,12 @@
import { expect } from 'chai';
import { GitProcess, IGitExecutionOptions, IGitResult } from 'dugite';
import * as sinon from 'sinon';
import { SpawnSyncReturns } from 'node:child_process';
import * as path from 'node:path';
import * as notes from '../script/release/notes/notes';
/* Fake a Dugite GitProcess that only returns the specific
/* Fake a git spawnSync that only returns the specific
commits that we want to test */
class Commit {
@@ -43,10 +43,10 @@ class GitFake {
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
exec (args: string[], path: string, options?: IGitExecutionOptions | undefined): Promise<IGitResult> {
exec (command: string, args: string[], options?: any): SpawnSyncReturns<string> {
let stdout = '';
const stderr = '';
const exitCode = 0;
const status = 0;
if (args.length === 3 && args[0] === 'merge-base') {
// expected form: `git merge-base branchName1 branchName2`
@@ -78,10 +78,10 @@ class GitFake {
// git branch --all --contains ${ref} --sort version:refname
stdout = args[3];
} else {
console.error('unhandled GitProcess.exec():', args);
console.error('unhandled git spawnSync():', args);
}
return Promise.resolve({ exitCode, stdout, stderr });
return { status, stdout, stderr, pid: 0, output: [null, stdout, stderr], signal: null };
}
}
@@ -118,8 +118,14 @@ describe('release notes', () => {
});
beforeEach(() => {
const wrapper = (args: string[], path: string, options?: IGitExecutionOptions | undefined) => gitFake.exec(args, path, options);
sandbox.replace(GitProcess, 'exec', wrapper);
const wrapper = (command: unknown, args: unknown, options?: unknown) => {
if (command === 'git' && Array.isArray(args)) {
return gitFake.exec(command as string, args as string[], options);
}
// Default behavior for non-git commands
return { status: 0, stdout: '', stderr: '', pid: 0, output: [null, '', ''], signal: null };
};
sandbox.stub(require('node:child_process'), 'spawnSync').callsFake(wrapper);
gitFake.setBranch(oldBranch, [...sharedHistory, oldFix]);
});

View File

@@ -1,7 +1,8 @@
import { expect } from 'chai';
import { GitProcess, IGitExecutionOptions, IGitResult } from 'dugite';
import * as sinon from 'sinon';
import { SpawnSyncReturns } from 'node:child_process';
import { ifdescribe } from './lib/spec-helpers';
import { nextVersion } from '../script/release/version-bumper';
@@ -33,10 +34,10 @@ class GitFake {
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
exec (args: string[], path: string, options?: IGitExecutionOptions | undefined): Promise<IGitResult> {
exec (command: string, args: string[], options?: any): SpawnSyncReturns<string> {
let stdout = '';
const stderr = '';
const exitCode = 0;
const status = 0;
// handle for promoting from current master HEAD
let branch = 'stable';
@@ -48,7 +49,7 @@ class GitFake {
if (!this.branches[branch]) this.setBranch(branch);
stdout = this.branches[branch].join('\n');
return Promise.resolve({ exitCode, stdout, stderr });
return { status, stdout, stderr, pid: 0, output: [null, stdout, stderr], signal: null };
}
}
@@ -163,8 +164,14 @@ describe('version-bumper', () => {
const gitFake = new GitFake();
beforeEach(() => {
const wrapper = (args: string[], path: string, options?: IGitExecutionOptions | undefined) => gitFake.exec(args, path, options);
sandbox.replace(GitProcess, 'exec', wrapper);
const wrapper = (command: unknown, args: unknown, options?: unknown) => {
if (command === 'git' && Array.isArray(args)) {
return gitFake.exec(command as string, args as string[], options);
}
// Default behavior for non-git commands
return { status: 0, stdout: '', stderr: '', pid: 0, output: [null, '', ''], signal: null };
};
sandbox.stub(require('node:child_process'), 'spawnSync').callsFake(wrapper);
});
afterEach(() => {

View File

@@ -607,7 +607,6 @@ __metadata:
buffer: "npm:^6.0.3"
chalk: "npm:^4.1.0"
check-for-leaks: "npm:^1.2.1"
dugite: "npm:^2.7.1"
eslint: "npm:^8.57.1"
eslint-config-standard: "npm:^17.1.0"
eslint-plugin-import: "npm:^2.32.0"
@@ -644,8 +643,6 @@ __metadata:
dependenciesMeta:
abstract-socket:
built: true
dugite:
built: true
languageName: unknown
linkType: soft
@@ -4867,16 +4864,6 @@ __metadata:
languageName: node
linkType: hard
"dugite@npm:^2.7.1":
version: 2.7.1
resolution: "dugite@npm:2.7.1"
dependencies:
progress: "npm:^2.0.3"
tar: "npm:^6.1.11"
checksum: 10c0/8b7992b91abc2473e43a4900c5b100f5a4b98785b9955275c72b1a621152b5df9ff794cda50daced5ee452f4dc95b313ce9c30af5dc9e302241ef9f661a593df
languageName: node
linkType: hard
"dunder-proto@npm:^1.0.0, dunder-proto@npm:^1.0.1":
version: 1.0.1
resolution: "dunder-proto@npm:1.0.1"