/// <summary>
        /// Traverses all dependencies beginning in the given directory.
        /// </summary>
        /// <param name="visitor">The <see cref="IVisitor"/> that should be called at each dependency and project visit.</param>
        /// <param name="directory">The directory containing a GitDepend.json file.</param>
        public void TraverseDependencies(IVisitor visitor, string directory)
        {
            // Make sure we are working with something here.
            if (visitor == null || string.IsNullOrEmpty(directory))
            {
                return;
            }

            directory = _fileSystem.Path.GetFullPath(directory);

            // If the directory doesn't exist we are done.
            if (!_fileSystem.Directory.Exists(directory))
            {
                visitor.ReturnCode = ReturnCode.GitRepositoryNotFound;
                return;
            }

            string     dir;
            ReturnCode code;
            var        config = _factory.LoadFromDirectory(directory, out dir, out code);

            if (code != ReturnCode.Success)
            {
                visitor.ReturnCode = code;
                return;
            }

            foreach (var dependency in config.Dependencies)
            {
                dependency.Directory = _fileSystem.Path.GetFullPath(_fileSystem.Path.Combine(dir, dependency.Directory));

                // If the dependency does not exist on disk we need to clone it.
                if (!_fileSystem.Directory.Exists(dependency.Directory))
                {
                    _console.WriteLine($"Cloning {dependency.Name} into {dependency.Directory}");

                    code = _git.Clone(dependency.Url, dependency.Directory, dependency.Branch);
                    _console.WriteLine();

                    // If something went wrong with git we are done.
                    if (code != ReturnCode.Success)
                    {
                        visitor.ReturnCode = code;
                        return;
                    }
                }

                // Visit all dependencies of this dependency.
                TraverseDependencies(visitor, dependency.Directory);

                // If something went wrong with a dependency we are done.
                if (visitor.ReturnCode != ReturnCode.Success)
                {
                    return;
                }

                // Make sure to only visit dependencies once.
                if (!_visitedDependencies.Contains(dependency.Directory))
                {
                    _visitedDependencies.Add(dependency.Directory);

                    // Visit the dependency.
                    code = visitor.VisitDependency(dir, dependency);

                    // If something went wrong visiting the dependency we are done.
                    if (code != ReturnCode.Success)
                    {
                        visitor.ReturnCode = code;
                        return;
                    }
                }
            }

            // Make sure to only visit projects once.
            if (!_visitedProjects.Contains(dir))
            {
                _visitedProjects.Add(dir);

                // Visit the project.
                code = visitor.VisitProject(dir, config);
                _console.WriteLine();

                // If something went wrong visiting the project we are done.
                if (code != ReturnCode.Success)
                {
                    visitor.ReturnCode = code;
                }
            }
        }
예제 #2
0
        // throws ProcessException
        public void Process()
        {
            try
            {
                var      srcRepo = git.OpenGitRepo(srcRepoPath);
                IGitRepo intermediateRepo;

                var intermediateRepoPath = config.GetIntermediateRepoPath(srcRepoPath);

                // 이미 리포지토리가 있으면 더 이상 진행하지 않는다
                if (intermediateRepoPath == null)
                {
                    intermediateRepoPath = MakeNewIntermidateRepoPath(srcRepoPath);

                    // 클론 시켜서 임시저장소를 하나 더 만든다
                    git.Clone(srcRepoPath, intermediateRepoPath);

                    config.AddIntermediateRepo(srcRepoPath, intermediateRepoPath);
                    intermediateRepo = git.OpenGitRepo(intermediateRepoPath);
                }
                else
                {
                    intermediateRepo = git.OpenGitRepo(intermediateRepoPath);
                }

                //
                var branchName = srcRepo.GetCurrentBranchName();

                // branchName에 auto자가 붙으면 저장하지 않는다
                if (branchName.StartsWith("autosave/"))
                {
                    throw new ProcessException(ProcessException.Reason.WorkingOnAutosaveBranch);
                }

                intermediateRepo.FetchBranch("origin", branchName);

                var autosaveBranchName = $"autosave/{branchName}";

                if (intermediateRepo.BranchExists(autosaveBranchName))
                {
                    // git checkout autosave/master
                    intermediateRepo.CheckoutBranch(autosaveBranchName);
                }
                else
                {
                    // git checkout -b autosave/master --track origin/master
                    intermediateRepo.CheckoutNewBranchTrackingOriginBranch(autosaveBranchName, branchName);
                }

                intermediateRepo.MergeOurs("origin", branchName);
                intermediateRepo.ReadTree("origin", branchName);

                MirrorWorkingTree(srcRepo, srcRepoPath, intermediateRepoPath, true);

                intermediateRepo.AddAll();

                // DateTime.
                intermediateRepo.Commit($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} {branchName}");
                intermediateRepo.PushBranch("origin", autosaveBranchName);
            }
            catch (GitCloneException)
            {
                throw new ProcessException(ProcessException.Reason.CloneFailed);
            }
            catch
            {
                throw new UnreachableCodeException();
            }
        }