mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 10:02:05 +00:00
feat(Git Node): Add support for branches (#18870)
This commit is contained in:
@@ -5,7 +5,7 @@ import type {
|
||||
INodeType,
|
||||
INodeTypeDescription,
|
||||
} from 'n8n-workflow';
|
||||
import { NodeConnectionTypes } from 'n8n-workflow';
|
||||
import { NodeConnectionTypes, assertParamIsBoolean, assertParamIsString } from 'n8n-workflow';
|
||||
import type { LogOptions, SimpleGit, SimpleGitOptions } from 'simple-git';
|
||||
import simpleGit from 'simple-git';
|
||||
import { URL } from 'url';
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
commitFields,
|
||||
logFields,
|
||||
pushFields,
|
||||
switchBranchFields,
|
||||
tagFields,
|
||||
} from './descriptions';
|
||||
|
||||
@@ -141,6 +142,12 @@ export class Git implements INodeType {
|
||||
description: 'Return status of current repository',
|
||||
action: 'Return status of current repository',
|
||||
},
|
||||
{
|
||||
name: 'Switch Branch',
|
||||
value: 'switchBranch',
|
||||
description: 'Switch to a different branch',
|
||||
action: 'Switch to a different branch',
|
||||
},
|
||||
{
|
||||
name: 'Tag',
|
||||
value: 'tag',
|
||||
@@ -191,6 +198,7 @@ export class Git implements INodeType {
|
||||
...commitFields,
|
||||
...logFields,
|
||||
...pushFields,
|
||||
...switchBranchFields,
|
||||
...tagFields,
|
||||
// ...userSetupFields,
|
||||
],
|
||||
@@ -215,6 +223,58 @@ export class Git implements INodeType {
|
||||
return repositoryPath;
|
||||
};
|
||||
|
||||
interface CheckoutBranchOptions {
|
||||
branchName: string;
|
||||
createBranch?: boolean;
|
||||
startPoint?: string;
|
||||
force?: boolean;
|
||||
setUpstream?: boolean;
|
||||
remoteName?: string;
|
||||
}
|
||||
|
||||
const checkoutBranch = async (
|
||||
git: SimpleGit,
|
||||
options: CheckoutBranchOptions,
|
||||
): Promise<void> => {
|
||||
const {
|
||||
branchName,
|
||||
createBranch = true,
|
||||
startPoint,
|
||||
force = false,
|
||||
setUpstream = false,
|
||||
remoteName = 'origin',
|
||||
} = options;
|
||||
try {
|
||||
if (force) {
|
||||
await git.checkout(['-f', branchName]);
|
||||
} else {
|
||||
await git.checkout(branchName);
|
||||
}
|
||||
} catch (error) {
|
||||
if (createBranch) {
|
||||
// Try to create the branch when checkout fails
|
||||
if (startPoint) {
|
||||
await git.checkoutBranch(branchName, startPoint);
|
||||
} else {
|
||||
await git.checkoutLocalBranch(branchName);
|
||||
}
|
||||
// If we reach here, branch creation succeeded
|
||||
} else {
|
||||
// Don't create branch, throw original error
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
if (setUpstream) {
|
||||
try {
|
||||
await git.addConfig(`branch.${branchName}.remote`, remoteName);
|
||||
await git.addConfig(`branch.${branchName}.merge`, `refs/heads/${branchName}`);
|
||||
} catch (upstreamError) {
|
||||
// Upstream setup failed but that's non-fatal
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const operation = this.getNodeParameter('operation', 0);
|
||||
const returnItems: INodeExecutionData[] = [];
|
||||
for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
|
||||
@@ -304,6 +364,14 @@ export class Git implements INodeType {
|
||||
// ----------------------------------
|
||||
|
||||
const message = this.getNodeParameter('message', itemIndex, '') as string;
|
||||
const branch = options.branch;
|
||||
if (branch !== undefined && branch !== '') {
|
||||
assertParamIsString('branch', branch, this.getNode());
|
||||
await checkoutBranch(git, {
|
||||
branchName: branch,
|
||||
setUpstream: true,
|
||||
});
|
||||
}
|
||||
|
||||
let pathsToAdd: string[] | undefined = undefined;
|
||||
if (options.files !== undefined) {
|
||||
@@ -379,6 +447,16 @@ export class Git implements INodeType {
|
||||
// push
|
||||
// ----------------------------------
|
||||
|
||||
const branch = options.branch;
|
||||
if (branch !== undefined && branch !== '') {
|
||||
assertParamIsString('branch', branch, this.getNode());
|
||||
await checkoutBranch(git, {
|
||||
branchName: branch,
|
||||
createBranch: false,
|
||||
setUpstream: true,
|
||||
});
|
||||
}
|
||||
|
||||
if (options.repository) {
|
||||
const targetRepository = await prepareRepository(options.targetRepository as string);
|
||||
await git.push(targetRepository);
|
||||
@@ -464,6 +542,56 @@ export class Git implements INodeType {
|
||||
};
|
||||
}),
|
||||
);
|
||||
} else if (operation === 'switchBranch') {
|
||||
// ----------------------------------
|
||||
// switchBranch
|
||||
// ----------------------------------
|
||||
|
||||
const branchName = this.getNodeParameter('branchName', itemIndex);
|
||||
assertParamIsString('branchName', branchName, this.getNode());
|
||||
|
||||
const createBranch = options.createBranch;
|
||||
if (createBranch !== undefined) {
|
||||
assertParamIsBoolean('createBranch', createBranch, this.getNode());
|
||||
}
|
||||
const remoteName =
|
||||
typeof options.remoteName === 'string' && options.remoteName
|
||||
? options.remoteName
|
||||
: 'origin';
|
||||
|
||||
const startPoint = options.startPoint;
|
||||
if (startPoint !== undefined) {
|
||||
assertParamIsString('startPoint', startPoint, this.getNode());
|
||||
}
|
||||
|
||||
const setUpstream = options.setUpstream;
|
||||
if (setUpstream !== undefined) {
|
||||
assertParamIsBoolean('setUpstream', setUpstream, this.getNode());
|
||||
}
|
||||
|
||||
const force = options.force;
|
||||
if (force !== undefined) {
|
||||
assertParamIsBoolean('force', force, this.getNode());
|
||||
}
|
||||
|
||||
await checkoutBranch(git, {
|
||||
branchName,
|
||||
createBranch,
|
||||
startPoint,
|
||||
force,
|
||||
setUpstream,
|
||||
remoteName,
|
||||
});
|
||||
|
||||
returnItems.push({
|
||||
json: {
|
||||
success: true,
|
||||
branch: branchName,
|
||||
},
|
||||
pairedItem: {
|
||||
item: itemIndex,
|
||||
},
|
||||
});
|
||||
} else if (operation === 'tag') {
|
||||
// ----------------------------------
|
||||
// tag
|
||||
|
||||
Reference in New Issue
Block a user