Пример #1
0
        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);
            }
        }
Пример #2
0
        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.");
        }
Пример #3
0
        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."
                          );
            }
        }
Пример #4
0
 public void OptimizeRepos()
 {
     CommandRunner.Run("git", "gc");
 }
Пример #5
0
        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");
                    }
                }
            }
        }
Пример #6
0
 protected int RunCommand(CommandInfo cmdInfo, out string standardOutput, out string standardError)
 {
     return(CommandRunner.Run(cmdInfo.Command, cmdInfo.Arguments, out standardOutput, out standardError));
 }
Пример #7
0
 protected int RunCommand(CommandInfo cmdInfo)
 {
     return(CommandRunner.Run(cmdInfo.Command, cmdInfo.Arguments));
 }
Пример #8
0
        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;
                }
            }
        }