public void Clone() { Log("Start cloning..."); StringBuilder arguments = new StringBuilder("svn init --prefix=svn/ "); if (!string.IsNullOrWhiteSpace(Options.UserName)) { arguments.AppendFormat("--username=\"{0}\" ", Options.UserName); } if (!Options.IncludeMetaData) { arguments.Append("--no-metadata "); } if (Options.NoMinimizeUrl) { arguments.Append("--no-minimize-url "); } var branches = Options.Branches == null ? new List <string>() : new List <string>(Options.Branches); var tags = Options.Tags == null ? new List <string>() : new List <string>(Options.Tags); 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)) { arguments.AppendFormat("--trunk=\"{0}\" ", Options.SubpathToTrunk); } if (!Options.NoTags) { 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) { 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 + "\""); if (CommandRunner.RunGitSvnInteractiveCommand(arguments.ToString(), Options.Password) != 0) { string exceptionMessage = string.Format(ExceptionHelper.ExceptionMessage.FAIL_TO_EXECUTE_COMMAND, $"git {arguments.ToString()}"); throw new MigrateException(exceptionMessage); } if (!string.IsNullOrWhiteSpace(Options.Authors)) { string args = string.Format("{0} svn.authorsfile {1}", GitConfigCommandArguments, Options.Authors); CommandRunner.Run("git", args); } arguments = new StringBuilder("svn fetch "); if (!string.IsNullOrWhiteSpace(Options.Revision)) { 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); } if (Options.Exclude != null && Options.Exclude.Any()) { // Add exclude paths to the command line. Some versions of git support // this for fetch only, later also for init. List <string> regex = new List <string>(); if (!Options.RootIsTrunk) { if (!string.IsNullOrWhiteSpace(Options.SubpathToTrunk)) { regex.Add(Options.SubpathToTrunk + @"[\/]"); } if (!Options.NoTags && tags.Count > 0) { foreach (var t in tags) { regex.Add(t + @"[\/][^\/]+[\/]"); } } if (!Options.NoBranches && branches.Count > 0) { foreach (var b in branches) { regex.Add(b + @"[\/][^\/]+[\/]"); } } } string regexStr = "^(?:" + string.Join("|", regex) + ")(?:" + string.Join("|", Options.Exclude) + ")"; arguments.AppendFormat("--ignore-paths=\"{0}\" ", regexStr); } if (CommandRunner.Run("git", arguments.ToString().Trim()) != 0) { throw new MigrateException($"Fail to execute command \"git {arguments.ToString()}\". Run with -v or --verbose for details."); } FetchBranches(); Log("End clone."); }
public void OptimizeRepos() { CommandRunner.Run("git", "gc"); }
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.UserName); int exitCode = 0; if (string.IsNullOrWhiteSpace(Options.UserName)) { exitCode = RunCommand(cmdInfo); } else { exitCode = CommandRunner.RunGitSvnInteractiveCommand(cmdInfo.Arguments, Options.Password); } 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."); }
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"); } } } }