private static CommitRow CreateCommitRow(TeamFoundationRequestContext requestContext, TeamFoundationGitCommitService commitService, TfsGitRepository repository, TfsGitCommit gitCommit, CommitRowType rowType, PushNotification pushNotification, Dictionary <Sha1Id, List <GitRef> > refLookup) { var commitManifest = commitService.GetCommitManifest(requestContext, repository, gitCommit.ObjectId); string repoUri = repository.GetRepositoryUri(requestContext); var commitRow = new CommitRow() { CommitId = gitCommit.ObjectId, Type = rowType, CommitUri = repoUri + "/commit/" + gitCommit.ObjectId.ToHexString(), AuthorTime = gitCommit.GetLocalAuthorTime(requestContext), Author = gitCommit.GetAuthor(requestContext), AuthorName = gitCommit.GetAuthorName(requestContext), AuthorEmail = gitCommit.GetAuthorEmail(requestContext), Comment = gitCommit.GetComment(requestContext), ChangeCounts = commitManifest.ChangeCounts }; List <GitRef> refs; refLookup.TryGetValue(gitCommit.ObjectId, out refs); commitRow.Refs = refs; return(commitRow); }
protected override IEnumerable <Notifications.INotification> CreateNotifications(TeamFoundationRequestContext requestContext, RepositoryCreatedNotification ev, int maxLines) { var repositoryService = requestContext.GetService <TeamFoundationGitRepositoryService>(); var identityService = requestContext.GetService <ITeamFoundationIdentityService>(); var commonService = requestContext.GetService <CommonStructureService>(); var identity = identityService.ReadIdentity(requestContext, IdentitySearchFactor.Identifier, ev.Creator.Identifier); using (TfsGitRepository repository = repositoryService.FindRepositoryById(requestContext, ev.RepositoryId)) { string repoUri = repository.GetRepositoryUri(requestContext); var notification = new Notifications.RepositoryCreatedNotification() { TeamProjectCollection = requestContext.ServiceHost.Name, UniqueName = identity.UniqueName, DisplayName = identity.DisplayName, ProjectName = commonService.GetProject(requestContext, ev.TeamProjectUri).Name, RepoUri = repoUri, RepoName = ev.RepositoryName, TeamNames = GetUserTeamsByProjectUri(requestContext, ev.TeamProjectUri, identity.Descriptor) }; yield return(notification); } }
internal static void LogRequest(TeamFoundationRequestContext requestContext, PushNotification pushNotification, TfsGitRepository repository) { if (!PluginConfiguration.Instance.HasLog) return; var lines = new List<string>(); lines.Add(string.Format("Request from {0} for {1}" , requestContext.GetNameToDisplay() , requestContext.ServiceName )); lines.Add("Summary for " + requestContext.GetSummary()); lines.Add(string.Format("{6} #{0} on {1} repo {2} at {3} by {5} ({4})" , pushNotification.PushId , pushNotification.TeamProjectUri , pushNotification.RepositoryName , pushNotification.PushTime , pushNotification.AuthenticatedUserName , pushNotification.Pusher , requestContext.Method.Name )); lines.Add("- Included Commits:"); foreach (var commitHash in pushNotification.IncludedCommits) { var commit = repository.TryLookupObject(requestContext, commitHash) as TfsGitCommit; lines.Add(string.Format(" Commit {0}: {1} '{2}'" , commit.ObjectId.DisplayHash() , commit.GetCommitterName(requestContext) , commit.GetComment(requestContext) )); foreach (var parentCommit in commit.GetParents(requestContext)) { lines.Add(string.Format(" Parent {0}: {1} '{2}'" , parentCommit.ObjectId.DisplayHash() , parentCommit.GetCommitterName(requestContext) , parentCommit.GetComment(requestContext) )); } } lines.Add("- Ref Update Results:"); foreach (var refUpdate in pushNotification.RefUpdateResults) { lines.Add(string.Format(" on {0} {1}..{2} is {3} (succeeded: {4}) rejecter '{5}' message '{6}'" , refUpdate.Name , refUpdate.NewObjectId.DisplayHash() , refUpdate.OldObjectId.DisplayHash() , refUpdate.Status , refUpdate.Succeeded , refUpdate.RejectedBy , refUpdate.CustomMessage )); }//for File.AppendAllLines(PluginConfiguration.Instance.LogFile, lines); }
public List<Validation> CheckRules(TeamFoundationRequestContext requestContext, PushNotification pushNotification, TfsGitRepository repository) { var res = new List<Validation>(); foreach (var rule in this.Rules) { res.Add(rule.CheckRule(requestContext, pushNotification, repository)); }//for return res; }
public override Validation CheckRule(TeamFoundationRequestContext requestContext, PushNotification pushNotification, TfsGitRepository repository) { var result = new Validation(); // refuse any push result.Fails = true; result.ReasonCode = 99; result.ReasonMessage = string.Format( "Repository '{0}' is in read-only mode", pushNotification.RepositoryName); return result; }
public static bool IsForceRequired(this PushNotification pushNotification, TeamFoundationRequestContext requestContext, TfsGitRepository repository) { foreach (var refUpdateResult in pushNotification.RefUpdateResults.Where(r => r.Succeeded)) { // Don't bother with new or deleted refs if (refUpdateResult.OldObjectId.IsZero() || refUpdateResult.NewObjectId.IsZero()) continue; TfsGitObject gitObject = repository.LookupObject(requestContext, refUpdateResult.NewObjectId); if (gitObject.ObjectType != TfsGitObjectType.Commit) continue; TfsGitCommit gitCommit = (TfsGitCommit)gitObject; if (!gitCommit.IsDescendantOf(requestContext, refUpdateResult.OldObjectId)) return true; } return false; }
public override Validation CheckRule(TeamFoundationRequestContext requestContext, PushNotification pushNotification, TfsGitRepository repository) { var result = new Validation(); long totalSize = 0; foreach (var commitId in pushNotification.IncludedCommits) { TfsGitCommit gitCommit = repository.LookupObject(requestContext, commitId) as TfsGitCommit; if (gitCommit == null) continue; long size = GetCommitSize(gitCommit, requestContext); totalSize += size; }//for // convert to MB totalSize = totalSize / (1024 * 1024); if (totalSize < this.Megabytes) { Logger.Log(string.Format( "Push request is {0} MB, below the {1} MB limit." , totalSize, this.Megabytes , "Limit Size")); } else { if (IsUserExempted(requestContext, pushNotification)) { Logger.Log(string.Format( "Push request is {0} MB, above or equal to the {1} MB limit, but user is exempted." , totalSize, this.Megabytes , "Limit Size")); } else { result.Fails = true; result.ReasonCode = 2; result.ReasonMessage = string.Format( "Push request is {0} MB, above or equal to the {1} MB limit: refused." , totalSize, this.Megabytes); } }//if return result; }
protected override IEnumerable <Notifications.INotification> CreateNotifications(TeamFoundationRequestContext requestContext, ReviewerVoteNotification ev, int maxLines) { var repositoryService = requestContext.GetService <TeamFoundationGitRepositoryService>(); var identityService = requestContext.GetService <ITeamFoundationIdentityService>(); var commonService = requestContext.GetService <ICommonStructureService>(); var identity = identityService.ReadIdentity(requestContext, IdentitySearchFactor.Identifier, ev.Reviewer.Identifier); using (TfsGitRepository repository = repositoryService.FindRepositoryById(requestContext, ev.RepositoryId)) { var pullRequestService = requestContext.GetService <ITeamFoundationGitPullRequestService>(); TfsGitPullRequest pullRequest; if (pullRequestService.TryGetPullRequestDetails(requestContext, repository, ev.PullRequestId, out pullRequest)) { string repoUri = repository.GetRepositoryUri(requestContext); var creator = identityService.ReadIdentities(requestContext, new[] { pullRequest.Creator }).First(); var reviewers = identityService.ReadIdentities(requestContext, pullRequest.Reviewers.Select(r => r.Reviewer).ToArray()); var notification = new Notifications.PullRequestReviewerVoteNotification() { TeamProjectCollection = requestContext.ServiceHost.Name, CreatorUserName = creator.UniqueName, Vote = ev.ReviewerVote, UniqueName = identity.UniqueName, DisplayName = identity.DisplayName, ProjectName = commonService.GetProject(requestContext, ev.TeamProjectUri).Name, RepoUri = repoUri, RepoName = ev.RepositoryName, PrId = pullRequest.PullRequestId, PrUrl = string.Format("{0}/pullrequest/{1}#view=discussion", repoUri, ev.PullRequestId), PrTitle = pullRequest.Title, TeamNames = GetUserTeamsByProjectUri(requestContext, ev.TeamProjectUri, ev.Reviewer), SourceBranch = new Notifications.GitRef(pullRequest.SourceBranchName), TargetBranch = new Notifications.GitRef(pullRequest.TargetBranchName), ReviewerUserNames = reviewers.Select(r => r.UniqueName) }; yield return(notification); } else { throw new TfsNotificationRelayException("Unable to get pull request " + ev.PullRequestId); } } }
public override Validation CheckRule(TeamFoundationRequestContext requestContext, PushNotification pushNotification, TfsGitRepository repository) { var result = new Validation(); foreach (var refUpdateResult in pushNotification.RefUpdateResults) { // new or deleted refs have id==0 if (IsNullHash(refUpdateResult.OldObjectId) || IsNullHash(refUpdateResult.NewObjectId)) continue; TfsGitCommit gitCommit = repository.LookupObject(requestContext, refUpdateResult.NewObjectId) as TfsGitCommit; if (gitCommit == null) continue; string authorEmail = gitCommit.GetAuthorEmail(requestContext); if (!AuthorEmail.Any(pattern => Regex.IsMatch(authorEmail, pattern))) { result.Fails = true; result.ReasonCode = 2; result.ReasonMessage = string.Format( "Author email '{0}' on commit {1} is not admitted", authorEmail, gitCommit.ObjectId.DisplayHash()); break; } string committerEmail = gitCommit.GetCommitterEmail(requestContext); if (!CommitterEmail.Any(pattern => Regex.IsMatch(committerEmail, pattern))) { result.Fails = true; result.ReasonCode = 3; result.ReasonMessage = string.Format( "Committer email '{0}' on commit {1} is not admitted", authorEmail, gitCommit.ObjectId.DisplayHash()); break; }//if }//for changes return result; }
protected override Notifications.INotification CreateNotification(TeamFoundationRequestContext requestContext, ReviewerVoteNotification ev, int maxLines) { var repositoryService = requestContext.GetService <TeamFoundationGitRepositoryService>(); var identityService = requestContext.GetService <ITeamFoundationIdentityService>(); var commonService = requestContext.GetService <ICommonStructureService>(); var identity = identityService.ReadIdentity(requestContext, IdentitySearchFactor.Identifier, ev.Reviewer.Identifier); using (TfsGitRepository repository = repositoryService.FindRepositoryById(requestContext, ev.RepositoryId)) { var pullRequestService = requestContext.GetService <ITeamFoundationGitPullRequestService>(); TfsGitPullRequest pullRequest; if (pullRequestService.TryGetPullRequestDetails(requestContext, repository, ev.PullRequestId, out pullRequest)) { string repoUri = repository.GetRepositoryUri(requestContext); var notification = new Notifications.PullRequestReviewerVoteNotification() { TeamProjectCollection = requestContext.ServiceHost.Name, Vote = ev.ReviewerVote, UniqueName = identity.UniqueName, DisplayName = identity.DisplayName, ProjectName = commonService.GetProject(requestContext, ev.TeamProjectUri).Name, RepoUri = repoUri, RepoName = ev.RepositoryName, PrId = pullRequest.PullRequestId, PrUrl = string.Format("{0}/pullrequest/{1}#view=discussion", repoUri, ev.PullRequestId), PrTitle = pullRequest.Title }; return(notification); } else { throw new TfsNotificationRelayException("Unable to get pull request " + ev.PullRequestId); } } }
protected bool RequiresForcePush(PushNotification pushNotification, TeamFoundationRequestContext requestContext, TfsGitRepository repository) { foreach (var refUpdateResult in pushNotification.RefUpdateResults) { // new or deleted refs have id==0 if (IsNullHash(refUpdateResult.OldObjectId) || IsNullHash(refUpdateResult.NewObjectId)) { continue; } TfsGitCommit gitCommit = repository.LookupObject(requestContext, refUpdateResult.NewObjectId) as TfsGitCommit; if (gitCommit == null) { continue; } if (!DescendsFrom(gitCommit, refUpdateResult.OldObjectId, requestContext)) { // aha! no common node return(true); } } return(false); }
public List <Validation> CheckRules(TeamFoundationRequestContext requestContext, PushNotification pushNotification, TfsGitRepository repository) { var res = new List <Validation>(); foreach (var rule in this.Rules) { res.Add(rule.CheckRule(requestContext, pushNotification, repository)); }//for return(res); }
protected override IEnumerable <INotification> CreateNotifications(TeamFoundationRequestContext requestContext, PushNotification pushNotification, int maxLines) { var repositoryService = requestContext.GetService <TeamFoundationGitRepositoryService>(); var commonService = requestContext.GetService <CommonStructureService>(); var commitService = requestContext.GetService <TeamFoundationGitCommitService>(); var identityService = requestContext.GetService <TeamFoundationIdentityService>(); var identity = identityService.ReadIdentity(requestContext, IdentitySearchFactor.Identifier, pushNotification.Pusher.Identifier); var teamNames = GetUserTeamsByProjectUri(requestContext, pushNotification.TeamProjectUri, pushNotification.Pusher); using (TfsGitRepository repository = repositoryService.FindRepositoryById(requestContext, pushNotification.RepositoryId)) { var pushRow = new PushRow() { UniqueName = pushNotification.AuthenticatedUserName, DisplayName = identity.DisplayName, RepoName = pushNotification.RepositoryName, RepoUri = repository.GetRepositoryUri(requestContext), ProjectName = commonService.GetProject(requestContext, pushNotification.TeamProjectUri).Name, IsForcePush = settings.IdentifyForcePush ? pushNotification.IsForceRequired(requestContext, repository) : false }; var notification = new GitPushNotification(requestContext.ServiceHost.Name, pushRow.ProjectName, pushRow.RepoName, teamNames); notification.Add(pushRow); notification.TotalLineCount++; var refNames = new Dictionary <byte[], List <string> >(new ByteArrayComparer()); var oldCommits = new HashSet <byte[]>(new ByteArrayComparer()); var unknowns = new List <RefUpdateResultGroup>(); // Associate refs (branch, lightweight and annotated tag) with corresponding commit var refUpdateResultGroups = pushNotification.RefUpdateResults .Where(r => r.Succeeded) .GroupBy(r => r.NewObjectId, (key, items) => new RefUpdateResultGroup(key, items), new ByteArrayComparer()); foreach (var refUpdateResultGroup in refUpdateResultGroups) { byte[] newObjectId = refUpdateResultGroup.NewObjectId; byte[] commitId = null; if (newObjectId.IsZero()) { commitId = newObjectId; } else { TfsGitObject gitObject = repository.LookupObject(requestContext, newObjectId); if (gitObject.ObjectType == TfsGitObjectType.Commit) { commitId = newObjectId; } else if (gitObject.ObjectType == TfsGitObjectType.Tag) { var tag = (TfsGitTag)gitObject; var commit = tag.TryResolveToCommit(requestContext); if (commit != null) { commitId = commit.ObjectId; } } } if (commitId != null) { List <string> names; if (!refNames.TryGetValue(commitId, out names)) { names = new List <string>(); refNames.Add(commitId, names); } names.AddRange(RefsToStrings(refUpdateResultGroup.RefUpdateResults)); if (commitId.IsZero() || !pushNotification.IncludedCommits.Any(r => r.SequenceEqual(commitId))) { oldCommits.Add(commitId); } } else { unknowns.Add(refUpdateResultGroup); } } notification.TotalLineCount += pushNotification.IncludedCommits.Count() + oldCommits.Count + unknowns.Count; // Add new commits with refs foreach (byte[] commitId in pushNotification.IncludedCommits.TakeWhile(c => notification.Count < maxLines)) { TfsGitCommit gitCommit = (TfsGitCommit)repository.LookupObject(requestContext, commitId); notification.Add(CreateCommitRow(requestContext, commitService, gitCommit, CommitRowType.Commit, pushNotification, refNames)); } // Add updated refs to old commits foreach (byte[] commitId in oldCommits.TakeWhile(c => notification.Count < maxLines)) { if (commitId.IsZero()) { notification.Add(new DeleteRow() { RefNames = refNames[commitId] }); } else { TfsGitCommit gitCommit = (TfsGitCommit)repository.LookupObject(requestContext, commitId); notification.Add(CreateCommitRow(requestContext, commitService, gitCommit, CommitRowType.RefUpdate, pushNotification, refNames)); } } // Add "unknown" refs foreach (var refUpdateResultGroup in unknowns.TakeWhile(c => notification.Count < maxLines)) { byte[] newObjectId = refUpdateResultGroup.NewObjectId; TfsGitObject gitObject = repository.LookupObject(requestContext, newObjectId); notification.Add(new RefUpdateRow() { NewObjectId = newObjectId, ObjectType = gitObject.ObjectType, RefNames = RefsToStrings(refUpdateResultGroup.RefUpdateResults) }); } yield return(notification); } }
protected override IEnumerable <INotification> CreateNotifications(TeamFoundationRequestContext requestContext, DiscussionsNotification args, int maxLines) { var locationService = requestContext.GetService <ILocationService>(); var linkingService = requestContext.GetService <TeamFoundationLinkingService>(); var hyperlinkService = requestContext.GetService <TswaServerHyperlinkService>(); var identityService = requestContext.GetService <ITeamFoundationIdentityService>(); var commonService = requestContext.GetService <ICommonStructureService>(); var discussionService = requestContext.GetService <ITeamFoundationDiscussionService>(); var notifications = new List <INotification>(); foreach (var thread in args.Threads) { if (thread.Comments == null) { continue; // e.g. when a comment is deleted } var artifactId = LinkingUtilities.DecodeUri(thread.ArtifactUri); int discussionId = thread.DiscussionId <= 0 ? thread.Comments[0].DiscussionId : thread.DiscussionId; if (artifactId.ArtifactType.Equals("Commit", StringComparison.OrdinalIgnoreCase)) { var repositoryService = requestContext.GetService <TeamFoundationGitRepositoryService>(); var commitService = requestContext.GetService <TeamFoundationGitCommitService>(); Guid projectGuid; Guid repositoryId; Sha1Id commitId; GitCommitArtifactId.Decode(artifactId, out projectGuid, out repositoryId, out commitId); using (TfsGitRepository repository = repositoryService.FindRepositoryById(requestContext, repositoryId)) { var project = commonService.GetProject(requestContext, projectGuid); var repoUri = repository.GetRepositoryUri(requestContext); var commitUri = repoUri + "/commit/" + commitId.ToHexString(); string itemPath; if (thread.Properties.TryGetValue <string>("Microsoft.TeamFoundation.Discussion.ItemPath", out itemPath)) { commitUri += string.Format("#path={0}&discussionId={1}&_a=contents", Uri.EscapeDataString(itemPath), discussionId); } var commitManifest = commitService.GetCommitManifest(requestContext, repository, commitId); var pusher = identityService.ReadIdentities(requestContext, new[] { commitManifest.PusherId }).FirstOrDefault(); foreach (var comment in thread.Comments) { var commenter = identityService.ReadIdentities(requestContext, new[] { comment.Author }).First(); var notification = new Notifications.CommitCommentNotification() { TeamProjectCollection = requestContext.ServiceHost.Name, PusherUniqueName = pusher?.UniqueName, UniqueName = commenter.UniqueName, DisplayName = comment.AuthorDisplayName, ProjectName = project.Name, RepoUri = repoUri, RepoName = repository.Name, CommitId = commitId, CommitUri = commitUri, Comment = TextHelper.Truncate(comment.Content, Settings.DiscussionCommentMaxLength), TeamNames = GetUserTeamsByProjectUri(requestContext, project.Uri, commenter.Descriptor), }; notifications.Add(notification); } } } else if (artifactId.ArtifactType.Equals("CodeReviewId", StringComparison.OrdinalIgnoreCase)) { Guid projectGuid; int pullRequestId; LegacyCodeReviewArtifactId.Decode(artifactId, out projectGuid, out pullRequestId); var pullRequestService = requestContext.GetService <ITeamFoundationGitPullRequestService>(); var pullRequest = pullRequestService.GetPullRequestDetails(requestContext, pullRequestId); var repositoryService = requestContext.GetService <TeamFoundationGitRepositoryService>(); using (TfsGitRepository repository = repositoryService.FindRepositoryById(requestContext, pullRequest.RepositoryId)) { var project = commonService.GetProject(requestContext, projectGuid); string repoUri = repository.GetRepositoryUri(requestContext); var creator = identityService.ReadIdentities(requestContext, new[] { pullRequest.Creator }).FirstOrDefault(); foreach (var comment in thread.Comments) { var commenter = identityService.ReadIdentities(requestContext, new[] { comment.Author }).First(); var notification = new Notifications.PullRequestCommentNotification() { TeamProjectCollection = requestContext.ServiceHost.Name, CreatorUniqueName = creator?.UniqueName, UniqueName = commenter.UniqueName, DisplayName = commenter.DisplayName, ProjectName = project.Name, RepoUri = repoUri, RepoName = repository.Name, PrId = pullRequest.PullRequestId, PrUrl = $"{repoUri}/pullrequest/{pullRequest.PullRequestId}#view=discussion", PrTitle = pullRequest.Title, TeamNames = GetUserTeamsByProjectUri(requestContext, project.Uri, commenter.Descriptor), SourceBranch = new GitRef(pullRequest.SourceBranchName), TargetBranch = new GitRef(pullRequest.TargetBranchName), Comment = TextHelper.Truncate(comment.Content, Settings.DiscussionCommentMaxLength) }; notifications.Add(notification); } } } else if (artifactId.ArtifactType.Equals("Changeset", StringComparison.OrdinalIgnoreCase)) { var versionControlService = requestContext.GetService <TeamFoundationVersionControlService>(); var uri = new VersionControlIntegrationUri(thread.ArtifactUri); var changesetId = int.Parse(uri.ArtifactName); var reader = versionControlService.QueryChangeset(requestContext, changesetId, true, false, false); var changeset = reader.Current <Changeset>(); var changesetUrl = hyperlinkService.GetChangesetDetailsUrl(changesetId).AbsoluteUri; string baseUrl = String.Format("{0}/{1}/", locationService.GetAccessMapping(requestContext, "PublicAccessMapping").AccessPoint, requestContext.ServiceHost.Name); string itemPath = string.Empty; string projectName = string.Empty; const string projectNamePattern = @"^\$\/([^\/]*)\/"; if (thread.Properties != null && thread.Properties.TryGetValue <string>("Microsoft.TeamFoundation.Discussion.ItemPath", out itemPath)) { changesetUrl += string.Format("#path={0}&discussionId={1}&_a=contents", Uri.EscapeDataString(itemPath), discussionId); Match match = Regex.Match(itemPath, projectNamePattern); if (match.Success) { projectName = match.Groups[1].Value; } } else { // This assumes changeset doesn't span multiple projects. var serverItem = changeset.Changes.FirstOrDefault()?.Item.ServerItem; if (serverItem != null) { Match match = Regex.Match(serverItem, projectNamePattern); if (match.Success) { projectName = match.Groups[1].Value; } } } var commiter = identityService.ReadIdentity(requestContext, IdentitySearchFactor.AccountName, changeset.Committer); foreach (var comment in thread.Comments) { var commenter = identityService.ReadIdentities(requestContext, new[] { comment.Author }).First(); var notification = new Notifications.ChangesetCommentNotification() { TeamProjectCollection = requestContext.ServiceHost.Name, CreatorUniqueName = commiter?.UniqueName, UniqueName = commenter.UniqueName, DisplayName = commenter.DisplayName, ProjectUrl = baseUrl + projectName, ProjectName = projectName, ChangesetId = changesetId, ChangesetUrl = changesetUrl, TeamNames = GetUserTeamsByProjectName(requestContext, projectName, commenter.Descriptor), SourcePath = itemPath, Comment = TextHelper.Truncate(comment.Content, Settings.DiscussionCommentMaxLength) }; notifications.Add(notification); } } } return(notifications); }
internal static void LogRequest(TeamFoundationRequestContext requestContext, PushNotification pushNotification, TfsGitRepository repository) { if (!PluginConfiguration.Instance.HasLog) { return; } var lines = new List <string>(); lines.Add(string.Format("Request from {0} for {1}" , requestContext.GetNameToDisplay() , requestContext.ServiceName )); lines.Add("Summary for " + requestContext.GetSummary()); lines.Add(string.Format("{6} #{0} on {1} repo {2} at {3} by {5} ({4})" , pushNotification.PushId , pushNotification.TeamProjectUri , pushNotification.RepositoryName , pushNotification.PushTime , pushNotification.AuthenticatedUserName , pushNotification.Pusher , requestContext.Method.Name )); lines.Add("- Included Commits:"); foreach (var commitHash in pushNotification.IncludedCommits) { var commit = repository.TryLookupObject(requestContext, commitHash) as TfsGitCommit; lines.Add(string.Format(" Commit {0}: {1} '{2}'" , commit.ObjectId.DisplayHash() , commit.GetCommitterName(requestContext) , commit.GetComment(requestContext) )); foreach (var parentCommit in commit.GetParents(requestContext)) { lines.Add(string.Format(" Parent {0}: {1} '{2}'" , parentCommit.ObjectId.DisplayHash() , parentCommit.GetCommitterName(requestContext) , parentCommit.GetComment(requestContext) )); } } lines.Add("- Ref Update Results:"); foreach (var refUpdate in pushNotification.RefUpdateResults) { lines.Add(string.Format(" on {0} {1}..{2} is {3} (succeeded: {4}) rejecter '{5}' message '{6}'" , refUpdate.Name , refUpdate.NewObjectId.DisplayHash() , refUpdate.OldObjectId.DisplayHash() , refUpdate.Status , refUpdate.Succeeded , refUpdate.RejectedBy , refUpdate.CustomMessage )); }//for File.AppendAllLines(PluginConfiguration.Instance.LogFile, lines); }
public abstract Validation CheckRule(TeamFoundationRequestContext requestContext, PushNotification pushNotification, TfsGitRepository repository);
public EventNotificationStatus ProcessEvent(TeamFoundationRequestContext requestContext, NotificationType notificationType, object notificationEventArgs, out int statusCode, out string statusMessage, out Microsoft.TeamFoundation.Common.ExceptionPropertyCollection properties) { statusCode = 0; statusMessage = string.Empty; properties = null; try { if (notificationType == NotificationType.Notification && notificationEventArgs is PushNotification) { Stopwatch timer = new Stopwatch(); timer.Start(); PushNotification pushNotification = notificationEventArgs as PushNotification; var repositoryService = requestContext.GetService <TeamFoundationGitRepositoryService>(); var commonService = requestContext.GetService <CommonStructureService>(); using (TfsGitRepository repository = repositoryService.FindRepositoryById(requestContext, pushNotification.RepositoryId)) { string repoName = pushNotification.RepositoryName; string projectName = commonService.GetProject(requestContext, pushNotification.TeamProjectUri).Name; string userName = pushNotification.AuthenticatedUserName.Replace(DOMAIN_PREFIX, ""); var lines = new List <string>(); string pushText = pushNotification.IsForceRequired(requestContext, repository) ? "FORCE push" : "push"; lines.Add(String.Format("{0} by {1} to {2}/{3}", pushText, userName, projectName, repoName)); var refNames = new Dictionary <byte[], List <string> >(new ByteArrayComparer()); var oldCommits = new HashSet <byte[]>(new ByteArrayComparer()); var unknowns = new List <RefUpdateResultGroup>(); // Associate refs (branch, ligtweight and annotated tag) with corresponding commit var refUpdateResultGroups = pushNotification.RefUpdateResults .Where(r => r.Succeeded) .GroupBy(r => r.NewObjectId, (key, items) => new RefUpdateResultGroup(key, items), new ByteArrayComparer()); foreach (var refUpdateResultGroup in refUpdateResultGroups) { byte[] newObjectId = refUpdateResultGroup.NewObjectId; byte[] commitId = null; if (newObjectId.IsZero()) { commitId = newObjectId; } else { TfsGitObject gitObject = repository.LookupObject(requestContext, newObjectId); if (gitObject.ObjectType == TfsGitObjectType.Commit) { commitId = newObjectId; } else if (gitObject.ObjectType == TfsGitObjectType.Tag) { var tag = (TfsGitTag)gitObject; var commit = tag.TryResolveToCommit(requestContext); if (commit != null) { commitId = commit.ObjectId; } } } if (commitId != null) { List <string> names; if (!refNames.TryGetValue(commitId, out names)) { names = new List <string>(); refNames.Add(commitId, names); } names.AddRange(RefsToStrings(refUpdateResultGroup.RefUpdateResults)); if (commitId.IsZero() || !pushNotification.IncludedCommits.Any(r => r.SequenceEqual(commitId))) { oldCommits.Add(commitId); } } else { unknowns.Add(refUpdateResultGroup); } } // Display new commits with refs foreach (byte[] commitId in pushNotification.IncludedCommits) { TfsGitCommit gitCommit = (TfsGitCommit)repository.LookupObject(requestContext, commitId); string line = CommitToString(requestContext, gitCommit, "commit", pushNotification, refNames); lines.Add(line); } // Display updated refs to old commits foreach (byte[] commitId in oldCommits) { string line = null; if (commitId.IsZero()) { line = String.Format("{0} deleted", String.Join("", refNames[commitId])); } else { TfsGitCommit gitCommit = (TfsGitCommit)repository.LookupObject(requestContext, commitId); line = CommitToString(requestContext, gitCommit, "->", pushNotification, refNames); } lines.Add(line); } // Display "unknown" refs foreach (var refUpdateResultGroup in unknowns) { byte[] newObjectId = refUpdateResultGroup.NewObjectId; TfsGitObject gitObject = repository.LookupObject(requestContext, newObjectId); string line = String.Format("{0} -> {1} {2}", RefsToString(refUpdateResultGroup.RefUpdateResults), gitObject.ObjectType, newObjectId.ToHexString()); lines.Add(line); } //Log(lines); List <string> sendLines = lines; if (lines.Count > MAX_LINES) { sendLines = lines.Take(MAX_LINES).ToList(); sendLines.Add(String.Format("{0} more line(s) suppressed.", lines.Count - MAX_LINES)); } Task.Run(() => SendToBot(sendLines)); } timer.Stop(); //Log("Time spent in ProcessEvent: " + timer.Elapsed); } } catch (Exception ex) { Log(ex.Message); Log(ex.StackTrace); } return(EventNotificationStatus.ActionPermitted); }
protected override IEnumerable <INotification> CreateNotifications(TeamFoundationRequestContext requestContext, PushNotification pushNotification, int maxLines) { var repositoryService = requestContext.GetService <TeamFoundationGitRepositoryService>(); var commonService = requestContext.GetService <CommonStructureService>(); var commitService = requestContext.GetService <TeamFoundationGitCommitService>(); var identityService = requestContext.GetService <TeamFoundationIdentityService>(); var identity = identityService.ReadIdentity(requestContext, IdentitySearchFactor.Identifier, pushNotification.Pusher.Identifier); var teamNames = GetUserTeamsByProjectUri(requestContext, pushNotification.TeamProjectUri, pushNotification.Pusher); using (TfsGitRepository repository = repositoryService.FindRepositoryById(requestContext, pushNotification.RepositoryId)) { var pushRow = new PushRow() { UniqueName = pushNotification.AuthenticatedUserName, DisplayName = identity.DisplayName, RepoName = pushNotification.RepositoryName, RepoUri = repository.GetRepositoryUri(requestContext), ProjectName = commonService.GetProject(requestContext, pushNotification.TeamProjectUri).Name, IsForcePush = settings.IdentifyForcePush ? pushNotification.IsForceRequired(requestContext, repository) : false }; var notification = new GitPushNotification(requestContext.ServiceHost.Name, pushRow.ProjectName, pushNotification.AuthenticatedUserName, pushRow.RepoName, teamNames, pushNotification.RefUpdateResults.Where(r => r.Succeeded).Select(r => new GitRef(r))); notification.Add(pushRow); notification.TotalLineCount++; var refLookup = new Dictionary <byte[], List <GitRef> >(new ByteArrayComparer()); var deletedRefs = new List <GitRef>(); var oldCommits = new HashSet <TfsGitCommit>(new TfsGitObjectEqualityComparer()); var unknowns = new List <TfsGitRefUpdateResult>(); // Associate refs (branch, lightweight and annotated tag) with corresponding commit foreach (var refUpdateResult in pushNotification.RefUpdateResults.Where(r => r.Succeeded)) { var newObjectId = refUpdateResult.NewObjectId; TfsGitCommit commit = null; if (newObjectId.IsZero()) { deletedRefs.Add(new GitRef(refUpdateResult)); continue; } TfsGitObject gitObject = repository.LookupObject(requestContext, newObjectId); if (gitObject.ObjectType == TfsGitObjectType.Commit) { commit = gitObject as TfsGitCommit; } else if (gitObject.ObjectType == TfsGitObjectType.Tag) { var tag = (TfsGitTag)gitObject; commit = tag.TryResolveToCommit(requestContext); } if (commit != null) { List <GitRef> refs; if (!refLookup.TryGetValue(commit.ObjectId, out refs)) { refs = new List <GitRef>(); refLookup.Add(commit.ObjectId, refs); } refs.Add(new GitRef(refUpdateResult)); if (!pushNotification.IncludedCommits.Any(r => r.SequenceEqual(commit.ObjectId))) { oldCommits.Add(commit); } } else { unknowns.Add(refUpdateResult); } } notification.TotalLineCount += pushNotification.IncludedCommits.Count() + oldCommits.Count + unknowns.Count; // Add new commits with refs foreach (var commitId in pushNotification.IncludedCommits.TakeWhile(c => notification.Count < maxLines)) { TfsGitCommit gitCommit = (TfsGitCommit)repository.LookupObject(requestContext, commitId); notification.Add(CreateCommitRow(requestContext, commitService, gitCommit, CommitRowType.Commit, pushNotification, refLookup)); } // Add updated refs to old commits foreach (TfsGitCommit gitCommit in oldCommits.OrderByDescending(c => c.GetCommitTime(requestContext)).TakeWhile(c => notification.Count < maxLines)) { notification.Add(CreateCommitRow(requestContext, commitService, gitCommit, CommitRowType.RefUpdate, pushNotification, refLookup)); } // Add deleted refs if any if (deletedRefs.Any() && notification.Count < maxLines) { notification.Add(new DeleteRow() { Refs = deletedRefs }); } // Add "unknown" refs foreach (var refUpdateResult in unknowns.TakeWhile(c => notification.Count < maxLines)) { var newObjectId = refUpdateResult.NewObjectId; TfsGitObject gitObject = repository.LookupObject(requestContext, newObjectId); notification.Add(new RefUpdateRow() { NewObjectId = newObjectId, ObjectType = gitObject.ObjectType, Refs = new[] { new GitRef(refUpdateResult) } }); } yield return(notification); } }
public override Validation CheckRule(TeamFoundationRequestContext requestContext, PushNotification pushNotification, TfsGitRepository repository) { var result = new Validation(); foreach (var refUpdateResult in pushNotification.RefUpdateResults) { // new or deleted refs have id==0 if (IsNullHash(refUpdateResult.OldObjectId) || IsNullHash(refUpdateResult.NewObjectId)) { continue; } TfsGitCommit gitCommit = repository.LookupObject(requestContext, refUpdateResult.NewObjectId) as TfsGitCommit; if (gitCommit == null) { continue; } string authorEmail = gitCommit.GetAuthorEmail(requestContext); if (!AuthorEmail.Any(pattern => Regex.IsMatch(authorEmail, pattern))) { result.Fails = true; result.ReasonCode = 2; result.ReasonMessage = string.Format( "Author email '{0}' on commit {1} is not admitted", authorEmail, gitCommit.ObjectId.DisplayHash()); break; } string committerEmail = gitCommit.GetCommitterEmail(requestContext); if (!CommitterEmail.Any(pattern => Regex.IsMatch(committerEmail, pattern))) { result.Fails = true; result.ReasonCode = 3; result.ReasonMessage = string.Format( "Committer email '{0}' on commit {1} is not admitted", authorEmail, gitCommit.ObjectId.DisplayHash()); break; } //if } //for changes return(result); }
public override Validation CheckRule(TeamFoundationRequestContext requestContext, PushNotification pushNotification, TfsGitRepository repository) { var result = new Validation(); long totalSize = 0; foreach (var commitId in pushNotification.IncludedCommits) { TfsGitCommit gitCommit = repository.LookupObject(requestContext, commitId) as TfsGitCommit; if (gitCommit == null) { continue; } long size = GetCommitSize(gitCommit, requestContext); totalSize += size; }//for // convert to MB totalSize = totalSize / (1024 * 1024); if (totalSize < this.Megabytes) { Logger.Log(string.Format( "Push request is {0} MB, below the {1} MB limit." , totalSize, this.Megabytes , "Limit Size")); } else { if (IsUserExempted(requestContext, pushNotification)) { Logger.Log(string.Format( "Push request is {0} MB, above or equal to the {1} MB limit, but user is exempted." , totalSize, this.Megabytes , "Limit Size")); } else { result.Fails = true; result.ReasonCode = 2; result.ReasonMessage = string.Format( "Push request is {0} MB, above or equal to the {1} MB limit: refused." , totalSize, this.Megabytes); } }//if return(result); }
public override Validation CheckRule(TeamFoundationRequestContext requestContext, PushNotification pushNotification, TfsGitRepository repository) { var result = new Validation(); // refuse any push result.Fails = true; result.ReasonCode = 99; result.ReasonMessage = string.Format( "Repository '{0}' is in read-only mode", pushNotification.RepositoryName); return(result); }
public override Validation CheckRule(TeamFoundationRequestContext requestContext, PushNotification pushNotification, TfsGitRepository repository) { var result = new Validation(); bool force = RequiresForcePush(pushNotification, requestContext, repository); if (force) { if (IsUserExempted(requestContext, pushNotification)) { Logger.Log(string.Format( "User {0} has explicit permission for {1}" , pushNotification.AuthenticatedUserName , "Forced Push")); } else { result.Fails = true; result.ReasonCode = 1; result.ReasonMessage = "Force Push policy fails for user " + pushNotification.AuthenticatedUserName + "."; } //if } //if return(result); }
public static bool IsForceRequired(this PushNotification pushNotification, TeamFoundationRequestContext requestContext, TfsGitRepository repository) { foreach (var refUpdateResult in pushNotification.RefUpdateResults.Where(r => r.Succeeded)) { // Don't bother with new or deleted refs if (refUpdateResult.OldObjectId.IsEmpty || refUpdateResult.NewObjectId.IsEmpty) { continue; } TfsGitObject gitObject = repository.LookupObject(requestContext, refUpdateResult.NewObjectId); if (gitObject.ObjectType != GitObjectType.Commit) { continue; } TfsGitCommit gitCommit = (TfsGitCommit)gitObject; if (!gitCommit.IsDescendantOf(requestContext, refUpdateResult.OldObjectId)) { return(true); } } return(false); }