187 lines
5.3 KiB
TypeScript
187 lines
5.3 KiB
TypeScript
import * as plugins from './smartgit.plugins.js';
|
|
import { Smartgit } from './smartgit.classes.smartgit.js';
|
|
|
|
/**
|
|
* class GitRepo allows access to git directories from node
|
|
*/
|
|
export class GitRepo {
|
|
// STATIC
|
|
/**
|
|
* creates a new GitRepo Instance after cloning a project
|
|
*/
|
|
public static async fromCloningIntoDir(
|
|
smartgitRefArg: Smartgit,
|
|
fromArg: string,
|
|
toArg: string
|
|
): Promise<GitRepo> {
|
|
const dirArg = plugins.path.resolve(toArg);
|
|
await plugins.isomorphicGit.clone({
|
|
dir: toArg,
|
|
fs: smartgitRefArg.envDeps.fs,
|
|
http: smartgitRefArg.envDeps.http,
|
|
url: fromArg,
|
|
});
|
|
return new GitRepo(smartgitRefArg, toArg);
|
|
}
|
|
|
|
public static async fromCreatingRepoInDir(
|
|
smartgitRefArg: Smartgit,
|
|
dirArg: string
|
|
): Promise<GitRepo> {
|
|
dirArg = plugins.path.resolve(dirArg);
|
|
await plugins.isomorphicGit.init({
|
|
dir: dirArg,
|
|
fs: smartgitRefArg.envDeps.fs,
|
|
});
|
|
return new GitRepo(smartgitRefArg, dirArg);
|
|
}
|
|
|
|
public static async fromOpeningRepoDir(smartgitRefArg: Smartgit, dirArg: string) {
|
|
dirArg = plugins.path.resolve(dirArg);
|
|
return new GitRepo(smartgitRefArg, dirArg);
|
|
}
|
|
|
|
// INSTANCE
|
|
public smartgitRef: Smartgit;
|
|
public repoDir: string;
|
|
|
|
constructor(smartgitRefArg: Smartgit, repoDirArg: string) {
|
|
this.smartgitRef = smartgitRefArg;
|
|
this.repoDir = repoDirArg;
|
|
}
|
|
|
|
/**
|
|
* lists remotes
|
|
*/
|
|
public async listRemotes(): Promise<
|
|
{
|
|
remote: string;
|
|
url: string;
|
|
}[]
|
|
> {
|
|
const remotes = await plugins.isomorphicGit.listRemotes({
|
|
fs: this.smartgitRef.envDeps.fs,
|
|
dir: this.repoDir,
|
|
});
|
|
return remotes;
|
|
}
|
|
|
|
/**
|
|
* ensures the existence of a remote within a repository
|
|
* @param remoteNameArg
|
|
* @param remoteUrlArg
|
|
*/
|
|
public async ensureRemote(remoteNameArg: string, remoteUrlArg: string): Promise<void> {
|
|
const remotes = await this.listRemotes();
|
|
const existingRemote = remotes.find((itemArg) => itemArg.remote === remoteNameArg);
|
|
if (existingRemote) {
|
|
if (existingRemote.url !== remoteUrlArg) {
|
|
await plugins.isomorphicGit.deleteRemote({
|
|
remote: remoteNameArg,
|
|
fs: this.smartgitRef.envDeps.fs,
|
|
dir: this.repoDir,
|
|
});
|
|
} else {
|
|
return;
|
|
}
|
|
}
|
|
await plugins.isomorphicGit.addRemote({
|
|
remote: remoteNameArg,
|
|
fs: this.smartgitRef.envDeps.fs,
|
|
url: remoteUrlArg,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* gets the url for a specific remote
|
|
*/
|
|
public async getUrlForRemote(remoteName: string): Promise<string> {
|
|
const remotes = await this.listRemotes();
|
|
const existingRemote = remotes.find((remoteArg) => remoteArg.remote === remoteName);
|
|
return existingRemote?.url;
|
|
}
|
|
|
|
public async pushBranchToRemote(branchName: string, remoteName: string) {
|
|
await plugins.isomorphicGit.push({
|
|
fs: this.smartgitRef.envDeps.fs,
|
|
http: this.smartgitRef.envDeps.http,
|
|
ref: branchName,
|
|
remote: remoteName,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Get the diff of the current uncommitted changes while excluding specified files
|
|
*/
|
|
public async getUncommittedDiff(excludeFiles: string[] = []): Promise<string[]> {
|
|
const statusMatrix = await plugins.isomorphicGit.statusMatrix({
|
|
fs: this.smartgitRef.envDeps.fs,
|
|
dir: this.repoDir,
|
|
});
|
|
|
|
const diffs: string[] = [];
|
|
for (const row of statusMatrix) {
|
|
const [filepath, head, workdir] = row;
|
|
if (excludeFiles.includes(filepath)) {
|
|
continue; // Skip excluded files
|
|
}
|
|
|
|
let headContent = '';
|
|
let workdirContent = '';
|
|
|
|
// Handle modified files
|
|
if (head !== 0 && workdir !== 0 && head !== workdir) {
|
|
headContent = await plugins.isomorphicGit.readBlob({
|
|
fs: this.smartgitRef.envDeps.fs,
|
|
dir: this.repoDir,
|
|
oid: await plugins.isomorphicGit.resolveRef({
|
|
fs: this.smartgitRef.envDeps.fs,
|
|
dir: this.repoDir,
|
|
ref: 'HEAD',
|
|
}),
|
|
filepath,
|
|
}).then(result => new TextDecoder().decode(result.blob));
|
|
|
|
workdirContent = await this.smartgitRef.envDeps.fs.promises.readFile(plugins.path.join(this.repoDir, filepath), 'utf8');
|
|
}
|
|
|
|
// Handle added files
|
|
if (head === 0 && workdir !== 0) {
|
|
workdirContent = await this.smartgitRef.envDeps.fs.promises.readFile(plugins.path.join(this.repoDir, filepath), 'utf8');
|
|
}
|
|
|
|
// Handle deleted files
|
|
if (head !== 0 && workdir === 0) {
|
|
headContent = await plugins.isomorphicGit.readBlob({
|
|
fs: this.smartgitRef.envDeps.fs,
|
|
dir: this.repoDir,
|
|
oid: await plugins.isomorphicGit.resolveRef({
|
|
fs: this.smartgitRef.envDeps.fs,
|
|
dir: this.repoDir,
|
|
ref: 'HEAD',
|
|
}),
|
|
filepath,
|
|
}).then(result => new TextDecoder().decode(result.blob));
|
|
}
|
|
|
|
if (headContent || workdirContent) {
|
|
const diff = plugins.diff.createTwoFilesPatch(filepath, filepath, headContent, workdirContent);
|
|
diffs.push(diff);
|
|
}
|
|
}
|
|
|
|
return diffs;
|
|
}
|
|
|
|
/**
|
|
* Get all commit messages
|
|
*/
|
|
public async getAllCommitMessages(): Promise<string[]> {
|
|
const commits = await plugins.isomorphicGit.log({
|
|
fs: this.smartgitRef.envDeps.fs,
|
|
dir: this.repoDir,
|
|
});
|
|
return commits.map(commit => commit.commit.message);
|
|
}
|
|
}
|