private void DoGitInit(IList <string> branches, IList <string> tags) { StringBuilder arguments = new StringBuilder("svn init --prefix=svn/ "); if (Options.GetUserName() != null) { arguments.AppendFormat("--username=\"{0}\" ", Options.GetUserName()); } if (Options.IncludeMetaData == false) { arguments.Append("--no-metadata "); } if (Options.NoMinimizeUrl) { arguments.Append("--no-minimize-url "); } if (Options.RootIsTrunk) { // Non-standard repository layout. // The repository root is effectively trunk. // // Note: There's a bug of git svn init so that we cannot assign the svn url to --trunk. // We assign "/" to --trunk to tell git svn init we're using root as trunk. arguments.Append("--trunk=\"/\" "); } else { // Add each component to the command that was passed as an argument. if (string.IsNullOrWhiteSpace(Options.SubpathToTrunk) == false) { arguments.AppendFormat("--trunk=\"{0}\" ", Options.SubpathToTrunk); } if (Options.NoTags == false) { if (tags.Count == 0) { // Fill default tags here so that they can be filtered later tags.Add("tags"); } // Process default or user-supplied tags foreach (var t in tags) { arguments.AppendFormat("--tags=\"{0}\" ", t); } } if (Options.NoBranches == false) { if (branches.Count == 0) { // Fill default branches here so that they can be filtered later branches.Add("branches"); } // Process default or user-supplied branches foreach (var b in branches) { arguments.AppendFormat("--branches=\"{0}\" ", b); } } } arguments.Append(_svnUrl); this._lockBreaker.BreakLocksIfEnabled(); if (CommandRunner.RunGitSvnInteractiveCommand(arguments.ToString(), Options.GetPassword()) != 0) { string exceptionMessage = string.Format(ExceptionHelper.ExceptionMessage.FAIL_TO_EXECUTE_COMMAND, $"git {arguments.ToString()}"); throw new MigrateException(exceptionMessage); } // Setup author file after the init. if (string.IsNullOrWhiteSpace(Options.Authors) == false) { string args = string.Format("{0} svn.authorsfile {1}", GitConfigCommandArguments, Options.Authors); CommandRunner.Run("git", args); } }
public void FixBranches() { Log("Start fixing branches..."); List <string> svnBranches = new List <string>(); if (_metaInfo.RemoteBranches != null) { if (_metaInfo.Tags == null) { svnBranches = _metaInfo.RemoteBranches.ToList(); } else { svnBranches = _metaInfo.RemoteBranches.Except(_metaInfo.Tags).ToList(); } svnBranches.RemoveAll(b => !Regex.IsMatch(b.Trim(), @"^svn\/")); } if (Options.IsVerbose) { Log("To fix branches include:"); foreach (var b in svnBranches) { Log(b); } } if (Options.Rebase) { Log("Rebasing..."); CommandInfo cmdInfo = CommandInfoBuilder.BuildGitSvnFetchCommandInfo(Options.GetUserName()); int exitCode = 0; if (string.IsNullOrWhiteSpace(Options.GetUserName())) { exitCode = RunCommand(cmdInfo); } else { exitCode = CommandRunner.RunGitSvnInteractiveCommand(cmdInfo.Arguments, Options.GetPassword()); } if (exitCode != 0) { throw new MigrateException(string.Format(ExceptionHelper.ExceptionMessage.FAIL_TO_EXECUTE_COMMAND, cmdInfo.ToString())); } } // In case of large branches, we build a hash set to boost the query later. HashSet <string> localBranchSet = new HashSet <string>(_metaInfo.LocalBranches); if (Options.IsVerbose) { StringBuilder sb = new StringBuilder("We have following local branches:"); sb.AppendLine(); foreach (var b in _metaInfo.LocalBranches) { sb.AppendLine(b); } Log(sb.ToString()); } foreach (var b in svnBranches) { var branch = Regex.Replace(b, @"^svn\/", "").Trim(); bool isTrunkBranchOrIsLocalBranch = branch.Equals("trunk", StringComparison.InvariantCulture) || localBranchSet.Contains(branch); Log($"Current branch is {b}"); Log($"Current branch without prefix: {branch}"); Log($"IsTrunkBranchOrIsLocalBranch: {isTrunkBranchOrIsLocalBranch}"); if (Options.Rebase && isTrunkBranchOrIsLocalBranch) { string localBranch = branch == "trunk" ? "master" : branch; CommandInfo forceCheckoutLocalBranchCommandInfo = CommandInfoBuilder.BuildForceCheckoutLocalBranchCommandInfo(localBranch); CommandInfo rebaseRemoteBranchCommandInfo = CommandInfoBuilder.BuildGitRebaseRemoteSvnBranchCommandInfo(branch); RunCommand(CommandInfoBuilder.BuildForceCheckoutLocalBranchCommandInfo(localBranch)); RunCommand(CommandInfoBuilder.BuildGitRebaseRemoteSvnBranchCommandInfo(branch)); continue; } if (isTrunkBranchOrIsLocalBranch) { Log($"{branch} is trunk branch or local branch, skip."); continue; } // Now checkout the remote svn branch. RunCommand(CommandInfoBuilder.BuildCheckoutSvnRemoteBranchCommandInfo(branch)); } Log("End fixing branches."); }
private void DoFetch(IList <string> branches, IList <string> tags) { StringBuilder arguments = new StringBuilder("svn fetch "); if (string.IsNullOrWhiteSpace(Options.Revision) == false) { var range = Options.Revision.Split(":"); string start = range[0]; string end = range.Length < 2 || string.IsNullOrWhiteSpace(range[1]) ? "HEAD" : range[1]; arguments.AppendFormat("-r {0}:{1} ", start, end); } string ignorePathRegex = IgnorePathBuilder.BuildIgnorePathRegex( Options, branches, tags ); if (string.IsNullOrWhiteSpace(ignorePathRegex) == false) { arguments.AppendFormat("--ignore-paths=\"{0}\" ", ignorePathRegex); } //---- Fetch ---- this._gcIgnorer.DeleteGcLogIfEnabled(); this._lockBreaker.BreakLocksIfEnabled(); int lastRevision = -1; int currentRevision = lastRevision; void ParseRevision(string s) { Match match = revisionRegex.Match(s); if (match.Success) { int.TryParse(match.Groups["rev"].Value, out currentRevision); } } bool success = false; int currentAttempt = 0; do { try { int exitCode = CommandRunner.Run( "git", arguments.ToString().Trim(), ParseRevision, null, null, this.Options.GetFetchTimeout() ); if (exitCode == 0) { Log("Fetch Successful!"); success = true; break; } else if (lastRevision != currentRevision) { Log("Made Progress, will not increment attempt"); lastRevision = currentRevision; // We made progress! Reset our current attempts. currentAttempt = 0; } else { ++currentAttempt; LogWarning("No progress made, attempt #" + currentAttempt + " was a failure"); } } catch (TimeoutException e) { LogWarning(e.Message); ++currentAttempt; LogWarning("Attempt #" + currentAttempt + " was a failure"); } this._gcIgnorer.DeleteGcLogIfEnabled(); this._lockBreaker.BreakLocksIfEnabled(); }while((this.Options.FetchAttempts < 0) || (currentAttempt <= this.Options.FetchAttempts)); if (success == false) { throw new MigrateException( $"Fail to execute command \"git {arguments.ToString()}\". Run with -v or --verbose for details." ); } }
public void OptimizeRepos() { CommandRunner.Run("git", "gc"); }
public void FixTags() { string currentUserName = string.Empty; string currentUserEmail = string.Empty; try { if (_metaInfo.Tags != null) { Log("Reading user.name and user.email..."); CommandRunner.Run("git", $"{GitConfigCommandArguments} --get user.name", out currentUserName); CommandRunner.Run("git", $"{GitConfigCommandArguments} --get user.email", out currentUserEmail); Log($"user.name: {currentUserName}"); Log($"user.email: {currentUserEmail}"); foreach (string t in _metaInfo.Tags) { string tag = t.Trim(); Log($"Processing tag: {tag}"); string id = Regex.Replace(tag, @"^svn\/tags\/", "").Trim(); Log($"id: {id}"); string quotesFreeTag = Utils.EscapeQuotes(tag); Log($"quotes free tag: {tag}"); string subject = Utils.RemoveFromTwoEnds(RunCommandIgnoreExitCode("git", $"log -1 --pretty=format:'%s' \"{quotesFreeTag}\""), '\''); string date = Utils.RemoveFromTwoEnds(RunCommandIgnoreExitCode("git", $"log -1 --pretty=format:'%ci' \"{quotesFreeTag}\""), '\''); string author = Utils.RemoveFromTwoEnds(RunCommandIgnoreExitCode("git", $"log -1 --pretty=format:'%an' \"{quotesFreeTag}\""), '\''); string email = Utils.RemoveFromTwoEnds(RunCommandIgnoreExitCode("git", $"log -1 --pretty=format:'%ae' \"{quotesFreeTag}\""), '\''); string quotesFreeAuthor = Utils.EscapeQuotes(author); CommandRunner.Run("git", $"{GitConfigCommandArguments} user.name \"{quotesFreeAuthor}\""); CommandRunner.Run("git", $"{GitConfigCommandArguments} user.email \"{quotesFreeAuthor}\""); string originalGitCommitterDate = Environment.GetEnvironmentVariable("GIT_COMMITTER_DATE"); Environment.SetEnvironmentVariable("GIT_COMMITTER_DATE", Utils.EscapeQuotes(date)); CommandRunner.Run("git", $"tag -a -m \"{Utils.EscapeQuotes( subject )}\" \"{Utils.EscapeQuotes( id )}\" \"{quotesFreeTag}\""); Environment.SetEnvironmentVariable("GIT_COMMITTER_DATE", originalGitCommitterDate); CommandRunner.Run("git", $"branch -d -r \"{quotesFreeTag}\""); } } } finally { // We only change the git config values if there are @tags available. // So it stands to reason we should revert them only in that case. if (_metaInfo.Tags != null && _metaInfo.Tags.Any()) { // If a line was read, then there was a config value so restore it. // Otherwise unset the value because originally there was none. if (!string.IsNullOrWhiteSpace(currentUserName)) { CommandRunner.Run("git", $"{GitConfigCommandArguments} user.name \"{currentUserName.Trim()}\""); } else { CommandRunner.Run("git", $"{GitConfigCommandArguments} --unset user.name"); } if (!string.IsNullOrWhiteSpace(currentUserEmail)) { CommandRunner.Run("git", $"{GitConfigCommandArguments} user.email \"{currentUserEmail.Trim()}\""); } else { CommandRunner.Run("git", $"{GitConfigCommandArguments} --unset user.email"); } } } }
protected int RunCommand(CommandInfo cmdInfo, out string standardOutput, out string standardError) { return(CommandRunner.Run(cmdInfo.Command, cmdInfo.Arguments, out standardOutput, out standardError)); }
protected int RunCommand(CommandInfo cmdInfo) { return(CommandRunner.Run(cmdInfo.Command, cmdInfo.Arguments)); }
static void Migrate(Options options, string[] args) { if (string.IsNullOrWhiteSpace(options.ConfigFile) == false) { if (File.Exists(options.ConfigFile) == false) { throw new FileNotFoundException("Could not find file " + options.ConfigFile); } Console.WriteLine("Using option file: " + options.ConfigFile); OptionXmlParser.ParseOptionFromFile(options, options.ConfigFile); } using (CancellationTokenSource cancelToken = new CancellationTokenSource()) { ConsoleCancelEventHandler onCtrlC = delegate(object sender, ConsoleCancelEventArgs cancelArgs) { // Wait for the process to end gracefully if we get CTRL+C, // otherwise, let it die without clean up if we get CTRL+Break. if (cancelArgs.SpecialKey == ConsoleSpecialKey.ControlC) { cancelArgs.Cancel = true; Console.WriteLine("CTRL+C was received, cleaning up..."); cancelToken.Cancel(); } }; try { Console.CancelKeyPress += onCtrlC; ILoggerFactory loggerFactory = LoggerFactory.Create( builder => { builder.AddConsole(); } ); ICommandRunner commandRunner = new CommandRunner( loggerFactory.CreateLogger <CommandRunner>(), options.IsVerbose, cancelToken.Token ); IMessageDisplayer messageDisplayer = new ConsoleMessageDisplayer(); int exitCode = commandRunner.Run("git", "svn --version"); if (exitCode != 0) { throw new PlatformNotSupportedException("git svn not installed"); } Migrator migrator = new Migrator( options, args, commandRunner, messageDisplayer, loggerFactory ); migrator.Initialize(); migrator.Run(); } catch (OperationCanceledException) { Console.WriteLine("CTRL+C was received, child processes have been killed."); } finally { Console.CancelKeyPress -= onCtrlC; } } }