Пример #1
0
        public string ResolveFullClonePath(IFromGit gitCfg, string?rootPathOverride = null)
        {
            if (gitCfg == null)
            {
                throw new ArgumentNullException(nameof(gitCfg));
            }
            if (gitCfg.SshRepoUrl == null)
            {
                throw new NullReferenceException(nameof(gitCfg.SshRepoUrl));
            }

            var chunks = gitCfg.SshRepoUrl.Split(":");

            if (chunks.Length != 2)
            {
                throw new InvalidOperationException(
                          $"Git Ssh Url is expected to be split by a colon into two parts. {gitCfg.SshRepoUrl}");
            }

            var pathChunks = new List <string> {
                rootPathOverride ?? _ringCfg.GitCloneRootPath
            };
            var inRepoPath = chunks[1].Replace(".git", "").Split("/");

            pathChunks.AddRange(inRepoPath);
            var targetPath = Environment.ExpandEnvironmentVariables(Path.Combine(pathChunks.ToArray()));

            return(Path.IsPathRooted(targetPath) ? targetPath : Path.GetFullPath(targetPath));
        }
Пример #2
0
        public async Task <ExecutionInfo> CloneOrPullAsync(IFromGit gitCfg, CancellationToken token, bool shallow = false, bool defaultBranchOnly = false, string?rootPathOverride = null)
        {
            using var _ = Logger.WithScope(gitCfg.SshRepoUrl, Phase.GIT);
            var depthArg        = shallow ? "--depth=1" : "";
            var singleBranchArg = defaultBranchOnly ? "--single-branch" : "";
            var cloneFullPath   = ResolveFullClonePath(gitCfg, rootPathOverride);

            async Task <ExecutionInfo> CloneAsync()
            {
                Logger.LogDebug("Cloning to {OutputPath}", cloneFullPath);

                return(await this.TryAsync(3, TimeSpan.FromSeconds(10),
                                           async t =>
                {
                    var result = await t.RunProcessWaitAsync(new object[] { "clone", singleBranchArg, depthArg, "--", gitCfg.SshRepoUrl, cloneFullPath }, token);
                    Logger.LogInformation(result.IsSuccess ? PhaseStatus.OK : PhaseStatus.FAILED);
                    return result;
                }, token));
            }

            if (!Directory.Exists(cloneFullPath))
            {
                return(await CloneAsync());
            }

            var output = await this.RunProcessWaitAsync(new object[] { "-C", cloneFullPath, "status" }, token);

            if (output.IsSuccess)
            {
                Logger.LogInformation("Pulling at {OutputPath}", cloneFullPath);
                return(await this.TryAsync(3, TimeSpan.FromSeconds(10),
                                           async t =>
                {
                    var result = await t.RunProcessWaitAsync(new object[] { "-C", cloneFullPath, "pull", depthArg }, token);
                    Logger.LogInformation(result.IsSuccess ? PhaseStatus.OK : PhaseStatus.FAILED);
                    return result;
                }, token));
            }

            var tryLeft = 3;

            while (Directory.Exists(cloneFullPath) && tryLeft > 0)
            {
                try
                {
                    Logger.LogInformation("Deleting an invalid clone at {OutputPath}", cloneFullPath);
                    SafeDelete(cloneFullPath);
                    break;
                }
                catch (Exception ex)
                {
                    Logger.LogError(ex, "Could not delete {CloneFullPath}", cloneFullPath);
                    await Task.Delay(TimeSpan.FromSeconds(10), token);

                    tryLeft--;
                }
            }
            return(await CloneAsync());
        }