Ejemplo n.º 1
0
        public void Run()
        {
            _git.EnsureIsClean();

            var(wasFound, oldProjectPath, solutionFolderPath) = findProject();
            if (!wasFound)
            {
                _errors.Handle($"{_configuration.OldProjectName} cannot be found in the solution");
            }

            var oldDir  = Path.GetDirectoryName(oldProjectPath);
            var newBase = _configuration.NewProjectName.Any(CommonExtensions.IsDirectorySeparator)
                ? CurrentDirectoryAbsolute
                : Path.GetDirectoryName(oldDir);
            var newDir         = _configuration.NewProjectName.ToAbsolutePath(newBase);
            var newFileName    = Path.GetFileName(_configuration.NewProjectName);
            var newProjectPath = Path.Combine(newDir, $"{newFileName}{Constants.ProjectFileExtension}");
            var isPaketUsed    = _filesystem.DoesDirectoryExist(".paket");
            var gitVersion     = _git.GetVersion();

            if (!_configuration.DontReviewSettings)
            {
                var lines = new[]
                {
                    "Please review the following settings:",
                    $"Project:                   {_configuration.OldProjectName}",
                    $"found at:                  {oldProjectPath}",
                    $"Rename to:                 {newFileName}",
                    $"at:                        {newProjectPath}",
                    $"VS Solution folder:        {solutionFolderPath ?? "none"}",
                    $"exclude:                   {_configuration.ExcludedDirectory}",
                    $"Paket in use:              {isPaketUsed.AsText()}",
                    $"Run paket install:         {(!_configuration.DontRunPaketInstall).AsText()}",
                    $"Run build after rename:    {_configuration.DoRunBuild.AsText()}",
                    $"Create automatic commit:   {(!_configuration.DontCreateCommit).AsText()}",
                    $"Git version:               {gitVersion}",
                    "-----------------------------------------------",
                    "Do you want to continue with the rename operation?"
                };
                if (!_input.AskUser(string.Join(Environment.NewLine, lines)))
                {
                    _runtime.Abort();
                }
            }

            var(dependents, dependencies) = analyzeReferences();
            removeFromSolution();
            removeOldReferences();
            gitMove();
            updatePaketReference();
            addNewReferences();
            addToSolution();
            updatePaket();
            _git.StageAllChanges();
            build();
            commit();

            void addNewReferences()
            {
                dependents.ForEach(p => _dotnet.AddReference(p, newProjectPath));
                dependencies.ForEach(d => _dotnet.AddReference(newProjectPath, d));
            }

            void removeOldReferences()
            {
                dependents.ForEach(p => _dotnet.RemoveReference(p, oldProjectPath));
                dependencies.ForEach(d => _dotnet.RemoveReference(oldProjectPath, d));
            }

            (string[] dependents, string[] dependencies) analyzeReferences()
            {
                _logger.Info(
                    "Analyzing references in your projects - depending on the number of projects this can take a bit...");

                return(
                    allProjects().Where(doesNotEqualOldProjectPath).Where(hasReferenceToOldProject).ToArray(),
                    getReferencedProjects(oldProjectPath).ToArray());

                bool hasReferenceToOldProject(string p) =>
                getReferencedProjects(p).Any(doesEqualOldProjectPath);
            }

            bool doesNotEqualOldProjectPath(string what) => !doesEqualOldProjectPath(what);
            bool doesEqualOldProjectPath(string what) => arePathsEqual(what, oldProjectPath);

            IEnumerable <string> getReferencedProjects(string project)
            {
                var relativeReferences = _dotnet.GetReferencedProjects(project).Select(p => p = Path.Combine(p.Split('\\')));
                var baseDirectory      = Path.GetFullPath(Path.GetDirectoryName(project));

                return(relativeReferences.Select(r => r.ToAbsolutePath(baseDirectory)));
            }

            bool arePathsEqual(string lhs, string rhs) => Path.GetFullPath(lhs) == Path.GetFullPath(rhs);

            void commit()
            {
                if (!_configuration.DontCreateCommit)
                {
                    var wasMove = _configuration.NewProjectName.Any(CommonExtensions.IsDirectorySeparator);
                    var msg     = wasMove
                        ? $"Moved {oldProjectPath.ToRelativePath(CurrentDirectoryAbsolute)} to {newProjectPath.ToRelativePath(CurrentDirectoryAbsolute)}"
                        : $"Renamed {_configuration.OldProjectName} to {_configuration.NewProjectName}";
                    _git.Commit(msg);
                }
            }

            void build()
            {
                if (_configuration.DoRunBuild)
                {
                    _dotnet.BuildSolution(() =>
                    {
                        if (_input.AskUser(
                                "dotnet build returned an error or warning - do you want to rollback all changes?")
                            )
                        {
                            _git.RollbackAllChanges();
                            _runtime.Abort();
                        }
                    });
                }
            }

            void updatePaket()
            {
                if (isPaketUsed && !_configuration.DontRunPaketInstall)
                {
                    _dotnet.PaketInstall();
                }
            }

            void updatePaketReference()
            {
                if (!isPaketUsed)
                {
                    return;
                }
                const string restoreTargets = @"\.paket\Paket.Restore.targets";
                var          nesting        = Path.GetFullPath(newProjectPath).Count(CommonExtensions.IsDirectorySeparator) -
                                              CurrentDirectoryAbsolute.Count(CommonExtensions.IsDirectorySeparator) - 1;
                var paketPath = @"..\".Repeat(nesting)[..^ 1] + restoreTargets;