예제 #1
0
 public async Task PushNotesAsync(CommitSha rootId)
 {
     //await PushNotesAsync(CommitBranchNoteNameSpace, rootId);
     await PushNotesAsync(ManualBranchNoteNameSpace, rootId);
 }
예제 #2
0
 public void SetCurrentMerging(Branch branch, CommitSha commitSha)
 {
     MergingBranch    = branch;
     MergingCommitSha = commitSha;
 }
예제 #3
0
 public Task <IReadOnlyList <CommitBranchName> > GetEditedBranchNamesAsync(CommitSha rootSha)
 {
     return(GetNoteBranchesAsync(ManualBranchNoteNameSpace, rootSha));
 }
예제 #4
0
 public Task <IReadOnlyList <CommitBranchName> > GetCommitBranchNamesAsync(CommitSha rootId)
 {
     return(Task.FromResult(Enumerable.Empty <CommitBranchName>().ToReadOnlyList()));
     //return GetNoteBranchesAsync(CommitBranchNoteNameSpace, rootId);
 }
예제 #5
0
 public Task PushNotesAsync(CommitSha rootId)
 {
     return(gitCommitBranchNameService.PushNotesAsync(rootId));
 }
예제 #6
0
 public Task SetCommitBranchNameAsync(CommitSha commitSha, BranchName branchName)
 {
     //SetNoteBranches(CommitBranchNoteNameSpace, commitSha, branchName);
     return(Task.CompletedTask);
 }
예제 #7
0
 public void SetCurrentMerging(Branch branch, CommitSha commitSha) => viewModel.SetCurrentMerging(branch, commitSha);
예제 #8
0
 public Task <CommitDiff> ParsePatchAsync(CommitSha commitSha, string patch, bool addPrefixes = true) =>
 am.Resolve <IGitDiffParser>().ParseAsync(commitSha, patch, addPrefixes, false);
예제 #9
0
        private async Task <bool> ExecuteAsync()
        {
            try
            {
                if (CommitSha.Length < ShaUsableLength)
                {
                    Log.LogError($"The CommitSHA should be at least {ShaUsableLength} characters long: CommitSha is '{CommitSha}'. Aborting feed creation.");
                    return(false);
                }

                JsonSerializerSettings _serializerSettings = new JsonSerializerSettings
                {
                    ContractResolver  = new CamelCasePropertyNamesContractResolver(),
                    NullValueHandling = NullValueHandling.Ignore
                };

                // GitHub repos may appear in the repository name with an 'org/repo' form.
                // When creating a repo, Github aslready replaces all of the characters invalid in AzDO feed names (see below)
                // with '-' in the repo name. We just need to replace '/' with '-' to deal with the org/repo input.
                // From the AzDO docs:
                // The feed name can't contain spaces, start with a '.' or '_', end with a '.',
                // or contain any of these: @ ~ ; { } ' + = , < > | / \ ? : & $ * " # [ ] %
                string feedCompatibleRepositoryName = RepositoryName.Replace('/', '-');

                string accessType        = IsInternal ? "internal" : "public";
                string publicSegment     = IsInternal ? string.Empty : "public/";
                string accessId          = IsInternal ? "int" : "pub";
                string extraContentInfo  = !string.IsNullOrEmpty(ContentIdentifier) ? $"-{ContentIdentifier}" : "";
                string baseFeedName      = $"darc-{accessId}{extraContentInfo}-{feedCompatibleRepositoryName}-{CommitSha.Substring(0, ShaUsableLength)}";
                string versionedFeedName = baseFeedName;
                bool   needsUniqueName   = false;
                int    subVersion        = 0;

                Log.LogMessage(MessageImportance.High, $"Creating the new {accessType} Azure DevOps artifacts feed '{baseFeedName}'...");

                if (baseFeedName.Length > MaxLengthForAzDoFeedNames)
                {
                    Log.LogError($"The name of the new feed ({baseFeedName}) exceeds the maximum feed name size of 64 chars. Aborting feed creation.");
                    return(false);
                }

                do
                {
                    using (HttpClient client = new HttpClient(new HttpClientHandler {
                        CheckCertificateRevocationList = true
                    })
                    {
                        BaseAddress = new Uri(AzureDevOpsFeedsBaseUrl)
                    })
                    {
                        client.DefaultRequestHeaders.Add(
                            "Accept",
                            $"application/json;api-version={AzureDevOpsFeedsApiVersion}");
                        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
                            "Basic",
                            Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Format("{0}:{1}", "", AzureDevOpsPersonalAccessToken))));

                        AzureDevOpsArtifactFeed newFeed = new AzureDevOpsArtifactFeed(versionedFeedName);

                        string body = JsonConvert.SerializeObject(newFeed, _serializerSettings);

                        HttpRequestMessage postMessage = new HttpRequestMessage(HttpMethod.Post, $"{publicSegment}_apis/packaging/feeds");
                        postMessage.Content = new StringContent(body, Encoding.UTF8, "application/json");

                        HttpResponseMessage response = await client.SendAsync(postMessage);

                        if (response.StatusCode == HttpStatusCode.Created)
                        {
                            needsUniqueName = false;
                            baseFeedName    = versionedFeedName;
                        }
                        else if (response.StatusCode == HttpStatusCode.Conflict)
                        {
                            versionedFeedName = $"{baseFeedName}-{++subVersion}";
                            needsUniqueName   = true;

                            if (versionedFeedName.Length > MaxLengthForAzDoFeedNames)
                            {
                                Log.LogError($"The name of the new feed ({baseFeedName}) exceeds the maximum feed name size of 64 chars. Aborting feed creation.");
                                return(false);
                            }
                        }
                        else
                        {
                            throw new Exception($"Feed '{baseFeedName}' was not created. Request failed with status code {response.StatusCode}. Exception: {await response.Content.ReadAsStringAsync()}");
                        }
                    }
                } while (needsUniqueName);

                TargetFeedURL  = $"https://pkgs.dev.azure.com/{AzureDevOpsOrg}/{publicSegment}_packaging/{baseFeedName}/nuget/v3/index.json";
                TargetFeedName = baseFeedName;

                Log.LogMessage(MessageImportance.High, $"Feed '{TargetFeedURL}' created successfully!");
            }
            catch (Exception e)
            {
                Log.LogErrorFromException(e, true);
            }

            return(!Log.HasLoggedErrors);
        }
예제 #10
0
        private async Task <bool> ExecuteAsync()
        {
            try
            {
                if (CommitSha?.Length < ShaUsableLength)
                {
                    Log.LogError($"The CommitSHA should be at least {ShaUsableLength} characters long: CommitSha is '{CommitSha}'. Aborting feed creation.");
                    return(false);
                }

                JsonSerializerSettings _serializerSettings = new JsonSerializerSettings
                {
                    ContractResolver  = new CamelCasePropertyNamesContractResolver(),
                    NullValueHandling = NullValueHandling.Ignore
                };

                // GitHub repos may appear in the repository name with an 'org/repo' form.
                // When creating a repo, Github aslready replaces all of the characters invalid in AzDO feed names (see below)
                // with '-' in the repo name. We just need to replace '/' with '-' to deal with the org/repo input.
                // From the AzDO docs:
                // The feed name can't contain spaces, start with a '.' or '_', end with a '.',
                // or contain any of these: @ ~ ; { } ' + = , < > | / \ ? : & $ * " # [ ] %
                string feedCompatibleRepositoryName = RepositoryName?.Replace('/', '-');

                // For clarity, and compatibility with existing infrastructure, we include the feed visibility tag.
                // This serves two purposes:
                // 1. In nuget.config files (and elsewhere), the name at a glance can identify its visibility
                // 2. Existing automation has knowledge of "darc-int" and "darc-pub" for purposes of injecting authentication for internal builds
                //    and managing the isolated feeds within the NuGet.config files.
                string extraContentInfo  = !string.IsNullOrEmpty(ContentIdentifier) ? $"-{ContentIdentifier}" : "";
                string baseFeedName      = FeedName ?? $"darc-{GetFeedVisibilityTag(AzureDevOpsOrg, AzureDevOpsProject)}{extraContentInfo}-{feedCompatibleRepositoryName}-{CommitSha.Substring(0, ShaUsableLength)}";
                string versionedFeedName = baseFeedName;
                bool   needsUniqueName   = false;
                int    subVersion        = 0;

                Log.LogMessage(MessageImportance.High, $"Creating the new Azure DevOps artifacts feed '{baseFeedName}'...");

                if (baseFeedName.Length > MaxLengthForAzDoFeedNames)
                {
                    Log.LogError($"The name of the new feed ({baseFeedName}) exceeds the maximum feed name size of 64 chars. Aborting feed creation.");
                    return(false);
                }

                string azureDevOpsFeedsBaseUrl = $"https://feeds.dev.azure.com/{AzureDevOpsOrg}/";
                do
                {
                    using (HttpClient client = new HttpClient(new HttpClientHandler {
                        CheckCertificateRevocationList = true
                    })
                    {
                        BaseAddress = new Uri(azureDevOpsFeedsBaseUrl)
                    })
                    {
                        client.DefaultRequestHeaders.Add(
                            "Accept",
                            $"application/json;api-version={AzureDevOpsFeedsApiVersion}");
                        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
                            "Basic",
                            Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Format("{0}:{1}", "", AzureDevOpsPersonalAccessToken))));

                        AzureDevOpsArtifactFeed newFeed = new AzureDevOpsArtifactFeed(versionedFeedName, AzureDevOpsOrg, AzureDevOpsProject);

                        string createBody = JsonConvert.SerializeObject(newFeed, _serializerSettings);

                        using HttpRequestMessage createFeedMessage = new HttpRequestMessage(HttpMethod.Post, $"{AzureDevOpsProject}/_apis/packaging/feeds");
                        createFeedMessage.Content = new StringContent(createBody, Encoding.UTF8, "application/json");
                        using HttpResponseMessage createFeedResponse = await client.SendAsync(createFeedMessage);

                        if (createFeedResponse.StatusCode == HttpStatusCode.Created)
                        {
                            needsUniqueName = false;
                            baseFeedName    = versionedFeedName;

                            /// This is where we would potentially update the Local feed view with permissions to the organization's
                            /// valid users. But, see <seealso cref="AzureDevOpsArtifactFeed"/> for more info on why this is not
                            /// done this way.
                        }
                        else if (createFeedResponse.StatusCode == HttpStatusCode.Conflict)
                        {
                            versionedFeedName = $"{baseFeedName}-{++subVersion}";
                            needsUniqueName   = true;

                            if (versionedFeedName.Length > MaxLengthForAzDoFeedNames)
                            {
                                Log.LogError($"The name of the new feed ({baseFeedName}) exceeds the maximum feed name size of 64 chars. Aborting feed creation.");
                                return(false);
                            }
                        }
                        else
                        {
                            throw new Exception($"Feed '{baseFeedName}' was not created. Request failed with status code {createFeedResponse.StatusCode}. Exception: {await createFeedResponse.Content.ReadAsStringAsync()}");
                        }
                    }
                } while (needsUniqueName);

                TargetFeedURL  = $"https://pkgs.dev.azure.com/{AzureDevOpsOrg}/{AzureDevOpsProject}/_packaging/{baseFeedName}/nuget/v3/index.json";
                TargetFeedName = baseFeedName;

                Log.LogMessage(MessageImportance.High, $"Feed '{TargetFeedURL}' created successfully!");
            }
            catch (Exception e)
            {
                Log.LogErrorFromException(e, true);
            }

            return(!Log.HasLoggedErrors);
        }
예제 #11
0
        public void AddBranchCommits(IReadOnlyList <GitBranch> branches, MRepository repository)
        {
            GitStatus status = repository.Status;

            Timing t = new Timing();
            IEnumerable <CommitSha> rootCommits = branches.Select(b => b.TipSha);

            if (branches.TryGetCurrent(out GitBranch current) && current.IsDetached)
            {
                rootCommits = rootCommits.Concat(new[] { current.TipSha });
            }

            if (!rootCommits.Any())
            {
                AddVirtualEmptyCommit(repository);
                rootCommits = new[] { CommitSha.NoCommits };
            }

            rootCommits = rootCommits.ToList();
            t.Log("Root commit ids");


            Dictionary <CommitSha, object> added = new Dictionary <CommitSha, object>();

            Dictionary <CommitId, BranchName> branchNameByCommitId        = new Dictionary <CommitId, BranchName>();
            Dictionary <CommitId, BranchName> subjectBranchNameByCommitId = new Dictionary <CommitId, BranchName>();

            Stack <CommitSha> commitShas = new Stack <CommitSha>();

            rootCommits.ForEach(sha => commitShas.Push(sha));
            rootCommits.ForEach(sha => added[sha] = null);
            t.Log("Pushed roots on stack");

            while (commitShas.Any())
            {
                CommitSha commitSha = commitShas.Pop();
                CommitId  commitId  = new CommitId(commitSha.Sha);

                GitCommit gitCommit;
                IEnumerable <CommitSha> parentIds = null;
                if (!repository.GitCommits.TryGetValue(commitId, out gitCommit))
                {
                    Log.Warn($"Unknown commit {commitSha}");
                    continue;
                }

                if (IsMergeCommit(gitCommit))
                {
                    TrySetBranchNameFromSubject(commitId, gitCommit, branchNameByCommitId, subjectBranchNameByCommitId);
                }

                MCommit commit = repository.Commit(commitId);
                if (!commit.IsSet)
                {
                    if (commit.Id == CommitId.NoCommits)
                    {
                        commit.IsVirtual = true;
                        commit.SetBranchName("master");
                    }

                    AddCommit(commit, gitCommit);

                    if (parentIds == null)
                    {
                        parentIds = gitCommit.ParentIds.Select(id => repository.GitCommits[id].Sha);
                    }

                    AddParents(parentIds, commitShas, added);
                }

                BranchName branchName;
                if (branchNameByCommitId.TryGetValue(commitId, out branchName))
                {
                    // Branch name set by a child commit (pull merge commit)
                    commit.SetBranchName(branchName);
                }

                BranchName subjectBranchName;
                if (subjectBranchNameByCommitId.TryGetValue(commitId, out subjectBranchName))
                {
                    // Subject branch name set by a child commit (merge commit)
                    gitCommit.SetBranchNameFromSubject(subjectBranchName);
                }
            }

            if (!status.OK)
            {
                // Adding a virtual "uncommitted" commit since current working folder status has changes
                AddVirtualUncommitted(current, status, repository);
            }
        }
        private static IReadOnlyDictionary <CommitSha, string> GetSingleBranchTipCommits(
            Repository repository,
            IReadOnlyList <GitBranch> branches)
        {
            Dictionary <CommitSha, GitBranch> branchByTip = new Dictionary <CommitSha, GitBranch>();

            foreach (GitBranch branch in branches)
            {
                try
                {
                    CommitSha commitSha = branch.TipSha;
                    CommitId  commitId  = new CommitId(commitSha);

                    // Check if commit has any children (i.e. is not sole branch tip)
                    if (repository.Commits.TryGetValue(commitId, out Commit commit) && !commit.Children.Any())
                    {
                        if (!branchByTip.TryGetValue(commitSha, out GitBranch existingBranch))
                        {
                            // No existing branch has yet a tip to this commit
                            branchByTip[commitSha] = branch;
                        }
                        else
                        {
                            try
                            {
                                // Some other branch points to this tip, lets check if it is remote/local pair
                                if (existingBranch != null)
                                {
                                    try
                                    {
                                        if (!AreLocalRemotePair(branch, existingBranch) &&
                                            !AreLocalRemotePair(existingBranch, branch))
                                        {
                                            // Multiple branches point to same commit, set to null to disable this commit id
                                            branchByTip[commitSha] = null;
                                            Log.Debug($"Multiple branches {commit}, {branch.Name} != {existingBranch.Name}");
                                        }
                                    }
                                    catch (Exception e)
                                    {
                                        Log.Exception(e, $"Failed for {branch}");
                                        throw;
                                    }
                                }
                                else
                                {
                                    Log.Warn($"Multiple branch {commit}, {branch.Name}");
                                }
                            }
                            catch (Exception e)
                            {
                                Log.Exception(e, $"Failed for {branch}");
                                throw;
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    Log.Exception(e, $"Failed for {branch}");
                    throw;
                }
            }

            return(branchByTip
                   .Where(pair => pair.Value != null)
                   .Select(pair => new { pair.Key, pair.Value.Name })
                   .ToDictionary(p => p.Key, p => p.Name));
        }
예제 #13
0
 public void ShowDiff(CommitSha uncommittedId)
 {
     Task.Run(() => ShowDiffAsync(CommitSha.Uncommitted).Wait())
     .Wait();
 }
예제 #14
0
 public Task <IReadOnlyList <CommitBranchName> > GetCommitBranchNamesAsync(CommitSha rootId)
 {
     return(GetNoteBranchesAsync(CommitBranchNoteNameSpace, rootId));
 }
 public Task SetSpecifiedCommitBranchAsync(
     CommitSha commitSha, CommitSha rootSha, BranchName branchName)
 {
     return(gitCommitBranchNameService.EditCommitBranchNameAsync(commitSha, rootSha, branchName));
 }