/// <summary> /// Filters all the likely causers from the list of changes since an issue was created /// </summary> /// <param name="Perforce">The perforce connection</param> /// <param name="Issue">The build issue</param> /// <param name="Changes">List of changes since the issue first occurred.</param> /// <returns>List of changes which are causers for the issue</returns> public virtual List <ChangeInfo> FindCausers(PerforceConnection Perforce, Issue Issue, IReadOnlyList <ChangeInfo> Changes) { List <ChangeInfo> Causers = new List <ChangeInfo>(); SortedSet <string> FileNamesWithoutPath = GetFileNamesWithoutPath(Issue.FileNames); if (FileNamesWithoutPath.Count > 0) { foreach (ChangeInfo Change in Changes) { DescribeRecord DescribeRecord = GetDescribeRecord(Perforce, Change); if (ContainsFileNames(DescribeRecord, FileNamesWithoutPath)) { Causers.Add(Change); } } } if (Causers.Count > 0) { return(Causers); } else { return(new List <ChangeInfo>(Changes)); } }
public override List <ChangeInfo> FindCausers(PerforceConnection Perforce, BuildHealthIssue Issue, IReadOnlyList <ChangeInfo> Changes) { SortedSet <string> FileNamesWithoutPath = new SortedSet <string>(StringComparer.Ordinal); foreach (string Identifier in Issue.Identifiers) { Match Match = Regex.Match(Identifier, "^[AUFS]([A-Z][A-Za-z_]*)::"); if (Match.Success) { FileNamesWithoutPath.Add(Match.Groups[1].Value + ".h"); FileNamesWithoutPath.Add(Match.Groups[1].Value + ".cpp"); } } if (FileNamesWithoutPath.Count > 0) { List <ChangeInfo> Causers = new List <ChangeInfo>(); foreach (ChangeInfo Change in Changes) { DescribeRecord DescribeRecord = GetDescribeRecord(Perforce, Change); if (ContainsFileNames(DescribeRecord, FileNamesWithoutPath)) { Causers.Add(Change); } } if (Causers.Count > 0) { return(Causers); } } return(base.FindCausers(Perforce, Issue, Changes)); }
public void CheckRequest_ShouldThrowWhenSchemaLanguageIsInvalid(string language) { var discovery = new Mock <Discovery>(); var processor = new DescribeRecordProcessorAccessor(discovery.Object); var request = new DescribeRecord() { schemaLanguage = (language != null ? new Uri(language) : null) }; Assert.Throws <OwsException>(() => processor.CheckRequest(request)); }
public void CheckRequest_ShouldThrowWhenOutputFormatIsInvalid(string format) { var discovery = new Mock <Discovery>(); var processor = new DescribeRecordProcessorAccessor(discovery.Object); var request = new DescribeRecord() { outputFormat = format }; Assert.Throws <OwsException>(() => processor.CheckRequest(request)); }
/// <summary> /// Determines if this change is a likely causer for an issue /// </summary> /// <param name="DescribeRecord">The change describe record</param> /// <param name="Fingerprint">Fingerprint for the issue</param> /// <returns>True if the change is a likely culprit</returns> protected static bool ContainsFileNames(DescribeRecord DescribeRecord, SortedSet <string> FileNamesWithoutPath) { foreach (DescribeFileRecord File in DescribeRecord.Files) { int Idx = File.DepotFile.LastIndexOf('/'); if (Idx != -1) { string FileName = File.DepotFile.Substring(Idx + 1); if (FileNamesWithoutPath.Contains(FileName)) { return(true); } } } return(false); }
/// <summary> /// Tests whether a change is a code change /// </summary> /// <param name="Perforce">The Perforce connection</param> /// <param name="Change">The change to query</param> /// <returns>True if the change is a code change</returns> public bool ContainsAnyFileWithExtension(PerforceConnection Perforce, ChangeInfo Change, string[] Extensions) { DescribeRecord Record = GetDescribeRecord(Perforce, Change); foreach (DescribeFileRecord File in Record.Files) { foreach (string Extension in Extensions) { if (File.DepotFile.EndsWith(Extension, StringComparison.OrdinalIgnoreCase)) { return(true); } } } return(false); }
public void UpdateRecord(DescribeRecord record) { IClientProfile profile = DefaultProfile.GetProfile("cn-hangzhou", accessKey, accessSecret); DefaultAcsClient client = new DefaultAcsClient(profile); var request = new UpdateDomainRecordRequest(); request.RecordId = record.RecordId; request.RR = record.RR; request.Type = record.Type; request.Value = record.Value; try { var response = client.GetAcsResponse(request); } catch (ServerException e) { Console.WriteLine(e); } catch (ClientException e) { Console.WriteLine(e); } }
/// <summary> /// Filters all the likely causers from the list of changes since an issue was created /// </summary> /// <param name="Perforce">The perforce connection</param> /// <param name="Fingerprint">Fingerprint for the issue</param> /// <param name="Changes">List of changes since the issue first occurred.</param> /// <returns>List of changes which are causers for the issue</returns> public virtual List <ChangeInfo> FindCausers(PerforceConnection Perforce, BuildHealthIssue Issue, IReadOnlyList <ChangeInfo> Changes) { SortedSet <string> FileNamesWithoutPath = GetFileNamesWithoutPath(Issue.FileNames); List <ChangeInfo> Causers = new List <ChangeInfo>(); foreach (ChangeInfo Change in Changes) { DescribeRecord Description = Perforce.Describe(Change.Record.Number).Data; if (ContainsFileNames(Description, FileNamesWithoutPath)) { Causers.Add(Change); } } if (Causers.Count > 0) { return(Causers); } else { return(new List <ChangeInfo>(Changes)); } }
/// <summary> /// Wraps P4 describe /// </summary> /// <param name="Changelists">List of changelist numbers to query full descriptions for</param> /// <param name="DescribeRecords">List of records we found. One for each changelist number. These will be sorted from oldest to newest.</param> /// <param name="AllowSpew"></param> /// <returns>True if everything went okay</returns> public bool DescribeChangelists(List<int> Changelists, out List<DescribeRecord> DescribeRecords, bool AllowSpew = true) { DescribeRecords = new List<DescribeRecord>(); CheckP4Enabled(); try { // Change 234641 by This.User@WORKSPACE-C2Q-67_Dev on 2008/05/06 10:32:32 // // Desc Line 1 // // Affected files ... // // ... //depot/UnrealEngine3/Development/Src/Engine/Classes/ArrowComponent.uc#8 edit // ... //depot/UnrealEngine3/Development/Src/Engine/Classes/DecalActorBase.uc#4 edit string Output; string CommandLine = "-s"; // Don't automatically diff the files // Add changelists to the command-line foreach( var Changelist in Changelists ) { CommandLine += " " + Changelist.ToString(); } if (!LogP4Output(out Output, "describe " + CommandLine, null, AllowSpew)) { return false; } int ChangelistIndex = 0; var Lines = Output.Split(new string[] { Environment.NewLine }, StringSplitOptions.None); for (var LineIndex = 0; LineIndex < Lines.Length; ++LineIndex) { var Line = Lines[ LineIndex ]; // If we've hit a blank line, then we're done if( String.IsNullOrEmpty( Line ) ) { break; } string MatchChange = "Change "; string MatchOn = " on "; string MatchBy = " by "; int ChangeAt = Line.IndexOf(MatchChange); int OnAt = Line.IndexOf(MatchOn); int ByAt = Line.IndexOf(MatchBy); int AtAt = Line.IndexOf("@"); if (ChangeAt == 0 && OnAt > ChangeAt && ByAt < OnAt) { var ChangeString = Line.Substring(ChangeAt + MatchChange.Length, ByAt - ChangeAt - MatchChange.Length); var CurrentChangelist = Changelists[ ChangelistIndex++ ]; if (!ChangeString.Equals( CurrentChangelist.ToString())) { throw new AutomationException("Was expecting changelists to be reported back in the same order we asked for them (CL {0} != {1})", ChangeString, CurrentChangelist.ToString()); } var DescribeRecord = new DescribeRecord(); DescribeRecords.Add( DescribeRecord ); DescribeRecord.CL = CurrentChangelist; DescribeRecord.User = Line.Substring(ByAt + MatchBy.Length, AtAt - ByAt - MatchBy.Length); DescribeRecord.Header = Line; ++LineIndex; if( LineIndex >= Lines.Length ) { throw new AutomationException("Was expecting a change summary to appear after Change header output from P4, but there were no more lines to read"); } Line = Lines[ LineIndex ]; if( !String.IsNullOrEmpty( Line ) ) { throw new AutomationException("Was expecting blank line after Change header output from P4"); } // Summary ++LineIndex; for( ; LineIndex < Lines.Length; ++LineIndex ) { Line = Lines[ LineIndex ]; if( String.IsNullOrEmpty( Line ) ) { // Summaries end with a blank line (no tabs) break; } // Summary lines are supposed to begin with a single tab character (even empty lines) if( Line[0] != '\t' ) { throw new AutomationException("Was expecting every line of the P4 changes summary to start with a tab character"); } // Remove the tab var SummaryLine = Line.Substring( 1 ); // Add a CR if we already had some summary text if( !String.IsNullOrEmpty( DescribeRecord.Summary ) ) { DescribeRecord.Summary += "\n"; } // Append the summary line! DescribeRecord.Summary += SummaryLine; } ++LineIndex; if( LineIndex >= Lines.Length ) { throw new AutomationException("Was expecting 'Affected files' to appear after the summary output from P4, but there were no more lines to read"); } // If the summary ends with an empty newline, it doesn't seem to be prefixed with a tab while (LineIndex < Lines.Length && Lines[LineIndex].Length == 0) { LineIndex++; } Line = Lines[ LineIndex ]; string MatchAffectedFiles = "Affected files"; int AffectedFilesAt = Line.IndexOf(MatchAffectedFiles); if( AffectedFilesAt == 0 ) { ++LineIndex; if( LineIndex >= Lines.Length ) { throw new AutomationException("Was expecting a list of files to appear after Affected Files header output from P4, but there were no more lines to read"); } Line = Lines[ LineIndex ]; if( !String.IsNullOrEmpty( Line ) ) { throw new AutomationException("Was expecting blank line after Affected Files header output from P4"); } // Files ++LineIndex; for( ; LineIndex < Lines.Length; ++LineIndex ) { Line = Lines[ LineIndex ]; if( String.IsNullOrEmpty( Line ) ) { // Summaries end with a blank line (no tabs) break; } // File lines are supposed to begin with a "... " string if( !Line.StartsWith( "... " ) ) { throw new AutomationException("Was expecting every line of the P4 describe files to start with a tab character"); } // Remove the "... " prefix var FilesLine = Line.Substring( 4 ); var DescribeFile = new DescribeRecord.DescribeFile(); DescribeRecord.Files.Add( DescribeFile ); // Find the revision # var RevisionNumberAt = FilesLine.LastIndexOf( "#" ) + 1; var ChangeTypeAt = 1 + FilesLine.IndexOf( " ", RevisionNumberAt ); DescribeFile.File = FilesLine.Substring( 0, RevisionNumberAt - 1 ); string RevisionString = FilesLine.Substring( RevisionNumberAt, ChangeTypeAt - RevisionNumberAt ); DescribeFile.Revision = int.Parse( RevisionString ); DescribeFile.ChangeType = FilesLine.Substring( ChangeTypeAt ); } } else { throw new AutomationException("Output of 'p4 describe' was not formatted how we expected. Could not find 'Affected files' in the output line: " + Line); } DescribeRecord.UserEmail = UserToEmail(DescribeRecord.User); } else { throw new AutomationException("Output of 'p4 describe' was not formatted how we expected. Could not find 'Change', 'on' and 'by' in the output line: " + Line); } } } catch (Exception) { return false; } DescribeRecords.Sort((A, B) => DescribeRecord.Compare(A, B)); return true; }
public static int Compare(DescribeRecord A, DescribeRecord B) { return (A.CL < B.CL) ? -1 : (A.CL > B.CL) ? 1 : 0; }
public new void CheckRequest(DescribeRecord request) { base.CheckRequest(request); }
/// <summary> /// Wraps P4 describe /// </summary> /// <param name="Changelist">Changelist numbers to query full descriptions for</param> /// <param name="DescribeRecord">Describe record for the given changelist.</param> /// <param name="AllowSpew"></param> /// <returns>True if everything went okay</returns> public bool DescribeChangelist(int Changelist, out DescribeRecord DescribeRecord, bool AllowSpew = true) { List<DescribeRecord> DescribeRecords; if(!DescribeChangelists(new List<int>{ Changelist }, out DescribeRecords, AllowSpew)) { DescribeRecord = null; return false; } else if(DescribeRecords.Count != 1) { DescribeRecord = null; return false; } else { DescribeRecord = DescribeRecords[0]; return true; } }