Functions/GenXdev.Coding.Git/New-GitCommit.cs
// ################################################################################
// Part of PowerShell module : GenXdev.Coding.Git // Original cmdlet filename : New-GitCommit.cs // Original author : René Vaessen / GenXdev // Version : 1.302.2025 // ################################################################################ // Copyright (c) René Vaessen / GenXdev // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ################################################################################ using System; using System.Management.Automation; namespace GenXdev.Coding.Git { /// <summary> /// <para type="synopsis"> /// Creates and pushes a new git commit with all changes. /// </para> /// /// <para type="description"> /// Stages all changes in the current git repository, creates a commit with the /// specified title, and pushes the changes to the remote origin. Automatically sets /// up upstream tracking if needed. /// </para> /// /// <para type="description"> /// PARAMETERS /// </para> /// /// <para type="description"> /// -Title <String><br/> /// The message to use for the git commit. If not specified, defaults to /// "Improved scripts".<br/> /// - <b>Position</b>: 0<br/> /// - <b>Default</b>: "Improved scripts"<br/> /// </para> /// /// <example> /// <para>Create a commit with a custom message</para> /// <para>This example creates a commit with the message "Added new authentication feature".</para> /// <code> /// New-GitCommit -Title "Added new authentication feature" /// </code> /// </example> /// /// <example> /// <para>Create a commit using the alias</para> /// <para>This example uses the 'commit' alias to create a commit with default message.</para> /// <code> /// commit "Hotfix for login issue" /// </code> /// </example> /// </summary> [Cmdlet(VerbsCommon.New, "GitCommit")] [Alias("commit")] [OutputType(typeof(void))] public class NewGitCommitCommand : PSGenXdevCmdlet { /// <summary> /// The commit message title to use /// </summary> [Parameter( Position = 0, Mandatory = false, ValueFromRemainingArguments = false, HelpMessage = "The commit message title to use")] public string Title { get; set; } = "Improved scripts"; private string branch; /// <summary> /// Initialize the cmdlet and extract the current branch name /// </summary> protected override void BeginProcessing() { // Extract the current branch name from git's symbolic reference var branchResult = InvokeCommand.InvokeScript("git symbolic-ref refs/remotes/origin/HEAD"); if (branchResult.Count > 0 && branchResult[0].BaseObject != null) { string branchRef = branchResult[0].BaseObject.ToString(); branch = branchRef.Split('/')[3]; WriteVerbose($"Operating on git branch: {branch}"); Console.WriteLine($"Current branch: {branch}"); } else { WriteError(new ErrorRecord(new Exception("Failed to get branch information"), "BranchDetectionFailed", ErrorCategory.OperationStopped, null)); return; } } /// <summary> /// Process the commit operation /// </summary> protected override void ProcessRecord() { if (string.IsNullOrEmpty(branch)) { WriteError(new ErrorRecord( new InvalidOperationException("Branch information is not available."), "BranchNotSet", ErrorCategory.InvalidOperation, null)); return; } // Add all changed files to git staging area WriteVerbose("Staging all modified files..."); if (ShouldProcess("all changes", "git add")) { var addScript = ScriptBlock.Create("$gitOutput = git add * 2>&1; $gitOutput; $LASTEXITCODE"); var addResult = addScript.Invoke(); int exitCode = 0; for (int i = 0; i < addResult.Count; i++) { if (i == addResult.Count - 1 && addResult[i].BaseObject is int ec) { exitCode = ec; } else if (addResult[i].BaseObject != null && addResult[i].BaseObject is string output) { Console.WriteLine(output); } } if (exitCode != 0) { WriteError(new ErrorRecord(new Exception("Failed to stage changes"), "GitAddFailed", ErrorCategory.OperationStopped, null)); return; } } // Create a new commit with the specified title WriteVerbose($"Creating commit with message: {Title}"); if (ShouldProcess($"commit with title: {Title}", "git commit")) { var commitScript = ScriptBlock.Create("param($title) $gitOutput = git commit -m $title 2>&1; $gitOutput; $LASTEXITCODE"); var commitResult = commitScript.Invoke(Title); int exitCode = 0; for (int i = 0; i < commitResult.Count; i++) { if (i == commitResult.Count - 1 && commitResult[i].BaseObject is int ec) { exitCode = ec; } else if (commitResult[i].BaseObject != null && commitResult[i].BaseObject is string output) { Console.WriteLine(output); } } if (exitCode != 0) { WriteError(new ErrorRecord(new Exception("Failed to create commit"), "GitCommitFailed", ErrorCategory.OperationStopped, null)); return; } } // Ensure branch is tracking upstream remote WriteVerbose($"Configuring upstream tracking to origin/{branch}"); if (ShouldProcess($"upstream branch to origin/{branch}", "git push -u")) { var upstreamScript = ScriptBlock.Create("param($branch) $gitOutput = git push -u origin $branch 2>&1; $gitOutput; $LASTEXITCODE"); var upstreamResult = upstreamScript.Invoke(branch); int exitCode = 0; for (int i = 0; i < upstreamResult.Count; i++) { if (i == upstreamResult.Count - 1 && upstreamResult[i].BaseObject is int ec) { exitCode = ec; } else if (upstreamResult[i].BaseObject != null && upstreamResult[i].BaseObject is string output) { Console.WriteLine(output); } } if (exitCode != 0) { WriteError(new ErrorRecord(new Exception("Failed to set upstream branch"), "GitUpstreamFailed", ErrorCategory.OperationStopped, null)); return; } } // Push committed changes to remote repository WriteVerbose("Pushing changes to remote repository..."); if (ShouldProcess("changes to remote", "git push")) { var pushScript = ScriptBlock.Create("$gitOutput = git push 2>&1; $gitOutput; $LASTEXITCODE"); var pushResult = pushScript.Invoke(); int exitCode = 0; for (int i = 0; i < pushResult.Count; i++) { if (i == pushResult.Count - 1 && pushResult[i].BaseObject is int ec) { exitCode = ec; } else if (pushResult[i].BaseObject != null && pushResult[i].BaseObject is string output) { Console.WriteLine(output); } } if (exitCode != 0) { WriteError(new ErrorRecord(new Exception("Failed to push changes"), "GitPushFailed", ErrorCategory.OperationStopped, null)); return; } } } /// <summary> /// Clean up after processing /// </summary> protected override void EndProcessing() { // No cleanup needed } } } |