mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
acf07d18a9
Currently the publish script prints an error if the release tag does not exist locally yet. This is not expected since the function that calls `git` to check if a given tag exists, returns a boolean and should not additionally print the git `stderr`. Note we can also look into attaching the release notes automatically, but since the release notes are making the URL too large and Github denies too large URL's, this is something we can explore in a follow-ups.
99 lines
3.6 KiB
TypeScript
99 lines
3.6 KiB
TypeScript
import {spawnSync, SpawnSyncReturns} from 'child_process';
|
|
|
|
/**
|
|
* Class that can be used to execute Git commands within a given project directory.
|
|
*
|
|
* Relying on the working directory of the current process is not good because it's not
|
|
* guaranteed that the working directory is always the target project directory.
|
|
*/
|
|
export class GitClient {
|
|
|
|
constructor(public projectDir: string, public remoteGitUrl: string) {}
|
|
|
|
/**
|
|
* Spawns a child process running Git. The "stderr" output is inherited and will be printed
|
|
* in case of errors. This makes it easier to debug failed commands.
|
|
*/
|
|
private _spawnGitProcess(args: string[], printStderr = true): SpawnSyncReturns<string> {
|
|
return spawnSync('git', args, {
|
|
cwd: this.projectDir,
|
|
stdio: ['pipe', 'pipe', printStderr ? 'inherit' : 'pipe'],
|
|
encoding: 'utf8',
|
|
});
|
|
}
|
|
|
|
/** Gets the currently checked out branch for the project directory. */
|
|
getCurrentBranch() {
|
|
return this._spawnGitProcess(['symbolic-ref', '--short', 'HEAD']).stdout.trim();
|
|
}
|
|
|
|
/** Gets the commit SHA for the specified remote repository branch. */
|
|
getRemoteCommitSha(branchName: string): string {
|
|
return this._spawnGitProcess(['ls-remote', this.remoteGitUrl, '-h',
|
|
`refs/heads/${branchName}`])
|
|
.stdout.split('\t')[0].trim();
|
|
}
|
|
|
|
/** Gets the latest commit SHA for the specified git reference. */
|
|
getLocalCommitSha(refName: string) {
|
|
return this._spawnGitProcess(['rev-parse', refName]).stdout.trim();
|
|
}
|
|
|
|
/** Gets whether the current Git repository has uncommitted changes. */
|
|
hasUncommittedChanges(): boolean {
|
|
return this._spawnGitProcess(['diff-index', '--quiet', 'HEAD']).status !== 0;
|
|
}
|
|
|
|
/** Checks out an existing branch with the specified name. */
|
|
checkoutBranch(branchName: string): boolean {
|
|
return this._spawnGitProcess(['checkout', branchName]).status === 0;
|
|
}
|
|
|
|
/** Creates a new branch which is based on the previous active branch. */
|
|
checkoutNewBranch(branchName: string): boolean {
|
|
return this._spawnGitProcess(['checkout', '-b', branchName]).status === 0;
|
|
}
|
|
|
|
/** Stages all changes by running `git add -A`. */
|
|
stageAllChanges(): boolean {
|
|
return this._spawnGitProcess(['add', '-A']).status === 0;
|
|
}
|
|
|
|
/** Creates a new commit within the current branch with the given commit message. */
|
|
createNewCommit(message: string): boolean {
|
|
return this._spawnGitProcess(['commit', '-m', message]).status === 0;
|
|
}
|
|
|
|
/** Gets the title of a specified commit reference. */
|
|
getCommitTitle(commitRef: string): string {
|
|
return this._spawnGitProcess(['log', '-n1', '--format="%s"', commitRef]).stdout.trim();
|
|
}
|
|
|
|
/** Creates a tag for the specified commit reference. */
|
|
createTag(commitRef: string, tagName: string, message: string): boolean {
|
|
return this._spawnGitProcess(['tag', tagName, '-m', message]).status === 0;
|
|
}
|
|
|
|
/** Checks whether the specified tag exists locally. */
|
|
hasLocalTag(tagName: string) {
|
|
return this._spawnGitProcess(['rev-parse', `refs/tags/${tagName}`], false).status === 0;
|
|
}
|
|
|
|
/** Gets the Git SHA of the specified local tag. */
|
|
getShaOfLocalTag(tagName: string) {
|
|
return this._spawnGitProcess(['rev-parse', `refs/tags/${tagName}`]).stdout.trim();
|
|
}
|
|
|
|
/** Gets the Git SHA of the specified remote tag. */
|
|
getShaOfRemoteTag(tagName: string): string {
|
|
return this._spawnGitProcess(['ls-remote', this.remoteGitUrl, '-t', `refs/tags/${tagName}`])
|
|
.stdout.split('\t')[0].trim();
|
|
}
|
|
|
|
/** Pushes the specified tag to the remote git repository. */
|
|
pushTagToRemote(tagName: string): boolean {
|
|
return this._spawnGitProcess(['push', this.remoteGitUrl, `refs/tags/${tagName}`]).status === 0;
|
|
}
|
|
}
|
|
|