77use App \Models \BuildUpdateFile ;
88use App \Models \Comment ;
99use App \Models \Project ;
10- use App \Models \RichBuildAlert ;
1110use App \Models \UploadFile ;
1211use App \Models \User ;
1312use App \Utils \DatabaseCleanupUtils ;
1615use App \Utils \TestingDay ;
1716use CDash \Database ;
1817use CDash \Model \Build ;
19- use CDash \Model \BuildFailure ;
2018use CDash \Model \BuildGroupRule ;
2119use CDash \Model \BuildRelationship ;
22- use CDash \ServiceContainer ;
2320use Illuminate \Http \JsonResponse ;
2421use Illuminate \Http \RedirectResponse ;
2522use Illuminate \Http \Request ;
@@ -867,264 +864,6 @@ public function build_file(int $build_id, int $file_id): StreamedResponse
867864 }, $ filename , $ headers , 'inline ' );
868865 }
869866
870- public function apiViewBuildError (): JsonResponse
871- {
872- $ pageTimer = new PageTimer ();
873-
874- if (!isset ($ _GET ['buildid ' ]) || !is_numeric ($ _GET ['buildid ' ])) {
875- abort (400 , 'Invalid buildid! ' );
876- }
877- $ this ->setBuildById ((int ) $ _GET ['buildid ' ]);
878-
879- $ eloquentBuild = EloquentBuild::findOrFail ((int ) $ this ->build ->Id );
880-
881- $ service = ServiceContainer::getInstance ();
882-
883- $ response = begin_JSON_response ();
884- $ response ['title ' ] = $ this ->project ->Name ;
885-
886- $ type = (int ) ($ _GET ['type ' ] ?? 0 );
887-
888- $ date = TestingDay::get ($ this ->project , $ this ->build ->StartTime );
889- get_dashboard_JSON ($ this ->project ->Name , $ date , $ response );
890-
891- $ menu = [];
892- if ($ this ->build ->GetParentId () > 0 ) {
893- $ menu ['back ' ] = 'index.php?project= ' . urlencode ($ this ->project ->Name ) . "&parentid= {$ this ->build ->GetParentId ()}" ;
894- } else {
895- $ menu ['back ' ] = 'index.php?project= ' . urlencode ($ this ->project ->Name ) . '&date= ' . $ date ;
896- }
897-
898- $ previous_buildid = $ this ->build ->GetPreviousBuildId ();
899- $ current_buildid = $ this ->build ->GetCurrentBuildId ();
900- $ next_buildid = $ this ->build ->GetNextBuildId ();
901-
902- $ menu ['previous ' ] = $ previous_buildid > 0 ? "viewBuildError.php?type= $ type&buildid= $ previous_buildid " : false ;
903- $ menu ['current ' ] = "viewBuildError.php?type= $ type&buildid= $ current_buildid " ;
904- $ menu ['next ' ] = $ next_buildid > 0 ? "viewBuildError.php?type= $ type&buildid= $ next_buildid " : false ;
905-
906- $ response ['menu ' ] = $ menu ;
907-
908- // Site
909- $ extra_build_fields = [
910- 'site ' => $ this ->build ->GetSite ()->name ,
911- ];
912-
913- // Update
914- if ($ eloquentBuild ->updateStep !== null ) {
915- $ revision = $ eloquentBuild ->updateStep ->revision ;
916- $ extra_build_fields ['revision ' ] = $ revision ;
917- } else {
918- $ revision = null ;
919- }
920-
921- // Build
922- $ response ['build ' ] = Build::MarshalResponseArray ($ this ->build , $ extra_build_fields );
923-
924- $ buildfailure = $ service ->get (BuildFailure::class);
925-
926- // Set the error
927- if ($ type === 0 ) {
928- $ response ['errortypename ' ] = 'Error ' ;
929- $ response ['nonerrortypename ' ] = 'Warning ' ;
930- $ response ['nonerrortype ' ] = 1 ;
931- } else {
932- $ response ['errortypename ' ] = 'Warning ' ;
933- $ response ['nonerrortypename ' ] = 'Error ' ;
934- $ response ['nonerrortype ' ] = 0 ;
935- }
936-
937- $ response ['parentBuild ' ] = $ this ->build ->IsParentBuild ();
938- $ response ['errors ' ] = [];
939- $ response ['numErrors ' ] = 0 ;
940-
941- if (isset ($ _GET ['onlydeltan ' ])) {
942- // Build error table
943- $ resolvedBuildErrors = $ this ->build ->GetResolvedBuildErrors ($ type );
944- if ($ resolvedBuildErrors !== false ) {
945- while ($ resolvedBuildError = $ resolvedBuildErrors ->fetch ()) {
946- $ this ->addErrorResponse (self ::marshalBuildError ($ resolvedBuildError , $ this ->project , $ revision ), $ response );
947- }
948- }
949-
950- // Build failure table
951- $ resolvedBuildFailures = $ this ->build ->GetResolvedBuildFailures ($ type );
952- foreach ($ resolvedBuildFailures as $ resolvedBuildFailure ) {
953- $ marshaledResolvedBuildFailure = self ::marshalBuildFailure ($ resolvedBuildFailure , $ this ->project , $ revision , false , $ buildfailure );
954-
955- if ($ this ->project ->DisplayLabels ) {
956- get_labels_JSON_from_query_results ('
957- SELECT text
958- FROM label, label2buildfailure
959- WHERE
960- label.id=label2buildfailure.labelid
961- AND label2buildfailure.buildfailureid=?
962- ORDER BY text ASC
963- ' , [(int ) $ resolvedBuildFailure ['id ' ]], $ marshaledResolvedBuildFailure );
964- }
965-
966- $ marshaledResolvedBuildFailure = array_merge ($ marshaledResolvedBuildFailure , [
967- 'stderr ' => $ resolvedBuildFailure ['stderror ' ],
968- 'stderrorrows ' => min (10 , substr_count ($ resolvedBuildFailure ['stderror ' ], "\n" ) + 1 ),
969- 'stdoutput ' => $ resolvedBuildFailure ['stdoutput ' ],
970- 'stdoutputrows ' => min (10 , substr_count ($ resolvedBuildFailure ['stdoutput ' ], "\n" ) + 1 ),
971- ]);
972-
973- $ this ->addErrorResponse ($ marshaledResolvedBuildFailure , $ response );
974- }
975- } else {
976- $ filter_error_properties = ['type ' => $ type ];
977-
978- if (isset ($ _GET ['onlydeltap ' ])) {
979- $ filter_error_properties ['newstatus ' ] = Build::STATUS_NEW ;
980- }
981-
982- // Build error table
983- $ buildErrors = $ this ->build ->GetErrors ($ filter_error_properties );
984-
985- foreach ($ buildErrors as $ error ) {
986- $ this ->addErrorResponse (self ::marshalBuildError ($ error , $ this ->project , $ revision ), $ response );
987- }
988-
989- // Build failure table
990- $ buildFailures = $ this ->build ->GetFailures (['type ' => $ type ]);
991-
992- foreach ($ buildFailures as $ fail ) {
993- $ failure = self ::marshalBuildFailure ($ fail , $ this ->project , $ revision , true , $ buildfailure );
994-
995- if ($ this ->project ->DisplayLabels ) {
996- $ labels = RichBuildAlert::findOrFail ((int ) $ fail ['id ' ])->labels ()->pluck ('text ' );
997- if ($ labels ->count () > 0 ) {
998- $ failure ['labels ' ] = $ labels ->toArray ();
999- }
1000- }
1001- $ this ->addErrorResponse ($ failure , $ response );
1002- }
1003- }
1004-
1005- if ($ this ->build ->IsParentBuild ()) {
1006- $ response ['numSubprojects ' ] = count (array_unique (array_map (fn ($ buildError ) => $ buildError ['subprojectid ' ], $ response ['errors ' ])));
1007- }
1008-
1009- $ pageTimer ->end ($ response );
1010- return response ()->json (cast_data_for_JSON ($ response ));
1011- }
1012-
1013- /**
1014- * @return array{
1015- * 'file': string,
1016- * 'directory': string,
1017- * }
1018- */
1019- private static function GetSourceFileFromBuildError (array $ data ): array
1020- {
1021- $ sourceFile = [];
1022-
1023- // Detect if the source directory has already been replaced by CTest
1024- // with /.../. If so, sourcefile is already a relative path from the
1025- // root of the source tree.
1026- if (str_contains ($ data ['stdoutput ' ], '/.../ ' )) {
1027- $ parts = explode ('/ ' , $ data ['sourcefile ' ]);
1028- $ sourceFile ['file ' ] = array_pop ($ parts );
1029- $ sourceFile ['directory ' ] = implode ('/ ' , $ parts );
1030- } else {
1031- $ sourceFile ['file ' ] = basename ($ data ['sourcefile ' ]);
1032- $ sourceFile ['directory ' ] = dirname ($ data ['sourcefile ' ]);
1033- }
1034-
1035- return $ sourceFile ;
1036- }
1037-
1038- // Ideally $data would be loaded into $this
1039- // need an id field?
1040- /**
1041- * Marshals the data of a particular build error into a serializable
1042- * friendly format.
1043- *
1044- * Requires the $data of a build error, the $project, and the buildupdate.revision.
1045- *
1046- * @return array<string,mixed>
1047- **/
1048- public static function marshalBuildError (array $ data , \CDash \Model \Project $ project , $ revision ): array
1049- {
1050- deepEncodeHTMLEntities ($ data );
1051-
1052- $ sourceFile = self ::GetSourceFileFromBuildError ($ data );
1053-
1054- // When building without launchers, CTest truncates the source dir to
1055- // /.../<project-name>/. Use this pattern to linkify compiler output.
1056- $ source_dir = "/\.\.\./[^/]+ " ;
1057-
1058- $ marshaled = [
1059- 'new ' => (int ) ($ data ['newstatus ' ] ?? -1 ),
1060- 'logline ' => (int ) $ data ['logline ' ],
1061- 'cvsurl ' => RepositoryUtils::get_diff_url ($ project ->Id , $ project ->CvsUrl ?? '' , $ sourceFile ['directory ' ], $ sourceFile ['file ' ], $ revision ),
1062- 'precontext ' => '' ,
1063- 'text ' => RepositoryUtils::linkify_compiler_output ($ project ->CvsUrl ?? '' , $ source_dir , $ revision , $ data ['stdoutput ' ]),
1064- 'postcontext ' => '' ,
1065- 'sourcefile ' => $ data ['sourcefile ' ],
1066- 'sourceline ' => $ data ['sourceline ' ],
1067- ];
1068-
1069- if (isset ($ data ['subprojectid ' ])) {
1070- $ marshaled ['subprojectid ' ] = $ data ['subprojectid ' ];
1071- $ marshaled ['subprojectname ' ] = $ data ['subprojectname ' ];
1072- }
1073-
1074- return $ marshaled ;
1075- }
1076-
1077- /**
1078- * Marshal a build failure, this includes the build failure arguments.
1079- **/
1080- public static function marshalBuildFailure ($ data , \CDash \Model \Project $ project , $ revision , $ linkifyOutput , $ buildfailure ): array
1081- {
1082- deepEncodeHTMLEntities ($ data );
1083-
1084- $ marshaled = array_merge ([
1085- 'language ' => $ data ['language ' ],
1086- 'sourcefile ' => $ data ['sourcefile ' ],
1087- 'targetname ' => $ data ['targetname ' ],
1088- 'outputfile ' => $ data ['outputfile ' ],
1089- 'outputtype ' => $ data ['outputtype ' ],
1090- 'workingdirectory ' => $ data ['workingdirectory ' ],
1091- 'exitcondition ' => $ data ['exitcondition ' ],
1092- ], $ buildfailure ->GetBuildFailureArguments ((int ) $ data ['id ' ]));
1093-
1094- $ marshaled ['stderror ' ] = $ data ['stderror ' ];
1095- $ marshaled ['stdoutput ' ] = $ data ['stdoutput ' ];
1096-
1097- if (isset ($ data ['sourcefile ' ])) {
1098- $ file = basename ($ data ['sourcefile ' ]);
1099- $ directory = dirname ($ data ['sourcefile ' ]);
1100-
1101- $ source_dir = RepositoryUtils::get_source_dir ($ project ->Id , $ project ->CvsUrl ?? '' , $ directory );
1102- if (str_starts_with ($ directory , $ source_dir )) {
1103- $ directory = substr ($ directory , strlen ($ source_dir ));
1104- }
1105-
1106- $ marshaled ['cvsurl ' ] = RepositoryUtils::get_diff_url ($ project ->Id ,
1107- $ project ->CvsUrl ?? '' ,
1108- $ directory ,
1109- $ file ,
1110- $ revision );
1111-
1112- if ($ source_dir !== null && $ linkifyOutput ) {
1113- $ marshaled ['stderror ' ] = RepositoryUtils::linkify_compiler_output ($ project ->CvsUrl ?? '' , $ source_dir ,
1114- $ revision , $ data ['stderror ' ]);
1115- $ marshaled ['stdoutput ' ] = RepositoryUtils::linkify_compiler_output ($ project ->CvsUrl ?? '' , $ source_dir ,
1116- $ revision , $ data ['stdoutput ' ]);
1117- }
1118- }
1119-
1120- if (isset ($ data ['subprojectid ' ])) {
1121- $ marshaled ['subprojectid ' ] = $ data ['subprojectid ' ];
1122- $ marshaled ['subprojectname ' ] = $ data ['subprojectname ' ];
1123- }
1124-
1125- return $ marshaled ;
1126- }
1127-
1128867 public function manageBuildGroup (): View
1129868 {
1130869 $ this ->setProjectById (request ()->integer ('projectid ' ));
@@ -1137,24 +876,6 @@ public function viewBuildGroup(): View
1137876 return $ this ->angular_view ('index ' );
1138877 }
1139878
1140- /**
1141- * Add a new (marshaled) error to the response.
1142- * Keeps track of the id necessary for frontend JS, and updates
1143- * the numErrors response key.
1144- *
1145- * @todo id should probably just be a unique id for the builderror?
1146- * builderror table currently has no integer that serves as a unique identifier.
1147- *
1148- * @param array<string,mixed> $response
1149- **/
1150- private function addErrorResponse (mixed $ data , array &$ response ): void
1151- {
1152- $ data ['id ' ] = $ response ['numErrors ' ];
1153- $ response ['numErrors ' ]++;
1154-
1155- $ response ['errors ' ][] = $ data ;
1156- }
1157-
1158879 public function apiBuildUpdateGraph (): JsonResponse
1159880 {
1160881 $ this ->setBuildById ((int ) ($ _GET ['buildid ' ] ?? -1 ));
0 commit comments