예제 #1
0
        public static string SubmoduleSyncCmd(string name)
        {
            var args = new ArgumentBuilder
            {
                "submodule sync",
                name?.Trim().QuoteNE()
            };

            return(args.ToString());
        }
        private static string GetBisectCommand(GitBisectOption bisectOption)
        {
            var args = new ArgumentBuilder
            {
                "bisect",
                bisectOption
            };

            return(args.ToString());
        }
예제 #3
0
        public static string BranchCmd(string branchName, string revision, bool checkout)
        {
            var args = new ArgumentBuilder
            {
                { checkout, "checkout -b", "branch" },
                branchName.Trim().Quote(),
                revision?.Trim().QuoteNE()
            };

            return(args.ToString());
        }
예제 #4
0
        public static string ContinueBisectCmd(GitBisectOption bisectOption, params string[] revisions)
        {
            var args = new ArgumentBuilder
            {
                "bisect",
                bisectOption,
                revisions
            };

            return(args.ToString());
        }
예제 #5
0
        public static string ApplyDiffPatchCmd(bool ignoreWhiteSpace, [NotNull] string patchFile)
        {
            var args = new ArgumentBuilder
            {
                "apply",
                { ignoreWhiteSpace, "--ignore-whitespace" },
                patchFile.ToPosixPath().Quote()
            };

            return(args.ToString());
        }
예제 #6
0
        /// <summary>
        /// Split arguments exceeding max length into multiple batches.
        /// Windows by default limit arguments length less than 32767 <see cref="short.MaxValue"/>.
        /// Implementation by <see cref="System.Diagnostics.Process"/> will have file path included in command line arguments,
        /// as well as added quotation and space characters, so we need base length to account for all these added characters
        /// <see href="https://referencesource.microsoft.com/#system/services/monitoring/system/diagnosticts/Process.cs,1944"/>
        /// </summary>
        /// <param name="builder">Argument builder instance.</param>
        /// <param name="arguments">Arguments.</param>
        /// <param name="baseLength">Base executable file and command line length.</param>
        /// <param name="maxLength">Command line max length. Default is 32767 - 1 on Windows.</param>
        /// <returns>Array of batch arguments split by max length.</returns>
        public static ArgumentString[] BuildBatchArguments(this ArgumentBuilder builder, IEnumerable <string> arguments, int baseLength, int maxLength = short.MaxValue)
        {
            var baseArgument = builder.ToString();

            if (baseLength + baseArgument.Length >= maxLength)
            {
                throw new ArgumentException($"Git base command \"{baseArgument}\" always reached max length of {maxLength} characters.", nameof(baseArgument));
            }

            // Clone command as argument builder
            var batches = new List <ArgumentString>();
            var currentArgumentLength = baseArgument.Length;
            var lastBatchBuilder      = arguments.Aggregate(builder, (currentBatchBuilder, argument) =>
            {
                // 1: ' ' space character length will be added
                // When enumeration is finished, no need to add ' ' to length calculcation
                if (baseLength + currentArgumentLength + 1 + argument.Length >= maxLength)
                {
                    // Handle abnormal case when base command and a single argument exceed max length
                    if (currentArgumentLength == baseArgument.Length)
                    {
                        throw new ArgumentException($"Git command \"{currentBatchBuilder}\" always exceeded max length of {maxLength} characters.", nameof(arguments));
                    }

                    // Finish current command line
                    batches.Add(currentBatchBuilder);

                    // Return new argument builder
                    currentArgumentLength = baseArgument.Length + 1 + argument.Length;
                    return(new ArgumentBuilder()
                    {
                        baseArgument, argument
                    });
                }

                currentBatchBuilder.Add(argument);
                currentArgumentLength += argument.Length + 1;
                return(currentBatchBuilder);
            });

            // Handle rare case when last argument length exceed max length
            if (baseLength + currentArgumentLength >= maxLength)
            {
                throw new ArgumentException($"Git command \"{lastBatchBuilder}\" always exceeded max length of {maxLength} characters.", nameof(arguments));
            }

            // Add last commandline batch
            if (!lastBatchBuilder.IsEmpty)
            {
                batches.Add(lastBatchBuilder.ToString());
            }

            return(batches.ToArray());
        }
예제 #7
0
        public static string RevertCmd(string commit, bool autoCommit, int parentIndex)
        {
            var args = new ArgumentBuilder
            {
                "revert",
                { !autoCommit, "--no-commit" },
                { parentIndex > 0, $"-m {parentIndex}" },
                commit
            };

            return(args.ToString());
        }
예제 #8
0
        public static string CherryPickCmd(string cherry, bool commit, string arguments)
        {
            var args = new ArgumentBuilder
            {
                "cherry-pick",
                { !commit, "--no-commit" },
                arguments,
                cherry.Quote()
            };

            return(args.ToString());
        }
예제 #9
0
        public static string CherryPickCmd(ObjectId commitId, bool commit, string arguments)
        {
            var args = new ArgumentBuilder
            {
                "cherry-pick",
                { !commit, "--no-commit" },
                arguments,
                commitId
            };

            return(args.ToString());
        }
예제 #10
0
        public static string GetAllChangedFilesCmd(bool excludeIgnoredFiles, UntrackedFilesMode untrackedFiles, IgnoreSubmodulesMode ignoreSubmodules = IgnoreSubmodulesMode.None)
        {
            var args = new ArgumentBuilder
            {
                "status --porcelain -z",
                untrackedFiles,
                ignoreSubmodules,
                { !excludeIgnoredFiles, "--ignored" }
            };

            return(args.ToString());
        }
예제 #11
0
        public static string CheckoutCmd(string branchOrRevisionName, LocalChangesAction changesAction)
        {
            var args = new ArgumentBuilder
            {
                "checkout",
                { changesAction == LocalChangesAction.Merge, "--merge" },
                { changesAction == LocalChangesAction.Reset, "--force" },
                branchOrRevisionName.Quote()
            };

            return(args.ToString());
        }
예제 #12
0
        /// <summary>Creates the 'push' command string. <example>"push --progress origin master:master"</example></summary>
        public override string ToString()
        {
            var args = new ArgumentBuilder
            {
                "push",
                { ReportProgress, "--progress" },
                Remote.Quote(),
                PushActions.Select(action => action.ToString())
            };

            return(args.ToString());
        }
예제 #13
0
        public static string GetAllChangedFilesCmd(bool excludeIgnoredFiles, UntrackedFilesMode untrackedFiles, IgnoreSubmodulesMode ignoreSubmodules = IgnoreSubmodulesMode.None, bool noLocks = false)
        {
            var args = new ArgumentBuilder
            {
                { noLocks&& VersionInUse.SupportNoOptionalLocks, "--no-optional-locks" },
                $"status --porcelain={(VersionInUse.SupportStatusPorcelainV2 ? 2 : 1)} -z",
                untrackedFiles,
                ignoreSubmodules,
                { !excludeIgnoredFiles, "--ignored" }
            };

            return(args.ToString());
        }
예제 #14
0
        public static string AddSubmoduleCmd(string remotePath, string localPath, string branch, bool force)
        {
            var args = new ArgumentBuilder
            {
                "submodule add",
                { force, "-f" },
                { !string.IsNullOrEmpty(branch), $"-b \"{branch?.Trim()}\"" },
                remotePath.ToPosixPath().Quote(),
                localPath.ToPosixPath().Quote()
            };

            return(args.ToString());
        }
예제 #15
0
        public static string ApplyMailboxPatchCmd(bool ignoreWhiteSpace, string patchFile = null)
        {
            var args = new ArgumentBuilder
            {
                "am",
                "--3way",
                "--signoff",
                { ignoreWhiteSpace, "--ignore-whitespace" },
                patchFile?.ToPosixPath().Quote()
            };

            return(args.ToString());
        }
예제 #16
0
        /// <summary>Remove files from the working tree and from the index. <remarks>git rm</remarks></summary>
        /// <param name="force">Override the up-to-date check.</param>
        /// <param name="isRecursive">Allow recursive removal when a leading directory name is given.</param>
        /// <param name="files">Files to remove. Fileglobs can be given to remove matching files.</param>
        public static string RemoveCmd(bool force = true, bool isRecursive = true, params string[] files)
        {
            var args = new ArgumentBuilder
            {
                "rm",
                { force, "--force" },
                { isRecursive, "-r" },
                { files.Length == 0, "." },
                files
            };

            return(args.ToString());
        }
예제 #17
0
        public static string CleanUpCmd(bool dryrun, bool directories, bool nonignored, bool ignored, string paths = null)
        {
            var args = new ArgumentBuilder
            {
                "clean",
                { directories, "-d" },
                { !nonignored && !ignored, "-x" },
                { ignored, "-X" },
                { dryrun, "--dry-run" },
                { !dryrun, "-f" },
                paths
            };

            return(args.ToString());
        }
예제 #18
0
        public static string StashSaveCmd(bool untracked, bool keepIndex, string message, IReadOnlyList <string> selectedFiles)
        {
            var isPartialStash = selectedFiles != null && selectedFiles.Any();

            var args = new ArgumentBuilder
            {
                "stash",
                { isPartialStash, "push", "save" },
                { untracked&& VersionInUse.StashUntrackedFilesSupported, "-u" },
                { keepIndex, "--keep-index" },
                message.QuoteNE(),
                { isPartialStash, "--" },
                { isPartialStash, selectedFiles }
            };

            return(args.ToString());
        }
예제 #19
0
        public static string MergeBranchCmd(string branch, bool allowFastForward, bool squash, bool noCommit, string strategy, bool allowUnrelatedHistories, string message, int?log)
        {
            // TODO Quote should escape any " characters, at least for usages like the below

            var args = new ArgumentBuilder
            {
                "merge",
                { !allowFastForward, "--no-ff" },
                { !string.IsNullOrEmpty(strategy), $"--strategy={strategy}" },
                { squash, "--squash" },
                { noCommit, "--no-commit" },
                { allowUnrelatedHistories, "--allow-unrelated-histories" },
                { !string.IsNullOrEmpty(message), $"-m {message.Quote()}" },
                { log != null, $"--log={log}" },
                branch
            };

            return(args.ToString());
        }
예제 #20
0
        public static string PushTagCmd(string path, string tag, bool all, ForcePushOptions force = ForcePushOptions.DoNotForce)
        {
            if (!all && string.IsNullOrWhiteSpace(tag))
            {
                // TODO this is probably an error
                return("");
            }

            var args = new ArgumentBuilder
            {
                "push",
                force,
                { VersionInUse.PushCanAskForProgress, "--progress" },
                path.ToPosixPath().Trim().Quote(),
                { all, "--tags" },
                { !all, $"tag {tag.Replace(" ", "")}" }
            };

            return(args.ToString());
        }
예제 #21
0
        public static string RebaseCmd(string branch, bool interactive, bool preserveMerges, bool autosquash, bool autostash, string from = null, string onto = null)
        {
            if (from == null ^ onto == null)
            {
                throw new ArgumentException($"For arguments \"{nameof(from)}\" and \"{nameof(onto)}\", either both must have values, or neither may.");
            }

            var args = new ArgumentBuilder
            {
                "rebase",
                { interactive, "-i" },
                { interactive&& autosquash, "--autosquash" },
                { interactive&& !autosquash, "--no-autosquash" },
                { preserveMerges, "--preserve-merges" },
                { autostash, "--autostash" },
                from.QuoteNE(),
                branch.Quote(),
                { onto != null, $"--onto {onto}" }
            };

            return(args.ToString());
        }
예제 #22
0
        /// <summary>
        /// Git Clone.
        /// </summary>
        /// <param name="central">Makes a bare repo.</param>
        /// <param name="branch">
        /// <para><c>NULL</c>: do not checkout working copy (--no-checkout).</para>
        /// <para><c>""</c> (empty string): checkout remote HEAD (branch param omitted, default behavior for clone).</para>
        /// <para>(a non-empty string): checkout the given branch (--branch smth).</para>
        /// </param>
        /// <param name="depth">An int value for --depth param, or <c>NULL</c> to omit the param.</param>
        /// <param name="isSingleBranch">
        /// <para><c>True</c>: --single-branch.</para>
        /// <para><c>False</c>: --no-single-branch.</para>
        /// <para><c>NULL</c>: don't pass any such param to git.</para>
        /// </param>
        /// <param name="lfs">True to use the <c>git lfs clone</c> command instead of <c>git clone</c>.</param>
        public static string CloneCmd(string fromPath, string toPath, bool central = false, bool initSubmodules = false, [CanBeNull] string branch = "", int?depth = null, bool?isSingleBranch = null, bool lfs = false)
        {
            var from = PathUtil.IsLocalFile(fromPath) ? fromPath.ToPosixPath() : fromPath;

            var args = new ArgumentBuilder
            {
                { lfs, "lfs" },
                "clone",
                "-v",
                { central, "--bare" },
                { initSubmodules, "--recurse-submodules" },
                { depth != null, $"--depth {depth}" },
                { isSingleBranch == true, "--single-branch" },
                { isSingleBranch == false, "--no-single-branch" },
                "--progress",
                { branch == null, "--no-checkout" },
                { !string.IsNullOrEmpty(branch), $"--branch {branch}" },
                from.Trim().Quote(),
                toPath.ToPosixPath().Trim().Quote()
            };

            return(args.ToString());
        }
        /// <summary>
        /// Split arguments exceeding max length into multiple batches.
        /// Windows by default limit arguments length less than 32767 <see cref="short.MaxValue"/>.
        /// Implementation by <see cref="System.Diagnostics.Process"/> will have file path included in command line arguments,
        /// as well as added quotation and space characters, so we need base length to account for all these added characters
        /// <see href="https://referencesource.microsoft.com/#system/services/monitoring/system/diagnosticts/Process.cs,1944"/>
        /// </summary>
        /// <param name="builder">Argument builder instance.</param>
        /// <param name="arguments">Arguments.</param>
        /// <param name="baseLength">Base executable file and command line length.</param>
        /// <param name="maxLength">Command line max length. Default is 32767 - 1 on Windows.</param>
        /// <returns>Array of batch arguments split by max length.</returns>
        public static List <BatchArgumentItem> BuildBatchArguments(this ArgumentBuilder builder, IEnumerable <string> arguments, int?baseLength = null, int maxLength = short.MaxValue)
        {
            // 3: double quotes + ' '
            // '"git.exe" ' is always included in final command line arguments
            if (!baseLength.HasValue)
            {
                baseLength = AppSettings.GitCommand.Length + 3;
            }

            var baseArgument = builder.ToString();

            if (baseLength + baseArgument.Length >= maxLength)
            {
                throw new ArgumentException($"Git base command \"{baseArgument}\" always reached max length of {maxLength} characters.", nameof(baseArgument));
            }

            // Clone command as argument builder
            var batches = new List <BatchArgumentItem>();
            var currentBatchItemCount = 0;
            var currentArgumentLength = baseArgument.Length;
            var lastBatchBuilder      = arguments.Aggregate(builder, (currentBatchBuilder, argument) =>
            {
                // 1: ' ' space character length will be added
                // When enumeration is finished, no need to add ' ' to length calculcation
                if (baseLength + currentArgumentLength + 1 + argument.Length >= maxLength)
                {
                    // Handle abnormal case when base command and a single argument exceed max length
                    if (currentBatchItemCount == 0)
                    {
                        throw new ArgumentException($"Git command \"{currentBatchBuilder}\" always exceeded max length of {maxLength} characters.", nameof(arguments));
                    }

                    // Finish current command line
                    batches.Add(new BatchArgumentItem(currentBatchBuilder, currentBatchItemCount));

                    // Return new argument builder
                    currentBatchItemCount = 1;
                    currentArgumentLength = baseArgument.Length + 1 + argument.Length;
                    return(new ArgumentBuilder()
                    {
                        baseArgument, argument
                    });
                }

                currentBatchBuilder.Add(argument);
                currentArgumentLength += argument.Length + 1;
                currentBatchItemCount++;
                return(currentBatchBuilder);
            });

            // Handle rare case when last argument length exceed max length
            if (baseLength + currentArgumentLength >= maxLength)
            {
                throw new ArgumentException($"Git command \"{lastBatchBuilder}\" always exceeded max length of {maxLength} characters.", nameof(arguments));
            }

            // Add last commandline batch
            if (!lastBatchBuilder.IsEmpty)
            {
                batches.Add(new BatchArgumentItem(lastBatchBuilder, currentBatchItemCount));
            }

            return(batches);
        }